Currently I'm working on a project which is being hosted on a clients server. For new 'modules' there is no intention to recompile the entire application. That said, the client wants to update the router/lazy loaded modules in runtime. I've tried several things out but I can't get it to work. I was wondering if any of you knows what I could still try or what I missed.
One thing I noticed, most of the resources I tried, using angular cli, are being bundled into seperate chunks by webpack by default when building the application. Which seems logical as it makes use of the webpack code splitting. but what if the module is not known yet at compile time (but a compiled module is stored somewhere on a server)? The bundling does not work because it can't find the module to import. And Using SystemJS will load up UMD modules whenever found on the system, but are also bundled in a seperate chunk by webpack.
Some resources I already tried;
dynamic-remote-component-loader
module-loading
Loading modules from different server at runtime
How to load dynamic external components into Angular application
Implementing a plugin architecture / plugin system / pluggable framework in Angular 2, 4, 5, 6
Angular 5 - load modules (that are not known at compile time) dynamically at run-time
https://medium.com/#nikolasleblanc/building-an-angular-4-component-library-with-the-angular-cli-and-ng-packagr-53b2ade0701e
Some several other relating this topic.
Some code I already tried and implement, but not working at this time;
Extending router with normal module.ts file
this.router.config.push({
path: "external",
loadChildren: () =>
System.import("./module/external.module").then(
module => module["ExternalModule"],
() => {
throw { loadChunkError: true };
}
)
});
Normal SystemJS Import of UMD bundle
System.import("./external/bundles/external.umd.js").then(modules => {
console.log(modules);
this.compiler.compileModuleAndAllComponentsAsync(modules['External'])
.then(compiled => {
const m = compiled.ngModuleFactory.create(this.injector);
const factory = compiled.componentFactories[0];
const cmp = factory.create(this.injector, [], null, m);
});
});
Import external module, not working with webpack (afaik)
const url = 'https://gist.githubusercontent.com/dianadujing/a7bbbf191349182e1d459286dba0282f/raw/c23281f8c5fabb10ab9d144489316919e4233d11/app.module.ts';
const importer = (url:any) => Observable.fromPromise(System.import(url));
console.log('importer:', importer);
importer(url)
.subscribe((modules) => {
console.log('modules:', modules, modules['AppModule']);
this.cfr = this.compiler
.compileModuleAndAllComponentsSync(modules['AppModule']);
console.log(this.cfr,',', this.cfr.componentFactories[0]);
this.external.createComponent(this.cfr.componentFactories[0], 0);
});
Use SystemJsNgModuleLoader
this.loader.load('app/lazy/lazy.module#LazyModule')
.then((moduleFactory: NgModuleFactory<any>) => {
console.log(moduleFactory);
const entryComponent = (<any>moduleFactory.moduleType).entry;
const moduleRef = moduleFactory.create(this.injector);
const compFactory = moduleRef.componentFactoryResolver
.resolveComponentFactory(entryComponent);
});
Tried loading a module made with rollup
this.http.get(`./myplugin/${metadataFileName}`)
.map(res => res.json())
.map((metadata: PluginMetadata) => {
// create the element to load in the module and factories
const script = document.createElement('script');
script.src = `./myplugin/${factoryFileName}`;
script.onload = () => {
//rollup builds the bundle so it's attached to the window
//object when loaded in
const moduleFactory: NgModuleFactory<any> =
window[metadata.name][metadata.moduleName + factorySuffix];
const moduleRef = moduleFactory.create(this.injector);
//use the entry point token to grab the component type that
//we should be rendering
const compType = moduleRef.injector.get(pluginEntryPointToken);
const compFactory = moduleRef.componentFactoryResolver
.resolveComponentFactory(compType);
// Works perfectly in debug, but when building for production it
// returns an error 'cannot find name Component of undefined'
// Not getting it to work with the router module.
}
document.head.appendChild(script);
}).subscribe();
Example with SystemJsNgModuleLoader only works when the Module is already provided as 'lazy' route in the RouterModule of the app (which turns it into a chunk when built with webpack)
I found a lot of discussion about this topic on StackOverflow here and there and provided solutions seem really good of loading modules/components dynamically if known up front. but none is fitting for our use case of the project. Please let me know what I can still try or dive into.
Thanks!
EDIT: I've found; https://github.com/kirjs/angular-dynamic-module-loading and will give this a try.
UPDATE: I've created a repository with an example of loading modules dynamically using SystemJS (and using Angular 6); https://github.com/lmeijdam/angular-umd-dynamic-example
I was facing the same problem. As far as I understand it until now:
Webpack puts all resources in a bundle and replaces all System.import with __webpack_require__. Therefore, if you want to load a module dynamically at runtime by using SystemJsNgModuleLoader, the loader will search for the module in the bundle. If the module does not exist in the bundle, you will get an error. Webpack is not going to ask the server for that module. This is a problem for us, since we want to load a module that we do not know at build/compile time.
What we need is loader that will load a module for us at runtime (lazy and dynamic). In my example, I am using SystemJS and Angular 6 / CLI.
Install SystemJS: npm install systemjs –save
Add it to angular.json: "scripts": [ "node_modules/systemjs/dist/system.src.js"]
app.component.ts
import { Compiler, Component, Injector, ViewChild, ViewContainerRef } from '#angular/core';
import * as AngularCommon from '#angular/common';
import * as AngularCore from '#angular/core';
declare var SystemJS;
#Component({
selector: 'app-root',
template: '<button (click)="load()">Load</button><ng-container #vc></ng-container>'
})
export class AppComponent {
#ViewChild('vc', {read: ViewContainerRef}) vc;
constructor(private compiler: Compiler,
private injector: Injector) {
}
load() {
// register the modules that we already loaded so that no HTTP request is made
// in my case, the modules are already available in my bundle (bundled by webpack)
SystemJS.set('#angular/core', SystemJS.newModule(AngularCore));
SystemJS.set('#angular/common', SystemJS.newModule(AngularCommon));
// now, import the new module
SystemJS.import('my-dynamic.component.js').then((module) => {
this.compiler.compileModuleAndAllComponentsAsync(module.default)
.then((compiled) => {
let moduleRef = compiled.ngModuleFactory.create(this.injector);
let factory = compiled.componentFactories[0];
if (factory) {
let component = this.vc.createComponent(factory);
let instance = component.instance;
}
});
});
}
}
my-dynamic.component.ts
import { NgModule, Component } from '#angular/core';
import { CommonModule } from '#angular/common';
import { Other } from './other';
#Component({
selector: 'my-dynamic-component',
template: '<h1>Dynamic component</h1><button (click)="LoadMore()">LoadMore</button>'
})
export class MyDynamicComponent {
LoadMore() {
let other = new Other();
other.hello();
}
}
#NgModule({
declarations: [MyDynamicComponent],
imports: [CommonModule],
})
export default class MyDynamicModule {}
other.component.ts
export class Other {
hello() {
console.log("hello");
}
}
As you can see, we can tell SystemJS what modules already exist in our bundle. So we do not need to load them again (SystemJS.set). All other modules that we import in our my-dynamic-component (in this example other) will be requested from the server at runtime.
I've used the https://github.com/kirjs/angular-dynamic-module-loading solution with Angular 6's library support to create an application I shared on Github. Due to company policy it needed to be taken offline. As soon as discussions are over regarding the example project source I will share it on Github!
UPDATE: repo can be found ; https://github.com/lmeijdam/angular-umd-dynamic-example
I have tested in Angular 6, below solution works for dynamically loading a module from an external package or an internal module.
1. If you want to dynamically load a module from a library project or a package:
I have a library project "admin" (or you can use a package) and an application project "app".
In my "admin" library project, I have AdminModule and AdminRoutingModule.
In my "app" project:
a. Make change in tsconfig.app.json:
"compilerOptions": {
"module": "esNext",
},
b. In app-routing.module.ts:
const routes: Routes = [
{
path: 'admin',
loadChildren: async () => {
const a = await import('admin')
return a['AdminModule'];
}
},
{
path: '',
redirectTo: '',
pathMatch: 'full'
}
];
#NgModule({
imports: [RouterModule.forRoot(routes)],
exports: [RouterModule]
})
export class AppRoutingModule {
}
2. if you want to load a module from the same project.
There are 4 different options:
a. In app-routing.module.ts:
const routes: Routes = [
{
path: 'example',
/* Options 1: Use component */
// component: ExampleComponent, // Load router from component
/* Options 2: Use Angular default lazy load syntax */
loadChildren: './example/example.module#ExampleModule', // lazy load router from module
/* Options 3: Use Module */
// loadChildren: () => ExampleModule, // load router from module
/* Options 4: Use esNext, you need to change tsconfig.app.json */
/*
loadChildren: async () => {
const a = await import('./example/example.module')
return a['ExampleModule'];
}
*/
},
{
path: '',
redirectTo: '',
pathMatch: 'full'
}
];
#NgModule({
imports: [RouterModule.forRoot(routes)],
exports: [RouterModule]
})
export class AppRoutingModule {
}
``
Do it with angular 6 library and rollup do the trick. I've just experiment with it and i can share standalone angular AOT module with the main app without rebuild last.
In angular library set angularCompilerOptions.skipTemplateCodegen to false and after build library you will get module factory.
After that build an umd module with rollup like this:
rollup dist/plugin/esm2015/lib/plugin.module.ngfactory.js --file src/assets/plugin.module.umd.js --format umd --name plugin
Load text source umd bundle in main app and eval it with module context
Now you can access to ModuleFactory from exports object
Here https://github.com/iwnow/angular-plugin-example you can find how develop plugin with standalone building and AOT
I believe this is possible using SystemJS to load a UMD bundle if you build and run your main application using webpack. I used a solution that uses ng-packagr to build a UMD bundle of the dynamic plugin/addon module. This github demonstrates the procedure described:
https://github.com/nmarra/dynamic-module-loading
Yes, you can lazy load modules using by referring them as modules in the router. Here is an example https://github.com/start-angular/SB-Admin-BS4-Angular-6
First couple all the components that you are using into a single module
Now refer that module in the router and angular will lazy load your module into the view.
Related
I was just trying to build a module/component and serve it as a JS bundle. it builds:
#Component({
selector: 'app-component-overview',
template: '<button><ng-content></ng-content></button>',
})
export class ButtonComponent {}
#NgModule({
declarations: [ButtonComponent],
})
export class AppModule {}
the issue is that after building it to a javascript bundle. when I try to import it in another angular project. I get:
//ERROR in ... error TS2306 '...' is not a module.
loadChildren: () => import('...').then(m=>m.ButtonModule)
maybe I am missing the point here and things are different in angular, having webpack control makes it a lot easier but I want to avoid bringing custom builders and fiddling with the settings as little as possible.
Question is, is there a well documented way to bundle a module or even a standalone component to be used outside my project as a JS bundle? I could not find anything useful other than high level explanation of reusing and lazyloading thing already inside the same project.
It seems you are building this module as part of an application which is supposed to run in a browser. But what you are looking for is to build this module as part of a library which can be re-used in other projects.
See this official Angular guide on how to create a library.
After a few hours browsing around. I figured it out.
The answer that #json-derulo gave is part of the solution but there are more steps to make this work.
follow the guide: https://angular.io/guide/creating-libraries
here is the tricky part if you import the lib inside the workspace it will work. but that does not make much sense. You likely have another repository with a angular app that you want to consume the lib.
now to be able to import the this component as a lazy loaded route you will need to add "#angular/router" to the lib peerDependecies and run npm install again
now create a routing module and add the empty path to point to the component in the lib.
//my-lib-routing.module.ts
import { NgModule} from "#angular/core";
import { RouterModule } from "#angular/router";
import { MyLibComponent } from "./my-lib.component";
const routes= [
{ path: '', component: MyLibComponent },
];
#NgModule({
imports: [
RouterModule.forChild(
routes,
)
// other imports here
],
// providers: [RouterModule],
exports: [RouterModule]
})
export class myLibRoutingModule { }
change the libmodule to import the routing module
//
import { NgModule } from '#angular/core';
import { myLibRoutingModule } from './my-lib-routing.module';
import { MyLibComponent } from './my-lib.component';
#NgModule({
declarations: [MyLibComponent],
imports: [
myLibRoutingModule
],
})
export class MyLibModule { }
on the lib project root run 'npm run build'.
create a separate repo and "ng new app"
add the lib to the package.json of the main app, something like "my-lib": "../my-lib-ws/dist/my-lib".
open angular.json and add "preserveSymlinks": true to the build options.
run npm i to link the lib as a dependency.
add the libmoudle as a lazy loaded route
import { NgModule } from '#angular/core';
import { Routes, RouterModule } from '#angular/router';
const routes: Routes = [
{path: 'test', loadChildren: () => import('my-lib').then(m=>m.MyLibModule)}
];
#NgModule({
imports: [RouterModule.forRoot(routes)],
exports: [RouterModule]
})
export class AppRoutingModule { }
run npm run start. and try to access the 'test' route. you should see the component loaded in the main app router outled
Now, this is more of learning exercise the bundles almost gets doubled. and you would profit more using module federation. But it is a use case we have. Anyhow the steps are here if anyone can't reproduce let me know.
I am trying to call the javascript function into the angular here is the plugin I am using "npm I global payments-3ds" of which I copied javascript files from node_modules and tried to call in my component
Below is the example :
import {
Component,
OnInit
} from '#angular/core';
import {
handleInitiateAuthentication
} from './globalpayments-3ds/types/index';
#Component({
selector: 'my-app',
templateUrl: './app.component.html',
styleUrls: ['./app.component.css']
})
export class AppComponent implements OnInit {
name = 'Angular';
ngOnInit(): void {
const status: any = "CHALLENGE_REQUIRED"
const resp = {
challenge: {
encodedChallengeRequest: "abcd",
requestUrl: "url,
},
challengeMandated: "MANDATED",
dsTransactionId: "44444",
id: "444444",
status: status,
};
const windowSize: any = "WINDOWED_600X400";
const displayMode: any = "lightbox";
const challengeWindow = {
windowSize: windowSize,
displayMode: displayMode,
};
handleInitiateAuthentication(resp, challengeWindow)
}
}
I am trying to call the handleInitiateAuthentication() which is giving me the below error
Here is the file structure
from index.d.ts i am calling the handleInitiateAuthentication() function
Here is Stackblitz code for the same
https://stackblitz.com/edit/angular-vodezz?file=src%2Fapp%2Fapp.component.ts
Please help I never used the js function in angular I tried to add in assets not worked
I have tried to create an angular library and add the js files in it and update the package, by converting the file to .tgz but nothing working it showing always the same error,
Why am I doing is I have to update one of the files from node_modules, basically I wanna change files from node modules which is why i copied those files locally
this is also giving error
You have to import directly js file.
// #ts-ignore
import { handleInitiateAuthentication } from './globalpayments-3ds/globalpayments-3ds.esm.js';
For error about module, it's because you have to define type of your module in TypeScript. You can directly use // #ts-ignore.
See this stackblitz : https://stackblitz.com/edit/angular-xz4kmp?file=src%2Fapp%2Fapp.component.ts
You don't need to import a library like that. First of all install the library to your project:
npm i globalpayments-3ds --save
then in your ts file:
import { handleInitiateAuthentication } from 'globalpayments-3ds';
see this stackblitz
The recommended way to make your own modified versions from open source libraries is to fork them and build your own versions.
Also note that you must take into account the license of that NPM package which in the case of https://github.com/globalpayments/globalpayments-js is GPL-v2, so if you will use it for commercial purposes you must follow the agreement. Check this branch: GNU General Public License (v2): can a company use the licensed software for free?.
Taking a look to your Stackblitz code, you may notice that there are several JS versions of the same module in src/app/global-payments-3ds/ folder:
globalpayments-3ds.js (CommonJS, used in Node environments).
globalpayments-3ds.min.js (CommonJS minified).
globalpayments-3ds.js.map (CommonJS minified map file to reference during debugging).
globalpayments-3ds.esm.js (ESM, ECMA Standard Module).
...
To use an external JS Module in an Angular App, as it is JavaScript and not TypeScript, you must tell TypeScript Compiler that you want to allow JS modules by enabling allowJS: true in tsconfig.ts file at the root of the project.
After that you should be be able to import the ESM version (globalpayments-3ds.esm.js) in your Angular App, or if you want to use the CommonJS version, you can also enable esModuleInterop: true in tsconfig.ts to allow importing CommonJS/AMD/UMD JS modules in your project, like globalpayments-3ds.js.
When I build my Angular library, publish it to npm, and use it as a dependency in another project, whenever I try to import on of my module classes into my app.module.ts, and get this error Class TekButtonModule is not an Angular module. I have followed steps from multiple different sites on how to create, build, and publish angular libraries, and I can't figure out why it won't recognize the class as a valid module class.
In my app.module.ts, this is how I am importing the module:
import { TekButtonModule } from "tek-angular-uimodules";
#NgModule({
imports: [
TekButtonModule
]
})
export class AppModule { }
My library project follows the standard directory structure outlined by Angular. I did not change anything with the build, or path settings when I setup the library project. My built library project has a bundles, esm5, esm2015, fesm5, fesm2015, lib (where my custom modules, and components are), as well as a package.json, public-api.d.ts (exports everything in the lib directory), README.md, tek-angular-uimodules.d.ts (exports the public api), and a tek-angular-uimodules.metadata.json file.
Is there some extra configuration that it needed that isn't setup by default to get modules to work correctly?
Here is my button module class:
import { CommonModule } from "#angular/common";
import { NgModule } from "#angular/core";
import { TekButton } from "./button";
#NgModule({
declarations: [
TekButton
],
exports: [
TekButton
],
imports: [
CommonModule
]
})
export class TekButtonModule {}
Here are some of the files that are generated when I build the project:
tek-angular-uimodules.d.ts:
/**
* Generated bundle index. Do not edit.
*/
export * from './public-api';
public-api.ts
export * from "./lib/button";
export * from "./lib/button-group";
export * from "./lib/nav-bar";
./lib/button/button-module.d.ts
export declare class TekButtonModule {
}
If I import the generated javascript module file from the esm5 directory manually in my app.module.ts file, then it works just fine. But I have to manually do that, when it should just work with the standard module import that WebStorm auto imports for me like any other package.
This is the generated module js file under the esm5 directory:
/**
* #fileoverview added by tsickle
* #suppress {checkTypes,extraRequire,missingOverride,missingReturn,unusedPrivateMembers,uselessCode} checked by tsc
*/
import { CommonModule } from "#angular/common";
import { NgModule } from "#angular/core";
import { TekButton } from "./button";
var TekButtonModule = /** #class */ (function () {
function TekButtonModule() {
}
TekButtonModule.decorators = [
{ type: NgModule, args: [{
declarations: [
TekButton
],
exports: [
TekButton
],
imports: [
CommonModule
]
},] }
];
return TekButtonModule;
}());
export { TekButtonModule };
//# sourceMappingURL=data:application/json;base64
Any help is appreciated. I can provide more code, and screenshots if needed.
This is the error I get when trying to import my module:
So I figured out what was causing my specific issue. It was two things. Point two is the direct reason for my issue, point one was making much more confusing to debug.
In order to test my built package, I would run ng build, and then cd into the built project in the dist directory, and run npm pack. I would then install my built package as a file dependency in an entirely separate project to ensure I did everything correctly. What I found out was (or I'm assuming) that there was a caching mechanism going on even when doing local file dependency installations. This caching seemed to be tied to the file name of the tgz file that is generated from npm pack. This caching was causing the very first version to be constantly reinstalled not matter how many changes I made to the built library. The fix, for me, was to simply rename the tgz file to something different each time. You should also change the library version number, and that should also work.
My file structure looked like this:
src
- public-api.ts
- lib
-- button
--- index.ts
--- public-api.ts
--- button.component.ts
--- button.module.ts
-- another-module
-- yet-another-module
The public-api.ts file directly in src looked like this:
export * from './lib/button'
// Other exports
The public-api.ts, and the index.ts file under src\lib\button looked like this:
// public-api.ts
export * from './button.component.ts'
export * from './button.module.ts'
// index.ts
export * from './public-api.ts'
I had assumed that by adding the index.ts files to each directory, the export line in the root public-api.ts would find the index file, and export the files accordingly, but somewhere along the line, this implicit resolution does not work, and, instead, an explicit export is needed. The fix was to change export * from './lib/button' to export * from './lib/button/index.ts' or export * from './lib/button/public-api.ts'.
Point two was the direct reason for my issue, point one just made it really confusing when trying to debug.
So I had the same issue with a different solution, so I thought I would share it here.
I had just updated my library to Angular 9. And everything seemed fine except the strange "Class my-module is not an Angular module" error.
What worked for me was to up tsconfig.lib.ts file with:
...
"angularCompilerOptions": {
...,
"enableIvy": false
}
Don't know if this will help anyone, but for me it was caused by the NgModule import path autocompleting with #angular/core/src/metadata/*, rather than #angular/core.
We have project of around 100 pages. We are migrating our front end to some emerging technology. We almost have finalized Vue.js(with vue cli). Vue CLI is building project in one build.js. We have a problem with that. We have frequent requirement changes. So after every small change, we will have to upload whole build js and that will need regression testing of the whole project. Is there any way that build will be module wise? So that only changed module need to be uploaded on live after changes.
Using the Vue router:
The following approach will tell the compiler (Webpack) to "return" the component vs "including" it. Resulting in the given component being "chunked" into its own file for lazy loading.
e.g.
export default new Router({
routes: [
// Home component to be included in bundle.js
{
path: '/',
name: 'home',
component: Home
},
// code splitting - generate a separate unique chuck for about component.
{
path: '/about',
name: 'about',
component: () => import(/* webpackMode: "lazy" */ '#/views/About.vue')
}
]
})
Output = bundle.js and about.js or... 100 other files, given you have a component per page.
more on component lazy loading: https://router.vuejs.org/guide/advanced/lazy-loading.html
Using webpack:
You can extend and/or modify the default compiler (webpack) configuration by adding a vue.config.js file to the project root.
e.g.
// vue.config.js
module.exports = {
configureWebpack: config => {
if (process.env.NODE_ENV === 'production') {
// mutate config for production...
} else {
// mutate for development...
}
}
}
Be sure to read all the documentation at https://cli.vuejs.org/guide/webpack.html as some settings should not be mutated directly.
more on webpack code splitting: https://webpack.js.org/guides/code-splitting
What is the recommended best practice for loading environment specific configuration during runtime of an Angular application? The Angular documentation mentions the use of APP_INITIALIZER, but that is still not early enough in the load process for things such as runtime configuration of imported modules that make use of the .forRoot() convention.
In my use case, I have an authentication service built and imported via a Core module, which is imported by the App module. The authentication library I am using (the angular-oauth2-oidc library) allows for configuration of the automatic appending of access tokens during when importing the module (see this segment). Since there are constraints in the build environment I am working with that only allows me to produce one common build package to deploy to all environments, I am unable to dynamically set values by using different environment.ts files.
One initial idea is to use the fetch API on the index.html page to load a JSON file containing the configuration onto a global variable, but since the call is asynchronous, there is a chance the configuration will not be fully loaded when the import of the Core module occurs.
This was part of my config setup to bring my app through the build pipeline and took me days. I ended up in a solution using the APP_INITIALIZER loading a REST service and build a AppConfigService for my App. I am using the same angular-oauth2-oidc library.
My Solution for this issue was not to setup the OAuthModule in its forRoot() method. It is called before any configs via APP_INITIALIZER are available - this results in undefined values when applied to the config object given to the forRoot() Method.
But we need a token in the http header. So I used a http interceptor for the attaching of the token like described here. The trick is to setup the OAuthModuleConfig in the factory. Obviously this is called after the app is initialized.
Configure Module
#NgModule({
imports: [
// no config here
OAuthModule.forRoot(),
],
providers: [
{
provide: HTTP_INTERCEPTORS,
useFactory: authenticationInterceptorFactory,
deps: [OAuthStorage, AuthenticationErrorHandler, OAuthModuleConfig],
multi: true
}
]
})
Factory for interceptor
const authenticationInterceptorFactory = (oAuthService: OAuthStorage, authenticationErrorHandler: AuthenticationErrorHandler, oAuthModuleConfig: OAuthModuleConfig) => {
const config = {
resourceServer: {
allowedUrls: [
// Include config settings here instead
AppConfigService.settings.apiURL,
AppConfigService.settings.anotherApiURL,
]
sendAccessToken: true
},
}
return new AuthenticationInterceptor(oAuthService, authenticationErrorHandler, config);
};
I have created a library angular-runtime-config for runtime configuration loading for Angular.
Simple usage example
Your custom Configuration class:
export class Configuration {
readonly apiUrl!: string; // only example
readonly apiKey?: string; // only example
// add some other configuration parameters
}
Registering angular-runtime-config module with declaring which configuration files to load. For example, you can determine it by application URL or you can even use Angular injector in the factory or make the factory asynchronous.
import { AngularRuntimeConfigModule } from 'angular-runtime-config';
#NgModule({
...
imports: [
...
AngularRuntimeConfigModule.forRoot(Configuration, {
urlFactory: () => [ 'config/config.common.json', 'config/config.DEV.json' ]
})
],
}
Then request your Configuration class in any injection context.
#Injectable({...})
export class SomeService {
constructor(private readonly config: Configuration) {}
}