ES6 Modules : Importing a module in an Angular component - javascript

I have an ES6 module where I am exporting a library. I want to be able to use this module in an Angular component. I cannot have the library files locally within my Angular app, neither can I publish the library as an NPM package.
Can I host the module in a dev server, and use the server URL to import the module in my Angular component?
I tried things like
component.ts
import * as lib from "...url";
or adding this in index.html
<script src = "..url"/>
Neither of them have worked. What can I try next?

Related

Can I dynamically import a JS module that uses rxjs into an Angular App

I have built an application with Angular 12.
I have a JS module called dynamic_module.js which is not available at build time which I want to import and use in the app. However, dynamic_module.js uses rxjs and other imports - all of which are already used in the Angular application and so included in the built webpack. dynamic_module is not an Angular / webpack artifact or anything complicated - it is a simple JavaScript file located on the same server but not available at build time .
When I try to import "dynamic_module.js" using the import(<path_to_dynamic_module.js> ) function - (I'm assuming this method is hi-jacked by webpack) I get an error:
"Error: Cannot find module '<path_to_dynamic_module.js>' ".
I expected this because the dynamic_module.js is not available when the app was built.
So, I tried the method of inserting a <script> element into the header -
e.g. <script type="module" src="<url_of_dynamic_module.js>"></script>
this loads the module but reports the error :
Failed to resolve module specifier "rxjs". Relative
references must start with either "/", "./", or "../".
I also tried this without the import of rxjs in the module, and it works ok.
And if I try using SystemJS with the babel transpiler and try to import the dynamic_module.js, I get an error when System JS tries to load the rxjs module it goes to http.
Error: Fetch error: 404 Not Found Instantiating
http://localhost:4400/rxjs
This also works when the import is removed from dynamic_module.js.
My question is : Can modules dynamically loaded with SystemJS (or any other method) import other modules that are already loaded by webpack - without duplication or reloading via http?
If this is not possible, I could make all the necessary module files available via http for SystemJS to load (I have done this with the 'babel' transpiler modules for SystemJS) . Would that cause two copies of the modules (ie. rxjs in this example) to be loaded into the browser - could this be a serious problem (space/performance/clashes ...)?
Here is a very simple example of the module - this can load by any method if the import is removed, but fails in if the import is included.
dynamic_module.js
import { Observable} from 'rxjs';
export class MyClass{
hello( msg ) {
console.log('[MODULE] Hello World');
console.log(msg);
}
}
Thanks for any advice!
Ok, after some research I have solved my problem:
Let me describe concisely what the issue I had was:
I was trying to import a module (dynamic_module.js) into an Angular
application at run time,
that module had a dependency on a module that was already bundled in
the Angular webpack (rxjs)
I used SystemJS to import my dynamic module
SystemJS tried to resolve my dynamic_module's dependencies by
reloading modules from the server.
I felt that this was unnecessary because the modules were already present in the client application - and anyway, the http requests failed because the dependencies were not to be found where it was looking for them.
The solution is to let SystemJS know in advance that the dependencies are already available. This is done using the SystemJS.set() method: for example in my case the key steps were:
import * as rxjs from "rxjs";
SystemJS.set('rxjs', SystemJS.newModule(rxjs));
SystemJS.import( <url_of_module> ).then( module=>.....});

External Dependencies not working in Nav.svelte

I am trying to load sv-bootstrap-dropdown module in nav.svelte component but I am getting the error <Dropdown> is not a valid SSR component. You may need to review your build config to ensure that dependencies are compiled, rather than imported as pre-compiled modules. After that I tried to install that as devDependency but than I was getting the error that Cannot read property remove of undefined. This gets generated itself in the server js file under the sapper folder
When working with svelte and sapper you to have think about 2 types of rendering : client side rendering (sveltjs, js) and server side rendering (SSR), it's sapper (nodejs or expressjs), there are a few ways to handle this, but according to the document of dependency you are using :
for SSR you consider to import like this:
import {
Carousel,
CarouselControl,
CarouselIndicators,
CarouselItem,
CarouselCaption
} from 'sveltestrap/src';
solve it by importing from the src folder of the package.

How is the Angular framework loaded into an application with Angular CLI?

I'm converting an existing AngularJS application to a hybrid application, to begin incrementally upgrading it to Angular 4. I want to understand how Angular 4 needs to be referenced in the existing AngularJS. In the existing AngularJS application, it's clear how the AngularJS framework is being loaded - it's simply an included script file:
<script src="/angular/angular.js"></script>
To familiarise myself with an up to date Angular version, I've created a separate 'quickstart' Angular 5 application using the Angular quickstart guide at https://angular.io/guide/quickstart, and I can run it using:
ng serve --open
When I look at the project files though, I'm not seeing where the angular framework is actually being loaded. There is no script being included anywhere in the src/index.html file for that application, it simply declares an directive for a component (app.component.ts) that looks like this:
import { Component } from '#angular/core';
#Component({
selector: 'app-root',
templateUrl: './app.component.html',
styleUrls: ['./app.component.css']
})
export class AppComponent {
title = 'Test Angular 5 app';
}
Where does the import actually import from? The Angular documentation says about the index.html file that it is:
The main HTML page that is served when someone visits your site. Most
of the time you'll never need to edit it. The CLI automatically adds
all js and css files when building your app so you never need to add
any or tags here manually.
So what is happening here? How is #angular/core actually being referenced?
When using Angular CLI, we have a lot of moving parts. To really understand what's happening, we should review some of the core technologies used in Angular CLI as they relate to output files and module resolution:
TypeScript -- will transpile your TypeScript code to ES5 or ES6 (most commonly ES5). The transpiled code will use CommonJS modules by default if the target is ES5. If the target is ES6, then ES6 modules will be used.
Webpack -- will take your transpiled TypeScript code and build a dependency graph of your import / exports based on the entry points defined in webpack.config.js. This dependency graph will include all of your modules and it will package these modules into 1+ bundles, depending on the configuration. This is the step where the #angular/core dependency (which lives in node_modules/#angular/core) is processed by Webpack and added to a bundle that can be accessed at runtime.
You can load the generated bundles into the page by including the generated files in your HTML. In the case of JS files, you load them using the script tag like you did with AngularJS.
Because we are using Angular CLI, there are a lot of configurations within Webpack that are set up by default, so we will have multiple generated bundles.
I just created an empty Angular CLI project and inspected the HTML to see the 5 generated bundles:
At the core of the complexity when comparing Angular project files with AngularJS files is that Angular code is transformed through multiple build steps, while AngularJS code is normally used out-of-the-box with ES5. If you were to add Webpack and TypeScript to your AngularJS build, you would see something very similar to the Angular output.
Where is Webpack Configured in Angular CLI?
Under the hood, Angular CLI uses Webpack to build your project and bundle your files.
The Angular team chose not to expose a configurable Webpack configuration file for Angular CLI, but they did add ng eject, which generates a webpack.config.js that matches the Webpack build of your project. The downside of ejecting is that you will no longer use ng serve to serve your project. Instead, you'll use npm run build && npm run start (you'll see these scripts added to your package.json after you eject), which will build and serve your project based on the generated webpack.config.js file.
This feature is essential if you need to make custom modifications to the default Webpack build.
Read more about ng eject here.
Where are the generated bundles?
If you are using ng serve, you won't see any of your generated files because these are being served from memory and not from disk (to speed up development when files are constantly changing), so your generated files are not located in any folder.
If you want to see your generated files, you can run ng build, which will create a dist folder with the index.html and associated assets/bundles.
Note that by default, all commands that build or serve your project will delete your dist folder unless you pass the --no-delete-output-path when building/serving.
You need to understand how imports and exports work in TypeScript
From TypeScript Docs
Exporting a declaration
Any declaration (such as a variable, function, class, type alias, or
interface) can be exported by adding the export keyword.
Validation.ts
export interface StringValidator {
isAcceptable(s: string): boolean;
}
ZipCodeValidator.ts
export const numberRegexp = /^[0-9]+$/;
export class ZipCodeValidator implements StringValidator {
isAcceptable(s: string) {
return s.length === 5 && numberRegexp.test(s);
}
}
Export statements
Export statements are handy when exports need to be renamed for
consumers, so the above example can be written as:
ZipCodeValidator.ts
class ZipCodeValidator implements StringValidator {
isAcceptable(s: string) {
return s.length === 5 && numberRegexp.test(s);
}
}
export { ZipCodeValidator };
export { ZipCodeValidator as mainValidator };
Import
Importing is just about as easy as exporting from a module. Importing
an exported declaration is done through using one of the import forms
below:
Import a single export from a module
import { ZipCodeValidator } from "./ZipCodeValidator";
let myValidator = new ZipCodeValidator();
imports can also be renamed
import { ZipCodeValidator as ZCV } from "./ZipCodeValidator";
let myValidator = new ZCV();
Import the entire module into a single variable, and use it to access the module exports
import * as validator from "./ZipCodeValidator";
let myValidator = new validator.ZipCodeValidator();
Since you followed the Angular quickstart guide you must have used npm which is used to install your modules and dependencies.
If you read angular.io/npm
#angular/core: Critical runtime parts of the framework needed by every
application. Includes all metadata decorators, Component, Directive,
dependency injection, and the component lifecycle hooks.
And by default npm stores all your dependencies in node_modules directory.
So you are importing Component from #angular/core which lives inside node_modules directory.

Angular 1.x ES6 Webpack include 3rd party libraries

I am developing an app using starter project : https://github.com/shprink/angular1.4-ES6-material-webpack-boilerplate.
I am stuck when I need to use 3rd party library.
I want to use js-yaml https://github.com/nodeca/js-yaml
I try to add it in my angular service:
import jsyaml from '../../node_modules/js-yaml/bin/js-yaml.js';
But I get error:
bundle-0d6476.js:75756 Uncaught Error: Cannot find module "../../node_modules/js-yaml/bin/js-yaml.js"
How do I solve this?
Check the docs on resolving modules. To import modules from node_modules, specify the path omitting everything up to and including node_modules. Thus, import jsyaml from 'js-yaml/bin/js-yaml.js' should work.

JSPM : importing SCSS with SystemJS in Angular2/TypeScript project doesn't works

Context
I'm working on a project using Angular2, TS and SystemJS. I've built a simple module loader using SystemJS which allows me to import 'custom' modules like this :
import { NavComponent } from "component#nav";
Maybe it'll be important.
Goal
I would like to import .scss files inside my angular components to be able to do things like that :
#Component({
selector: 'app-view',
styles: [ require('path/to/mainScss/file.scss') ],
template: //...
})
Issue
I've found some examples using webpack but I can't get this works. During searching, I've found this module. It can be interesting because it uses SystemJS like me and I don't have to add webpack to my project.
So I've decided to use it (and I'm not sure if it's possible to use webpack and SystemJS at the same time. require was undefined). I didn't know jspm before using this module, I've always used npm. So I've installed jspm locally (relative to my project) and globally and I've installed the module.
Then, inside a component : import './styles/importer.scss!';. And I get an error here.
Error: SyntaxError: Unexpected token <. I know that this error happens when SystemJS failed to load a module but I can't figure out why.
Why ?!
Why am I trying to do that ?
My module loader allows me to write some modules in separate folders (named like this namepace#name). I can add those folders inside another one named modules/ and then enable/disable modules by editing a configuration file.
So I want my .scss files to be loaded only if a module is enabled. That's why I want to include my sass inside an Angular component. That way, it'll be loaded only if the component is loaded.

Categories