angular-architects / module-federation-plugin Goto Github PK
View Code? Open in Web Editor NEWLicense: MIT License
License: MIT License
I have cloned https://github.com/manfredsteyer/module-federation-plugin-example.
I have updated browserlistrc file to support only modern browsers. Still, I see multiple bundles.
Also, I have observed that multiple bundles are required. App doesn't work if I delete duplicated.
I would like to know why it does generate duplicate bundles and what should I do to eliminate this.
Is it possible to add angular universal support? I would not mind helping, if someone with more ModuleFederation experience would support me. I have some experience with angular universal but almost no experience with ModuleFederation.
Hello!
I have 2 questions:
After read the section: Sharing Libs of a Monorepo, i put my lib in the webpack configuration file, see:
const ModuleFederationPlugin = require("webpack/lib/container/ModuleFederationPlugin");
const mf = require("@angular-architects/module-federation/webpack");
const path = require("path");
const sharedMappings = new mf.SharedMappings();
sharedMappings.register(
path.join(__dirname, '../../tsconfig.base.json'),[
"@dinamize/ui"
]);
module.exports = {
output: {
uniqueName: "appShell"
},
optimization: {
runtimeChunk: false
},
plugins: [
new ModuleFederationPlugin({
remotes: {
"emktConfig": "emktConfig@http://localhost:4201/remoteEntry.js"
},
shared: {
"@angular/core": { singleton: true, strictVersion: true },
"@angular/common": { singleton: true, strictVersion: true },
"@angular/router": { singleton: true, strictVersion: true },
"rxjs":{singleton:true, strictVersion: true},
"rxjs/operators":{singleton:true, strictVersion: true},
"rxjs/Observable":{singleton:true, strictVersion: true},
...sharedMappings.getDescriptors()
}
}),
sharedMappings.getPlugin(),
],
};
This throw me this error:
./libs/ui/src/index.ts - Error: Module build failed (from ./node_modules/@ngtools/webpack/src/ivy/index.js):
Error: The Angular Webpack loader requires the AngularWebpackPlugin.
at Object.angularWebpackLoader (C:\Users\ronal\Documents\projetos\dinamize\MFE\node_modules\@ngtools\webpack\src\ivy\loader.js:28:18)
./libs/ui/src/lib/web/style/theme.scss - Error: Module build failed (from ./node_modules/mini-css-extract-plugin/dist/loader.js):
ModuleBuildError: Module build failed (from ./node_modules/@ngtools/webpack/src/ivy/index.js):
Error: The Angular Webpack loader requires the AngularWebpackPlugin.
at Object.angularWebpackLoader (C:\Users\ronal\Documents\projetos\dinamize\MFE\node_modules\@ngtools\webpack\src\ivy\loader.js:28:18)
at processResult (C:\Users\ronal\Documents\projetos\dinamize\MFE\node_modules\webpack\lib\NormalModule.js:576:19)
at C:\Users\ronal\Documents\projetos\dinamize\MFE\node_modules\webpack\lib\NormalModule.js:669:5
at C:\Users\ronal\Documents\projetos\dinamize\MFE\node_modules\loader-runner\lib\LoaderRunner.js:399:11
at C:\Users\ronal\Documents\projetos\dinamize\MFE\node_modules\loader-runner\lib\LoaderRunner.js:251:18
at context.callback (C:\Users\ronal\Documents\projetos\dinamize\MFE\node_modules\loader-runner\lib\LoaderRunner.js:124:13)
at Object.angularWebpackLoader (C:\Users\ronal\Documents\projetos\dinamize\MFE\node_modules\@ngtools\webpack\src\ivy\loader.js:28:9)
PS C:\Users\ronal\Documents\projetos\dinamize\MFE> ng serve app-shell
Your global Angular CLI version (11.2.8) is greater than your local version (11.0.7). The local Angular CLI version is used.
To disable this warning use "ng config -g cli.warnings.versionMismatch false".
> nx run app-shell:serve
⠋ Generating browser application bundles (phase: building)...(node:8140) [DEP_WEBPACK_CHUNK_INTEGRATE] DeprecationWarning: Chunk.integrate: Use new ChunkGraph API
(Use `node --trace-deprecation ...` to show where the warning was created)
⠧ Generating browser application bundles (phase: sealing)...
Initial Chunk Files | Names | Size
main.js | main | 0 bytes
polyfills.js | polyfills | 0 bytes
styles.js | styles | 0 bytes
Lazy Chunk Files | Names | Size
apps_app-shell_src_bootstrap_ts.js | - | 0 bytes
default-libs_ui_src_index_ts.js | - | 0 bytes
default-node_modules_angular_common_fesm2015_common_js.js | - | 0 bytes
default-node_modules_rxjs__esm2015_internal_AsyncSubject_js-node_modules_rxjs__esm2015_intern-0da67e.js | - | 0 bytes
node_modules_angular_core_fesm2015_core_js.js | - | 0 bytes
node_modules_angular_router_fesm2015_router_js.js | - | 0 bytes
node_modules_rxjs__esm2015_index_js.js | - | 0 bytes
node_modules_rxjs__esm2015_operators_index_js.js | - | 0 bytes
4 unchanged chunks
Build at: 2021-04-14T16:45:11.970Z - Hash: 89d2f6e83e048eb513e9 - Time: 11698ms
./libs/ui/src/index.ts - Error: Module build failed (from ./node_modules/@ngtools/webpack/src/ivy/index.js):
Error: The Angular Webpack loader requires the AngularWebpackPlugin.
at Object.angularWebpackLoader (C:\Users\ronal\Documents\projetos\dinamize\MFE\node_modules\@ngtools\webpack\src\ivy\loader.js:28:18)
./libs/ui/src/index.ts - Error: Module build failed (from ./node_modules/@ngtools/webpack/src/ivy/index.js):
Error: The Angular Webpack loader requires the AngularWebpackPlugin.
at Object.angularWebpackLoader (C:\Users\ronal\Documents\projetos\dinamize\MFE\node_modules\@ngtools\webpack\src\ivy\loader.js:28:18)
./libs/ui/src/index.ts - Error: Module build failed (from ./node_modules/@ngtools/webpack/src/ivy/index.js):
Error: The Angular Webpack loader requires the AngularWebpackPlugin.
at Object.angularWebpackLoader (C:\Users\ronal\Documents\projetos\dinamize\MFE\node_modules\@ngtools\webpack\src\ivy\loader.js:28:18)
./libs/ui/src/index.ts - Error: Module build failed (from ./node_modules/@ngtools/webpack/src/ivy/index.js):
Error: The Angular Webpack loader requires the AngularWebpackPlugin.
at Object.angularWebpackLoader (C:\Users\ronal\Documents\projetos\dinamize\MFE\node_modules\@ngtools\webpack\src\ivy\loader.js:28:18)
./libs/ui/src/index.ts - Error: Module build failed (from ./node_modules/@ngtools/webpack/src/ivy/index.js):
Error: The Angular Webpack loader requires the AngularWebpackPlugin.
at Object.angularWebpackLoader (C:\Users\ronal\Documents\projetos\dinamize\MFE\node_modules\@ngtools\webpack\src\ivy\loader.js:28:18)
./libs/ui/src/index.ts - Error: Module build failed (from ./node_modules/@ngtools/webpack/src/ivy/index.js):
Error: The Angular Webpack loader requires the AngularWebpackPlugin.
at Object.angularWebpackLoader (C:\Users\ronal\Documents\projetos\dinamize\MFE\node_modules\@ngtools\webpack\src\ivy\loader.js:28:18)
./libs/ui/src/index.ts - Error: Module build failed (from ./node_modules/@ngtools/webpack/src/ivy/index.js):
Error: The Angular Webpack loader requires the AngularWebpackPlugin.
at Object.angularWebpackLoader (C:\Users\ronal\Documents\projetos\dinamize\MFE\node_modules\@ngtools\webpack\src\ivy\loader.js:28:18)
./apps/app-shell/src/styles.scss - Error: Module build failed (from ./node_modules/mini-css-extract-plugin/dist/loader.js):
ModuleBuildError: Module build failed (from ./node_modules/@ngtools/webpack/src/ivy/index.js):
Error: The Angular Webpack loader requires the AngularWebpackPlugin.
at Object.angularWebpackLoader (C:\Users\ronal\Documents\projetos\dinamize\MFE\node_modules\@ngtools\webpack\src\ivy\loader.js:28:18)
at processResult (C:\Users\ronal\Documents\projetos\dinamize\MFE\node_modules\webpack\lib\NormalModule.js:576:19)
at C:\Users\ronal\Documents\projetos\dinamize\MFE\node_modules\webpack\lib\NormalModule.js:669:5
at C:\Users\ronal\Documents\projetos\dinamize\MFE\node_modules\loader-runner\lib\LoaderRunner.js:399:11
at C:\Users\ronal\Documents\projetos\dinamize\MFE\node_modules\loader-runner\lib\LoaderRunner.js:251:18
at context.callback (C:\Users\ronal\Documents\projetos\dinamize\MFE\node_modules\loader-runner\lib\LoaderRunner.js:124:13)
at Object.angularWebpackLoader (C:\Users\ronal\Documents\projetos\dinamize\MFE\node_modules\@ngtools\webpack\src\ivy\loader.js:28:9)
./libs/ui/src/lib/web/style/theme.scss - Error: Module build failed (from ./node_modules/mini-css-extract-plugin/dist/loader.js):
ModuleBuildError: Module build failed (from ./node_modules/@ngtools/webpack/src/ivy/index.js):
Error: The Angular Webpack loader requires the AngularWebpackPlugin.
at Object.angularWebpackLoader (C:\Users\ronal\Documents\projetos\dinamize\MFE\node_modules\@ngtools\webpack\src\ivy\loader.js:28:18)
at processResult (C:\Users\ronal\Documents\projetos\dinamize\MFE\node_modules\webpack\lib\NormalModule.js:576:19)
at C:\Users\ronal\Documents\projetos\dinamize\MFE\node_modules\webpack\lib\NormalModule.js:669:5
at C:\Users\ronal\Documents\projetos\dinamize\MFE\node_modules\loader-runner\lib\LoaderRunner.js:399:11
at C:\Users\ronal\Documents\projetos\dinamize\MFE\node_modules\loader-runner\lib\LoaderRunner.js:251:18
at context.callback (C:\Users\ronal\Documents\projetos\dinamize\MFE\node_modules\loader-runner\lib\LoaderRunner.js:124:13)
at Object.angularWebpackLoader (C:\Users\ronal\Documents\projetos\dinamize\MFE\node_modules\@ngtools\webpack\src\ivy\loader.js:28:9)
** Angular Live Development Server is listening on localhost:4200, open your browser on http://localhost:4200/ **
✔ Browser application bundle generation complete.
(node:8140) [DEP_WEBPACK_DEPRECATION_ARRAY_TO_SET_INDEXER] DeprecationWarning: chunk.files was changed from Array to Set (indexing Array is deprecated)
⠸ Generating browser application bundles (phase: sealing)...
15 unchanged chunks
Build at: 2021-04-14T16:45:14.827Z - Hash: 89d2f6e83e048eb513e9 - Time: 2119ms
./libs/ui/src/index.ts - Error: Module build failed (from ./node_modules/@ngtools/webpack/src/ivy/index.js):
Error: The Angular Webpack loader requires the AngularWebpackPlugin.
at Object.angularWebpackLoader (C:\Users\ronal\Documents\projetos\dinamize\MFE\node_modules\@ngtools\webpack\src\ivy\loader.js:28:18)
./libs/ui/src/index.ts - Error: Module build failed (from ./node_modules/@ngtools/webpack/src/ivy/index.js):
Error: The Angular Webpack loader requires the AngularWebpackPlugin.
at Object.angularWebpackLoader (C:\Users\ronal\Documents\projetos\dinamize\MFE\node_modules\@ngtools\webpack\src\ivy\loader.js:28:18)
./libs/ui/src/index.ts - Error: Module build failed (from ./node_modules/@ngtools/webpack/src/ivy/index.js):
Error: The Angular Webpack loader requires the AngularWebpackPlugin.
at Object.angularWebpackLoader (C:\Users\ronal\Documents\projetos\dinamize\MFE\node_modules\@ngtools\webpack\src\ivy\loader.js:28:18)
./libs/ui/src/index.ts - Error: Module build failed (from ./node_modules/@ngtools/webpack/src/ivy/index.js):
Error: The Angular Webpack loader requires the AngularWebpackPlugin.
at Object.angularWebpackLoader (C:\Users\ronal\Documents\projetos\dinamize\MFE\node_modules\@ngtools\webpack\src\ivy\loader.js:28:18)
./libs/ui/src/index.ts - Error: Module build failed (from ./node_modules/@ngtools/webpack/src/ivy/index.js):
Error: The Angular Webpack loader requires the AngularWebpackPlugin.
at Object.angularWebpackLoader (C:\Users\ronal\Documents\projetos\dinamize\MFE\node_modules\@ngtools\webpack\src\ivy\loader.js:28:18)
./libs/ui/src/index.ts - Error: Module build failed (from ./node_modules/@ngtools/webpack/src/ivy/index.js):
Error: The Angular Webpack loader requires the AngularWebpackPlugin.
at Object.angularWebpackLoader (C:\Users\ronal\Documents\projetos\dinamize\MFE\node_modules\@ngtools\webpack\src\ivy\loader.js:28:18)
./libs/ui/src/index.ts - Error: Module build failed (from ./node_modules/@ngtools/webpack/src/ivy/index.js):
Error: The Angular Webpack loader requires the AngularWebpackPlugin.
at Object.angularWebpackLoader (C:\Users\ronal\Documents\projetos\dinamize\MFE\node_modules\@ngtools\webpack\src\ivy\loader.js:28:18)
./apps/app-shell/src/styles.scss - Error: Module build failed (from ./node_modules/mini-css-extract-plugin/dist/loader.js):
ModuleBuildError: Module build failed (from ./node_modules/@ngtools/webpack/src/ivy/index.js):
Error: The Angular Webpack loader requires the AngularWebpackPlugin.
at Object.angularWebpackLoader (C:\Users\ronal\Documents\projetos\dinamize\MFE\node_modules\@ngtools\webpack\src\ivy\loader.js:28:18)
at processResult (C:\Users\ronal\Documents\projetos\dinamize\MFE\node_modules\webpack\lib\NormalModule.js:576:19)
at C:\Users\ronal\Documents\projetos\dinamize\MFE\node_modules\webpack\lib\NormalModule.js:669:5
at C:\Users\ronal\Documents\projetos\dinamize\MFE\node_modules\loader-runner\lib\LoaderRunner.js:399:11
at C:\Users\ronal\Documents\projetos\dinamize\MFE\node_modules\loader-runner\lib\LoaderRunner.js:251:18
at context.callback (C:\Users\ronal\Documents\projetos\dinamize\MFE\node_modules\loader-runner\lib\LoaderRunner.js:124:13)
at Object.angularWebpackLoader (C:\Users\ronal\Documents\projetos\dinamize\MFE\node_modules\@ngtools\webpack\src\ivy\loader.js:28:9)
./libs/ui/src/lib/web/style/theme.scss - Error: Module build failed (from ./node_modules/mini-css-extract-plugin/dist/loader.js):
ModuleBuildError: Module build failed (from ./node_modules/@ngtools/webpack/src/ivy/index.js):
Error: The Angular Webpack loader requires the AngularWebpackPlugin.
at Object.angularWebpackLoader (C:\Users\ronal\Documents\projetos\dinamize\MFE\node_modules\@ngtools\webpack\src\ivy\loader.js:28:18)
at processResult (C:\Users\ronal\Documents\projetos\dinamize\MFE\node_modules\webpack\lib\NormalModule.js:576:19)
at C:\Users\ronal\Documents\projetos\dinamize\MFE\node_modules\webpack\lib\NormalModule.js:669:5
at C:\Users\ronal\Documents\projetos\dinamize\MFE\node_modules\loader-runner\lib\LoaderRunner.js:399:11
at C:\Users\ronal\Documents\projetos\dinamize\MFE\node_modules\loader-runner\lib\LoaderRunner.js:251:18
at context.callback (C:\Users\ronal\Documents\projetos\dinamize\MFE\node_modules\loader-runner\lib\LoaderRunner.js:124:13)
at Object.angularWebpackLoader (C:\Users\ronal\Documents\projetos\dinamize\MFE\node_modules\@ngtools\webpack\src\ivy\loader.js:28:9)
✔ Browser application bundle generation complete.
What is the best way to change the remote url to test and production url
remotes: {
"emktConfig": "emktConfig@http://localhost:4201/remoteEntry.js"
}
When enabling HMR and serving the app with ng s --hmr
, application will not be served and it hangs.
Reproduction :
1- Create an Angular project.
2- Add Module Federation to the app.
3- Serve the app with --hmr
argument.
4- As you can see, application will not start.
Angular : 11.0.5
ngx-build-plus 10.1.1
@angular-architects/module-federation 1.2.2
Hello, you mention in your documentation the bug in the experimental CLI/webpack5 which does not allow bundling styles in the federated modules. Is there an ETA on when this will be resolved? This is a pretty big hurdle for any enterprise solution.
I've followed some tutorials and all fall in the same issue.:
The remoteName doesn't exist in window, so, it doesn't load and throw me an error, see bellow:
Files:
//app.module
import { NgModule } from '@angular/core';
import { BrowserModule } from '@angular/platform-browser';
import { AppComponent } from './app.component';
import { RouterModule } from '@angular/router';
import { loadRemoteModule } from '@angular-architects/module-federation';
@NgModule({
declarations: [AppComponent],
imports: [
BrowserModule,
RouterModule.forRoot([
{
path: 'domains',
loadChildren: () =>
loadRemoteModule({
remoteEntry: 'http://localhost:4201/remoteEntry.js',
remoteName: 'emkt-config',
exposedModule: './Domains',
}).then((m) => m.DomainsModule),
},
], { initialNavigation: 'enabled' }),
],
providers: [],
bootstrap: [AppComponent],
})
export class AppModule {}
//shell's webpack.config.js
const ModuleFederationPlugin = require("webpack/lib/container/ModuleFederationPlugin");
const mf = require("@angular-architects/module-federation/webpack");
const path = require("path");
const sharedMappings = new mf.SharedMappings();
sharedMappings.register(
path.join(__dirname, '../../tsconfig.base.json'),[]);
module.exports = {
output: {
uniqueName: "app-shell"
},
optimization: {
// Only needed to bypass a temporary bug
runtimeChunk: false
},
plugins: [
new ModuleFederationPlugin({
// For hosts (please adjust)
remotes: {
"emkt-config": "emkt-config@http://localhost:4200/remoteEntry.js",
},
shared: {
"@angular/core": { singleton: true, strictVersion: true },
"@angular/common": { singleton: true, strictVersion: true },
"@angular/router": { singleton: true, strictVersion: true },
...sharedMappings.getDescriptors()
}
}),
sharedMappings.getPlugin(),
],
};
// emkt-config's webpack.config.js
const ModuleFederationPlugin = require("webpack/lib/container/ModuleFederationPlugin");
const mf = require("@angular-architects/module-federation/webpack");
const path = require("path");
const sharedMappings = new mf.SharedMappings();
sharedMappings.register(
path.join(__dirname, '../../tsconfig.base.json'),
[
// "@dinamize-nx-workspace/ui"
]
);
module.exports = {
output: {
uniqueName: "emkt-config"
},
optimization: {
// Only needed to bypass a temporary bug
runtimeChunk: false
},
plugins: [
new ModuleFederationPlugin({
name: "emkt-config",
filename: "remoteEntry.js",
exposes: {
'./Domains': './apps/emkt-config/src/app/domains/domains.module.ts',
'./Content': './apps/emkt-config/src/app/content/content.module.ts',
'./Send': './apps/emkt-config/src/app/send/send.module.ts',
'./ConfigForms': './apps/emkt-config/src/app/config-forms/config-forms.module.ts',
'./Integrations': './apps/emkt-config/src/app/integrations/integrations.module.ts',
},
shared: {
"@angular/core": { singleton: true, strictVersion: true },
"@angular/common": { singleton: true, strictVersion: true },
"@angular/router": { singleton: true, strictVersion: true },
...sharedMappings.getDescriptors()
}
}),
sharedMappings.getPlugin(),
],
};
Hi,
My Company requires all our packages to have a License on NPM otherwise our proxy quarantines them.
Is it possible to add a License for:
@angular-architects/module-federation-runtime
and
@angular-architects/module-federation-tools
Many thanks :)
An unhandled exception occurred: Invalid configuration object. Webpack has been initialised using a configuration object that does not match the API schema.
output
options tell webpack how to write the compiled files to disk.Hello,
I am trying to improve the library sharing between shell and microfronts using the feature to load the remote entry upfront:
https://www.angulararchitects.io/aktuelles/dynamic-module-federation-with-angular/ -> Improvement for Dynamic Module Federation
I am attaching screenshots of the code and the error:
zone-evergreen.js:1063 Unhandled Promise rejection: Cannot read property 'init' of undefined ; Zone: ; Task: HTMLScriptElement.addEventListener:load ; Value: TypeError: Cannot read property 'init' of undefined
at dynamic-federation.js:28
at Generator.next ()
at tslib.es6.js:74
at new ZoneAwarePromise (zone-evergreen.js:1387)
at Module.__awaiter (tslib.es6.js:70)
at initRemote (dynamic-federation.js:17)
at HTMLScriptElement.script.onload [as __zone_symbol__ON_PROPERTYload] (dynamic-federation.js:44)
at HTMLScriptElement.wrapFn (zone-evergreen.js:763)
at ZoneDelegate.invokeTask (zone-evergreen.js:406)
at Zone.runTask (zone-evergreen.js:178) TypeError: Cannot read property 'init' of undefined
at http://localhost:3000/vendor.js:52:25
at Generator.next ()
at http://localhost:3000/vendor.js:195:71
at new ZoneAwarePromise (http://localhost:3000/polyfills.js:1397:29)
at Module.__awaiter (http://localhost:3000/vendor.js:191:12)
at initRemote (http://localhost:3000/vendor.js:41:20)
at HTMLScriptElement.script.onload [as __zone_symbol__ON_PROPERTYload] (http://localhost:3000/vendor.js:68:13)
at HTMLScriptElement.wrapFn (http://localhost:3000/polyfills.js:773:39)
at ZoneDelegate.invokeTask (http://localhost:3000/polyfills.js:416:31)
at Zone.runTask (http://localhost:3000/polyfills.js:188:47)
@manfredsteyer I tried using the @angular-architects/module-federation plugin by following the steps mentioned for using this library in a newly created Angular 11 project. However, the execution of the ng serve or yarn start halts up at 21% with the below mentioned message.
Could you please help me out if I am missing something here.
I add an old project (PRJ1) which was working. This project is in Angular 11.0.7 and module federation 1.2.2
I create a new project (PRJ2) with the last version of Angular (11.1.4) and module federation 1.2.3.
This project doesn't start and doesn't build.
I have updated PRJ1 to 11.1.4 and have the same problem.
I downgraded PRJ2 to 11.0.7 and it works !!! (i have used the working package.json from PRJ1).
package.json files that is working :
package.working.json.txt
package.json files that is not working :
package.notworking.json.txt
if you create your application with the flag "minimal":
ng g app shell --minimal --routing
and try to apply:
ng add @angular-architects/module-federation --project shell --port 5000
you will get an error:
expected node projects/shell/architect/test in angular.json
not sure whether it's a bug or a feature :)
The Angular core team announced that Webpack 5 will be the default in Angular 12. The Yarn requirement is a stumbling block as our build system only supports NPM today.
I started playing around with Angular 12 (v12.0.0-rc-0) and the both the MFE and shell build with NPM but at runtime it fails to load the MFE module in the host. I know it's early, but I'm curious. Will the Angular 12 out of the box support for Webpack 5 enable dropping the Yarn requirement?
I also tested upgrading the module-federation-with-angular-dynamic to Angular 12 and I received the same errors as with Angular 12 and NPM.
Any ideas?
load script:41 GET http://localhost:5000/common.js net::ERR_ABORTED 404 (Not Found) __webpack_require__.l @ load script:41 __webpack_require__.f.j @ jsonp chunk loading:43 (anonymous) @ ensure chunk:6 __webpack_require__.e @ ensure chunk:5 ./Module @ container-entry:6 get @ container-entry:13 (anonymous) @ dynamic-federation.js:11 (anonymous) @ tslib.es6.js:76 ZoneAwarePromise @ zone.js:1340 __awaiter @ tslib.es6.js:72 lookupExposedModule @ dynamic-federation.js:9 (anonymous) @ dynamic-federation.js:57 fulfilled @ tslib.es6.js:73 __webpack_modules__.9140.ZoneDelegate.invoke @ zone.js:400 onInvoke @ core.js:28632 __webpack_modules__.9140.ZoneDelegate.invoke @ zone.js:399 __webpack_modules__.9140.Zone.run @ zone.js:160 (anonymous) @ zone.js:1318 __webpack_modules__.9140.ZoneDelegate.invokeTask @ zone.js:434 onInvokeTask @ core.js:28619 __webpack_modules__.9140.ZoneDelegate.invokeTask @ zone.js:433 __webpack_modules__.9140.Zone.runTask @ zone.js:205 drainMicroTaskQueue @ zone.js:620 __webpack_modules__.9140.ZoneTask.invokeTask @ zone.js:520 invokeTask @ zone.js:1656 globalZoneAwareCallback @ zone.js:1682 load (async) customScheduleGlobal @ zone.js:1808 __webpack_modules__.9140.ZoneDelegate.scheduleTask @ zone.js:421 onScheduleTask @ zone.js:311 __webpack_modules__.9140.ZoneDelegate.scheduleTask @ zone.js:414 __webpack_modules__.9140.Zone.scheduleTask @ zone.js:248 __webpack_modules__.9140.Zone.scheduleEventTask @ zone.js:274 (anonymous) @ zone.js:1965 desc.set @ zone.js:864 (anonymous) @ dynamic-federation.js:43 ZoneAwarePromise @ zone.js:1340 loadRemoteEntry @ dynamic-federation.js:34 (anonymous) @ dynamic-federation.js:55 (anonymous) @ tslib.es6.js:76 ZoneAwarePromise @ zone.js:1340 __awaiter @ tslib.es6.js:72 loadRemoteModule @ dynamic-federation.js:53 loadChildren @ menu-utils.ts:10 loadModuleFactory @ router.js:3687 load @ router.js:3661 (anonymous) @ router.js:2798 _tryNext @ mergeMap.js:44 _next @ mergeMap.js:34 next @ Subscriber.js:49 (anonymous) @ subscribeToArray.js:3 _trySubscribe @ Observable.js:42 subscribe @ Observable.js:28 call @ mergeMap.js:19 subscribe @ Observable.js:23 call @ mergeMap.js:19 subscribe @ Observable.js:23 call @ catchError.js:14 subscribe @ Observable.js:23 innerSubscribe @ innerSubscribe.js:67 _innerSub @ mergeMap.js:57 _tryNext @ mergeMap.js:51 _next @ mergeMap.js:34 next @ Subscriber.js:49 (anonymous) @ subscribeToArray.js:3 _trySubscribe @ Observable.js:42 subscribe @ Observable.js:28 call @ mergeMap.js:19 subscribe @ Observable.js:23 call @ filter.js:13 subscribe @ Observable.js:23 call @ take.js:22 subscribe @ Observable.js:23 call @ throwIfEmpty.js:13 subscribe @ Observable.js:23 call @ catchError.js:14 subscribe @ Observable.js:23 call @ map.js:16 subscribe @ Observable.js:23 innerSubscribe @ innerSubscribe.js:67 _innerSub @ mergeMap.js:57 _tryNext @ mergeMap.js:51 _next @ mergeMap.js:34 next @ Subscriber.js:49 (anonymous) @ subscribeToArray.js:3 _trySubscribe @ Observable.js:42 subscribe @ Observable.js:28 call @ mergeMap.js:19 subscribe @ Observable.js:23 call @ scan.js:18 subscribe @ Observable.js:23 call @ takeLast.js:22 subscribe @ Observable.js:23 call @ throwIfEmpty.js:13 subscribe @ Observable.js:23 call @ map.js:16 subscribe @ Observable.js:23 call @ map.js:16 subscribe @ Observable.js:23 call @ catchError.js:14 subscribe @ Observable.js:23 call @ map.js:16 subscribe @ Observable.js:23 innerSubscribe @ innerSubscribe.js:67 _innerSub @ switchMap.js:44 _next @ switchMap.js:34 next @ Subscriber.js:49 notifyNext @ switchMap.js:66 _next @ innerSubscribe.js:10 next @ Subscriber.js:49 (anonymous) @ subscribeToPromise.js:5 __webpack_modules__.9140.ZoneDelegate.invoke @ zone.js:400 onInvoke @ core.js:28632 __webpack_modules__.9140.ZoneDelegate.invoke @ zone.js:399 __webpack_modules__.9140.Zone.run @ zone.js:160 (anonymous) @ zone.js:1318 __webpack_modules__.9140.ZoneDelegate.invokeTask @ zone.js:434 onInvokeTask @ core.js:28619 __webpack_modules__.9140.ZoneDelegate.invokeTask @ zone.js:433 __webpack_modules__.9140.Zone.runTask @ zone.js:205 drainMicroTaskQueue @ zone.js:620 __webpack_modules__.9140.ZoneTask.invokeTask @ zone.js:520 invokeTask @ zone.js:1656 globalZoneAwareCallback @ zone.js:1682 Show 93 more frames core.js:6456 ERROR Error: Uncaught (in promise): ChunkLoadError: Loading chunk common failed. (error: http://localhost:5000/common.js) ChunkLoadError: Loading chunk common failed. (error: http://localhost:5000/common.js) at Object.__webpack_require__.f.j (jsonp chunk loading:27) at ensure chunk:6 at Array.reduce (<anonymous>) at Function.__webpack_require__.e (ensure chunk:5) at Object../Module (container-entry:6) at Object.get (container-entry:13) at dynamic-federation.js:11 at Generator.next (<anonymous>) at tslib.es6.js:76 at new ZoneAwarePromise (zone.js:1340) at resolvePromise (zone.js:1255) at resolvePromise (zone.js:1209) at zone.js:1321 at ZoneDelegate.__webpack_modules__.9140.ZoneDelegate.invokeTask (zone.js:434) at Object.onInvokeTask (core.js:28619) at ZoneDelegate.__webpack_modules__.9140.ZoneDelegate.invokeTask (zone.js:433) at Zone.__webpack_modules__.9140.Zone.runTask (zone.js:205) at drainMicroTaskQueue (zone.js:620) at ZoneTask.__webpack_modules__.9140.ZoneTask.invokeTask [as invoke] (zone.js:520) at invokeTask (zone.js:1656)
I noticed that when installing the package that I was getting issues with actually requiring in the file. I noticed that the package.json main property is: "main": "src\\index.js",
when it should be "main": "src/index.js",
If I pull down this project and run yarn build mf
, it generates the correct path.
Here is the error:
➜ ngx-dashboard-widget-sandbox-example git:(feature/mfe) node
Welcome to Node.js v14.15.3.
Type ".help" for more information.
> require('@angular-architects/module-federation')
Uncaught:
Error: Cannot find module '/Volumes/Development/ngx-dashboard-widget-sandbox-example/node_modules/@angular-architects/module-federation/src\index.js'. Please verify that the package.json has a valid "main" entry
at tryPackage (internal/modules/cjs/loader.js:303:19)
at Function.Module._findPath (internal/modules/cjs/loader.js:516:18)
at Function.Module._resolveFilename (internal/modules/cjs/loader.js:867:27)
at Function.Module._load (internal/modules/cjs/loader.js:725:27)
at Module.require (internal/modules/cjs/loader.js:952:19)
at require (internal/modules/cjs/helpers.js:88:18) {
code: 'MODULE_NOT_FOUND',
path: '/Volumes/Development/ngx-dashboard-widget-sandbox-example/node_modules/@angular-architects/module-federation/package.json',
requestPath: '@angular-architects/module-federation'
}
>
Changing the above main property value allows for the module to work.
This also looks to have the same issue on the typings
property as well.
By design in tsconfig.json you able to set multilple paths like so:
"@wololo/auth": [
"dist/@wololo/auth",
"libs/auth/src/index"
]
This declaration works by following idea: "use compiled library, if not - compile from source"
But, here as you can see you just pick first path:
I'm loading microfrontends like so:
shell/main.ts:
import { loadRemoteEntry } from '@angular-architects/module-federation';
import { environment } from './environments/environment';
Promise.all([
loadRemoteEntry(
`${environment.microfrontends.mfe.entryPoint}`,
`${environment.microfrontends.mfe.remoteName}`
),
])
.catch((err) => console.error('Error loading remote entries', err))
.then(() => import('./bootstrap'))
.catch((err) => console.error(err));
When loading the app in IE 11, an error is caught (and hidden) that says:
"Object doesn't support property or method 'append'"
The error appears to occur in loadRemoteEntry at line 57 in https://github.com/angular-architects/module-federation-plugin/blob/main/packages/mf/src/utils/dynamic-federation.ts
What can I do to make this work in IE11?
Note: According to https://developer.mozilla.org/en-US/docs/Web/API/Element/append IE does not support Element.append. That does explain the error message but it doesn't help me solve this.
Hi, I'm using module federation plugin to create a "dynamic composable application".
Everything is working great, until i create a component inside a remote with a reference to HttpClient in constructor.
I use the loadRemoteModule method to load component from remote.
When i load the remote and create the component, i have experienced the "Static injector error" for HttpClient as follows:
ERROR Error: Uncaught (in promise): NullInjectorError: R3InjectorError(AppModule)[HttpClient -> HttpClient -> HttpClient]:
NullInjectorError: No provider for HttpClient!
NullInjectorError: R3InjectorError(AppModule)[HttpClient -> HttpClient -> HttpClient]:
NullInjectorError: No provider for HttpClient!
...
at NodeInjectorFactory.TestComponent_Factory [as factory] (test.component.ts:8)
i have created a repo to nail the problem:
https://github.com/davidesenatore/MFTest
I have no clue to resolve the problem.
Many thanks!
Davide
Hello Manfred, thank you for providing this cool plugin :)
Recently, I tried to add Angular Material to your plugin example and I got stuck registering custom icons into the MatIconRegistry. Although the HttpClientModule is imported into the FlightsModule from the mfe1, the MatIconRegistry cannot access the HttpClient.
When I start both the shell and the mfe1 in the browser, then I can see the following error message in the console:
core.js:4610 ERROR Error: Uncaught (in promise): Error: Could not find HttpClient provider for use with Angular Material icons. Please include the HttpClientModule from @angular/common/http in your app imports.
I added the following things to the project (see commit):
export class FlightsModule {
constructor(private iconService: IconService) {
iconService.registerMyIcons();
}
}
Custom icons can then be used in the template like this (using the angular.svg icon from the assets):
<mat-icon svgIcon="angular"></mat-icon>
The issue here is, that the method registerMyIcons
calls the addSvgIcon
method which requires the HttpClient to load the custom SVG icons from the assets folder.
The usage of the HttpClient inside mfe1 is generally possible, but does not getting injected into the MatIconRegistry.
Fork of @manfredsteyer's plugin example with the issue can be found here:
Hi, i am having issues importing an external angular library.
When i try to import it, the build hangs up. i tried to run first the project and then add de import and the terminal shows me this error:
✔ Browser application bundle generation complete.
⠹ Generating browser application bundles (phase: building)...(node:34635) [DEP_WEBPACK_DEPRECATION_ARRAY_TO_SET] DeprecationWarning: Compilation.modules was changed from Array to Set (using Array method 'find' is deprecated)
⠸ Generating browser application bundles (phase: sealing)...
anyone knows what this error is about? thanks!
When in the webpack configuration we define a name with the character "-" like my-app, we have an error.
The variable should be created after a transformation to camelCase
⠦ Generating ES5 bundles for differential loading...An unhandled exception occurred: /home/vagrant/.../remoteEntry.js: Missing semicolon (1:9)
> 1 | var my-app;my-app =
| ^
2 | /******/ (function() { // webpackBootstrap
3 | /******/ "use strict";
4 | /******/ var __webpack_modules__ = ({
See "/tmp/ng-J43sR3/angular-errors.log" for further details.
Hello, I have been following the steps at https://www.angulararchitects.io/ for module federation, and it worked fine until I tried to route dynamic modules. I get this error when I start the shell app:
[...] Error: Module not found: Error: Can't resolve '@angular-architects/module-federation' [...]
Before adding the funcion 'loadRemoteModule' it was working. This is my package.json:
Is it possible to avoid Yarn and only use NPM with Angular 11 and version 12.0.0-rc.1.0.1 if the plugin? The latest tutorial makes it sound like it's possible to choose between NPM or Yarn but the when installing the plugin it uses Yarn and creates a yarn,lock file.
When we are tying to use this plugin to setup module federation into and Angular 11 - single SPA application, it stops working with following error.
single-spa minified message #37: See https://single-spa.js.org/error/?code=37&arg=application&arg=models-plan&arg={"default":{},"__useDefault":true}
We followed below article by Manfred Steyer:
link
So I have a typical shell app for hosting mfe. Setup for dynamically loading components (like widgets). Like in the Plugin example. The only difference is I'm not adding them on click event but from the configuration list. The problem occurs when we ngFor the widgets. It happens so fast that the first widget is not yet rendered or loaded . That other widget one from the same Mfe brakes. is it possible to load multiple mfe at the same remoteEntry.js
This is not a issue rather a question. how to consume a component (available at remote) at design time ( without componentFactoryResolver)
exposes: {
"component": ".//src/app/app.component.ts"
}
while importing
import {component} from "mfe@component"
I am getting build error "cannot find module "mfe1@component"
how to consume remotely exposed component at design time
I am using Nx for React.js applications and have nx.json instead of angular.json in my project. How will I be able to use this for such a repository?
After upgrading to @angular/cli to version 11.1.1 this module is not loaded due to the backslash presents in package.json for main and typings
"main": "src\\index.js", "schematics": "./collection.json", "builders": "./builders.json", "dependencies": { "@nrwl/workspace": "^10.3.0", "ngx-build-plus": "^10.0.0", "cross-spawn": "^7.0.3", "json5": "^2.1.3" }, "typings": "src\\index.d.ts", "peerDependencies": {} }
Changing to
"main": "src/index.js", "schematics": "./collection.json", "builders": "./builders.json", "dependencies": { "@nrwl/workspace": "^10.3.0", "ngx-build-plus": "^10.0.0", "cross-spawn": "^7.0.3", "json5": "^2.1.3" }, "typings": "src/index.d.ts", "peerDependencies": {} }
makes the module loadable again.
If agree, I can file a pull request for this fix.
Hi,
I would like to know if there is an option to share individual components like in React using Module federation in Angular.
If yes, can someone please share an example or update the tutorial accordingly.
Thanks.
I am trying to run tests with Karma for Angular 11 and Webpack5, but I get this error for both the shell and the federated app:
Uncaught Error: Shared module is not available for eager consumption
I've found this article which writes about this issue, but I still can't make it work.
https://medium.com/dev-genius/module-federation-advanced-api-inwebpack-5-0-0-beta-17-71cd4d42e534
I have a host app A and a remote app B, both use the same custom shared library C. This library C is in the same monorepo managed by Nx. The module of library C re-exports some common modules (i.e. FormsModule)
During runtime when app B initializes a component with a dependency on such a common module it fails with a NullInjectorError.
This is my webpack config of remote app B
const mf = require("@angular-architects/module-federation/webpack");
const path = require("path");
const sharedMappings = new mf.SharedMappings();
sharedMappings.register(
path.join(__dirname, '../../tsconfig.json'),
['@lib-c/c']);
module.exports = {
output: {
uniqueName: "bsp",
publicPath: "auto"
},
optimization: {
runtimeChunk: false
},
resolve: {
alias: {
...sharedMappings.getAliases(),
}
},
plugins: [
new ModuleFederationPlugin({
// For remotes (please adjust)
name: "bsp",
filename: "remoteEntry.js",
exposes: {
'./Module': './apps/bsp/src/app/bsp.module.ts',
},
shared: {
"@angular/core": {singleton: true, strictVersion: true, requiredVersion: ">=12.0.0" },
"@angular/common": {singleton: true, strictVersion: true, requiredVersion: ">=12.0.0" },
"@angular/common/http": {singleton: true, strictVersion: true, requiredVersion: ">=12.0.0" },
"@angular/router": {singleton: true, strictVersion: true, requiredVersion: ">=12.0.0" },
"@ngx-translate/core": {singleton: true, strictVersion: true},
"@angular/forms": {singleton: true, strictVersion: true},
...sharedMappings.getDescriptors()
}
}),
sharedMappings.getPlugin()
],
};
Hello,
I use your awesome lib to integrate plugin in my Angular application.
But I need to use httpinterceptor for all of my api call, even if call is made by plugin (remote) (for oauth2-oidc).
Is it possible to make this just on shell (host)?
Regards
Damien Trouillet
Hello,
Will it be possible to have a different versions of Angular in each module ?
Core: ng11
Module1: ng11
Module2: ng12
...
Thank's in advance for your answer.
In my container app, I am trying to share a service. However, I get the error "Shared module is not available for eager consumption" even before main.ts starts.
The shared library is a simple Angular library that is in an npm module. I have it configured in my tsconfig.json as
"paths": {
"components-lib": [
"./node_modules/components-lib"
],
"components-lib/*": [
"./node_modules/components-lib/*"
]
and my webpack config:
sharedMappings.register(
path.join(__dirname, 'tsconfig.json'),
['components-lib']);
The service is actually sharing its instance between the apps. However, it is causing other issues such as preventing tailwind styles from loading.
Any thoughts on how to resolve the error? If you would like to see my sample app exhibiting this issue you can have a look at: https://github.com/scottfwalter/mfe
Little background, I am trying to breakup our monolith UI into separate buildable and deployable pieces. Module federation seems like a perfect use case for this.
Problem is, in our current application, there is a shared application state that a lot of the would be micro-frontends rely on. The micro-frontends also have their own piece of the store for their application specific state.
I use StoreModule.forFeature in the remote apps, but get an error NullInjectorError: No provider for ReducerManager!
which is provided when you do StoreModule.forRoot, however, I don't necessarily want to define another root store in the remote app. Is it possible to share the store state with all micro-frontends?
I have a child app wired up through the router:
{
path: 'hello',
loadChildren: () =>
loadRemoteModule({
remoteEntry: 'http://localhost:4201/remoteEntry.js',
remoteName: 'mfe1',
exposedModule: './HelloModule',
}).then((m) => m.HelloModule),
},
If the child app does not the angular libraries in its list of shared libraries it throw the error:
ERROR Error: Uncaught (in promise): Error: inject() must be called from an injection context
injectInjectorOnly@http://localhost:4201/default-src_app_hello_hello_module_ts.js:10890:15
ɵɵinject@http://localhost:4201/default-src_app_hello_hello_module_ts.js:10900:61
RouterModule_Factory@http://localhost:4201/default-src_app_hello_hello_module_ts.js:45267:130
hydrate@http://localhost:5000/node_modules_angular_core___ivy_ngcc___fesm2015_core_js.js:11928:35
The child app works fine on its own but not when consumed through loadRemoteModule. If I add the Angular libraries to the shared webpack config in the shared libraries it will work.
Any reason why I can't have the child app load its own version of the Angular libraries?
Thanks, Scott.
At first, I wanted to say on a new project generated by ng cli it worked correctly, and building process builds files:
In my project, I tried searching difference in configurations to serve files after ng serve command but I couldn't find any sensible difference between them.
I haven't tried custom-webpack builder, previously, with other configuration it has served the files, but I don't know can I use it with ModuleFederationPlugin
My application should be like a shell application like regular monorepo app, but one exception, in one routing I want to get outside the script and load it as micro frontend, currently, I load script on init app in index.html file.
after execute ng serve I see
> ng serve
√ Browser application bundle generation complete.
(node:14020) [DEP_WEBPACK_CHUNK_MODULES_ITERABLE] DeprecationWarning: Chunk.modulesIterable: Use new ChunkGraph API
(node:14020) [DEP_WEBPACK_CHUNK_ENTRY_MODULE] DeprecationWarning: Chunk.entryModule: Use new ChunkGraph API
as you can see it's lack of listing generated files.
package.json
{
"name": "iatfi",
"version": "1.0.0",
"husky": {
"hooks": {
"pre-commit": "lint-staged"
}
},
"lint-staged": {
"**/*.{ts,scss,html}": [
"prettier --write",
"git add"
]
},
"scripts": {
"ng": "ng",
"start": "ng serve",
"start:3200": "ng serve --port=3200",
"build:watch": "ng build --watch=true",
"build:develop-local": "ng build --configuration=local",
"build:develop": "ng build --configuration=develop",
"build:uat": "ng build --configuration=uat",
"build:production": "ng build --configuration=production",
"build:production-maps": "ng build --configuration=production --sourceMap=true",
"build:analize": "ng build --configuration=production --statsJson=true",
"test": "ng test",
"test:coverage": "ng test --coverage",
"test:watch": "ng test --watch",
"lint": "ng lint",
"e2e": "ng e2e",
"prettier": "prettier --write **/*.html **/*.scss **/*.ts",
"prettier-watch": "onchange **/*.ts **/*.scss **/*.html -- prettier --write {{changed}}",
"analize": "webpack-bundle-analyzer ../main/resources/static/dist/stats-es5.json",
"analize2015": "webpack-bundle-analyzer ../main/resources/static/dist/stats-es2015.json",
"postinstall": "ngcc"
},
"private": true,
"resolutions": {
"webpack": "^5.0.0"
},
"dependencies": {
"@angular-architects/module-federation": "^1.2.2",
"@angular-builders/custom-webpack": "^10.0.0",
"@angular-builders/jest": "^10.0.0",
"@angular-devkit/build-angular": "~0.1100.4",
"@angular/animations": "^11.0.4",
"@angular/cli": "^11.0.4",
"@angular/common": "^11.0.4",
"@angular/compiler": "^11.0.4",
"@angular/compiler-cli": "^11.0.4",
"@angular/core": "^11.0.4",
"@angular/forms": "^11.0.4",
"@angular/localize": "^11.0.4",
"@angular/platform-browser": "^11.0.4",
"@angular/platform-browser-dynamic": "^11.0.4",
"@angular/router": "^11.0.4",
"@ng-bootstrap/ng-bootstrap": "^7.0.0",
"@ngx-translate/core": "^13.0.0",
"@ngx-translate/http-loader": "^6.0.0",
"@types/jest": "^24.9.1",
"@types/jquery": "^3.3.31",
"@types/node": "^12.11.1",
"@webcomponents/webcomponentsjs": "^2.4.3",
"angular2-multiselect-dropdown": "^4.6.3",
"bootstrap": "^4.5.2",
"core-js": "^3.6.4",
"d3": "^5.15.0",
"jest": "^26.2.2",
"jest-preset-angular": "^8.2.1",
"jquery": "^3.5.1",
"ngx-cookie-service": "^2.3.0",
"prettier": "^1.19.1",
"rxjs": "^6.6.3",
"tslib": "^2.0.0",
"tslint-angular": "^3.0.2",
"typescript": "~4.0.5",
"zone.js": "~0.10.2"
},
"devDependencies": {
"@angular-builders/dev-server": "^7.3.1",
"@angular-devkit/build-angular": "~0.1100.4",
"@angular/language-service": "^11.0.4",
"@types/d3": "^5.7.2",
"codelyzer": "^6.0.0",
"husky": "^4.3.6",
"lint-staged": "^10.5.3",
"ts-node": "~7.0.0",
"tslint": "~6.1.0",
"webpack-bundle-analyzer": "^3.6.0"
}
}
angular.json
{
"$schema": "./node_modules/@angular/cli/lib/config/schema.json",
"version": 1,
"newProjectRoot": "projects",
"projects": {
"iatfi": {
"projectType": "application",
"schematics": {
"@schematics/angular:component": {
"style": "scss"
}
},
"root": "",
"sourceRoot": "src",
"prefix": "iatfi",
"architect": {
"build": {
"builder": "ngx-build-plus:browser",
"options": {
"outputPath": "../main/resources/static/dist",
"index": "src/index.html",
"main": "src/main.ts",
"polyfills": "src/polyfills.ts",
"tsConfig": "tsconfig.app.json",
"aot": true,
"assets": [
"src/favicon.ico",
"src/assets"
],
"styles": [
"node_modules/bootstrap/dist/css/bootstrap.css",
"node_modules/angular2-multiselect-dropdown/themes/default.theme.css",
"src/from-thymelife-styles.scss",
"src/icons/icons.scss",
"src/styles.scss"
],
"scripts": [],
"extraWebpackConfig": "webpack.config.js"
},
"configurations": {
"production": {
"fileReplacements": [
{
"replace": "src/environments/environment.ts",
"with": "src/environments/environment.prod.ts"
}
],
"optimization": true,
"outputHashing": "media",
"sourceMap": false,
"namedChunks": false,
"extractLicenses": true,
"vendorChunk": true,
"buildOptimizer": true,
"budgets": [
{
"type": "initial",
"maximumWarning": "2mb",
"maximumError": "5mb"
}
],
"extraWebpackConfig": "webpack.prod.config.js"
},
"local": {
"fileReplacements": [
{
"replace": "src/environments/environment.ts",
"with": "src/environments/environment.local.ts"
}
],
"deployUrl": "/iatfi-app/dist/",
"optimization": true,
"outputHashing": "media",
"sourceMap": true,
"namedChunks": true,
"buildOptimizer": false
},
"develop": {
"fileReplacements": [
{
"replace": "src/environments/environment.ts",
"with": "src/environments/environment.dev.ts"
}
],
"vendorChunk": true,
"deployUrl": "/iatfi-app/dist/",
"baseHref": "/iatfi-app",
"optimization": true,
"outputHashing": "media",
"sourceMap": true,
"namedChunks": true,
"aot": true,
"buildOptimizer": false
},
"uat": {
"fileReplacements": [
{
"replace": "src/environments/environment.ts",
"with": "src/environments/environment.uat.ts"
}
],
"optimization": true,
"outputHashing": "media",
"sourceMap": false,
"namedChunks": false,
"aot": true,
"extractLicenses": true,
"vendorChunk": true,
"buildOptimizer": true,
"deployUrl": "/iatfi-app/dist/",
"baseHref": "/iatfi-app",
"budgets": [
{
"type": "initial",
"maximumWarning": "2mb",
"maximumError": "5mb"
}
]
}
}
},
"serve": {
"builder": "ngx-build-plus:dev-server",
"options": {
"browserTarget": "iatfi:build",
"extraWebpackConfig": "webpack.config.js",
"port": 4200
},
"configurations": {
"production": {
"browserTarget": "iatfi:build:production",
"extraWebpackConfig": "webpack.prod.config.js"
}
}
},
"extract-i18n": {
"builder": "@angular-devkit/build-angular:extract-i18n",
"options": {
"browserTarget": "iatfi:build"
}
},
"test": {
"builder": "@angular-builders/jest:run",
"options": {
"main": "src/jestSetup.ts",
"tsConfig": "tsconfig.spec.json"
}
},
"lint": {
"builder": "@angular-devkit/build-angular:tslint",
"options": {
"tsConfig": [
"tsconfig.app.json",
"tsconfig.spec.json",
"e2e/tsconfig.json"
],
"exclude": [
"**/node_modules/**"
]
}
},
"e2e": {
"builder": "@angular-devkit/build-angular:protractor",
"options": {
"protractorConfig": "e2e/protractor.conf.js",
"devServerTarget": "iatfi:serve"
},
"configurations": {
"production": {
"devServerTarget": "iatfi:serve:production"
}
}
}
}
}
},
"defaultProject": "iatfi",
"cli": {
"analytics": false,
"packageManager": "yarn"
}
}
files:
bootstrap.ts, main.ts, webpack.config.js and webpack.prod.config.js are untouched after schematics changed after command ng add @angular-architects/module-federation
Hello, I am encountering an error when using the HttpClient in a federated module. Here is the error:
ERROR Error: Uncaught (in promise): NullInjectorError: R3InjectorError(QaRulesModule)[QaRulesApiService -> QaRulesApiService -> QaRulesApiService -> HttpClient -> HttpClient -> HttpClient]:
NullInjectorError: No provider for HttpClient!
NullInjectorError: R3InjectorError(QaRulesModule)[QaRulesApiService -> QaRulesApiService -> QaRulesApiService -> HttpClient -> HttpClient -> HttpClient]:
NullInjectorError: No provider for HttpClient!
at NullInjector.get (core.js:11027)
at R3Injector.get (core.js:11194)
at R3Injector.get (core.js:11194)
at R3Injector.get (core.js:11194)
at injectInjectorOnly (core.js:4706)
at Module.ɵɵinject (core.js:4710)
at Object.QaRulesApiService_Factory [as factory] (qa-rules-api.service.ts:9)
at R3Injector.hydrate (core.js:11363)
at R3Injector.get (core.js:11183)
at NgModuleRef$1.get (core.js:25238)
at resolvePromise (zone-evergreen.js:1213)
at resolvePromise (zone-evergreen.js:1167)
at zone-evergreen.js:1279
at ZoneDelegate.invokeTask (zone-evergreen.js:406)
at Object.onInvokeTask (core.js:28500)
at ZoneDelegate.invokeTask (zone-evergreen.js:405)
at Zone.runTask (zone-evergreen.js:178)
at drainMicroTaskQueue (zone-evergreen.js:582)
I am not writing my code because the usage is pretty basic and common, just injecting HttpClient in a constructor in the federated module I get this error.
The shell imports HttpClientModule in its app.module, and the federated module has it imported too.
UPDATE
I fixed it by doing this:
@manfredsteyer, is this a correct use?
When using shared library on cli monorepo and register the shared library name with SharedMappings register method.
when serving the app we get the follow warning -
"[DEP_WEBPACK_COMPILATION_ASSETS] DeprecationWarning: Compilation.assets will be frozen in future"
when we made changes in one of the micro frontend application and saved, we get the follow error -
"Conflict: Multiple assets emit different content to the same filename"
the error prevent from the app to re compile the application and the changes doesn't reflected.
used with version 1.2.0 and angular version 11 cli.
Hi,
I'm currently work arround module federation and a microfrontend architecture.
I meet a problem when i want to load remote dynamically. In fact, your plugin (module-federation-plugin) allow us to load module but not web-component like when you expoded the "bootstrap.ts" file. When i try to retrieve the "./web-components" element from the container like this :
const container = window[remoteName];
const factory = await container.get(exposedElement);
const Element = factory();
console.log(Element)
It is empty...
So you have an idea to solve this problem ?
Thanks
I am trying to build a POC for Micro Frontend using Angular and Webpack Module Federation. In this, I have created a shell app and another mfe1 app and rendering that mfe1 on a specific route hit and it is working as expected and rendering the app. Now, I am trying to create another app called mfe2 and render it. In this mfe2, I am creating a web component using Angular elements and rendering that in the shell app. When I do that, I am facing the following issue
Error: A platform with a different configuration has been created. Please destroy it first.
when the following code is executing
import('mfe2/web-component')
.then(_ => console.debug(`element loaded!`))
.catch(err => console.error(`error loading `, err));
I don't understand where the exact issue is. I am adding the required code below.
app.module.ts
@NgModule({
declarations: [
AppComponent
],
imports: [
BrowserModule,
AppRoutingModule
],
providers: [],
bootstrap: []
})
export class AppModule {
constructor(private injector: Injector) {}
ngDoBootstrap() {
const ce = createCustomElement(AppComponent, {injector: this.injector});
customElements.define('mfe2-elem', ce);
}
}
webpack.config.js
module.exports = {
output: {
uniqueName: "mfe2",
publicPath: "auto"
},
optimization: {
runtimeChunk: false
},
resolve: {
alias: {
...sharedMappings.getAliases(),
}
},
plugins: [
new ModuleFederationPlugin({
// For remotes (please adjust)
name: "mfe2",
filename: "remoteEntry.js",
exposes: {
'./web-component': './src/bootstrap.ts',
},
// For hosts (please adjust)
// remotes: {
// "mfe1": "mfe1@http://localhost:3000/remoteEntry.js",
// },
shared: {
"@angular/core": { singleton: true, strictVersion: true },
"@angular/common": { singleton: true, strictVersion: true },
"@angular/common/http": { singleton: true, strictVersion: true },
"@angular/router": { singleton: true, strictVersion: true },
...sharedMappings.getDescriptors()
}
}),
sharedMappings.getPlugin()
],
};
rendering it in a component:
@Component({
selector: 'app-mfe2element',
templateUrl: './mfe2element.component.html',
styleUrls: ['./mfe2element.component.scss']
})
export class Mfe2elementComponent implements AfterContentInit {
@ViewChild('vc', { read: ElementRef, static: true })
vc!: ElementRef;
constructor() { }
ngAfterContentInit(): void {
import('mfe2/web-component')
.then(_ => console.debug(`element loaded!`))
.catch(err => console.error(`error loading `, err));
// await import('mfe1/web-components');
// const element = document.createElement('mfe1-element');
// document.body.appendChild(element);
const element = document.createElement('mfe2-elem');
this.vc.nativeElement.appendChild(element);
}
}
webpack.config.js
module.exports = {
output: {
uniqueName: "shell"
},
optimization: {
// Only needed to bypass a temporary bug
runtimeChunk: false
},
plugins: [
new ModuleFederationPlugin({
// For remotes (please adjust)
// name: "shell",
// filename: "remoteEntry.js",
// exposes: {
// './Component': './/src/app/app.component.ts',
// },
// For hosts (please adjust)
remotes: {
"mfe1": "mfe1@http://localhost:3000/remoteEntry.js",
"mfe2": "mfe2@http://localhost:4000/remoteEntry.js",
},
shared: {
"@angular/core": { singleton: true, strictVersion: false },
"@angular/common": { singleton: true, strictVersion: false },
"@angular/router": { singleton: true, strictVersion: false },
...sharedMappings.getDescriptors()
}
}),
sharedMappings.getPlugin(),
],
};
Please help me solve this issue.
Thanks...
Testing the plugin and trying to build a mircrofrontend. ng serve seems to be getting hung up at:
Generating browser application bundles (phase: building)...
Verbose flag doesn't seem to give any more information on what it's doing.
Any ideas?
In my remote I have:
const ModuleFederationPlugin = require("webpack/lib/container/ModuleFederationPlugin");
const mf = require("@angular-architects/module-federation/webpack");
const path = require("path");
const sharedMappings = new mf.SharedMappings();
sharedMappings.register(
path.join(__dirname, 'tsconfig.json'),
[/* mapped paths to share */]);
module.exports = {
output: {
uniqueName: "mfe1"
},
optimization: {
// Only needed to bypass a temporary bug
runtimeChunk: false
},
plugins: [
new ModuleFederationPlugin({
// For remotes (please adjust)
name: "mfe1",
filename: "remoteEntry.js",
exposes: {
'./Module': './src/app/app.module.ts',
'./Module2': './src/app/helloworld/helloworld.module.ts',
},
// For hosts (please adjust)
// remotes: {
// "mfe1": "mfe1@http://localhost:3000/remoteEntry.js",
// },
shared: {
"@angular/core": { singleton: true, strictVersion: true },
"@angular/common": { singleton: true, strictVersion: true },
"@angular/router": { singleton: true, strictVersion: true },
...sharedMappings.getDescriptors()
}
}),
sharedMappings.getPlugin(),
],
};
and in my host I have
const ModuleFederationPlugin = require("webpack/lib/container/ModuleFederationPlugin");
const mf = require("@angular-architects/module-federation/webpack");
const path = require("path");
const sharedMappings = new mf.SharedMappings();
sharedMappings.register(
path.join(__dirname, 'tsconfig.json'),
[/* mapped paths to share */]);
module.exports = {
output: {
uniqueName: "container-module-federation"
},
optimization: {
// Only needed to bypass a temporary bug
runtimeChunk: false
},
plugins: [
new ModuleFederationPlugin({
// For hosts (please adjust)
remotes: {
"mfe1": "mfe1@http://localhost:4201/remoteEntry.js",
},
shared: {
"@angular/core": { singleton: true, strictVersion: true },
"@angular/common": { singleton: true, strictVersion: true },
"@angular/router": { singleton: true, strictVersion: true },
...sharedMappings.getDescriptors()
}
}),
sharedMappings.getPlugin(),
],
};
When I try to load the module via route:
const routes: Routes = [
{ path: 'hello',
loadChildren: () =>
loadRemoteModule({
remoteEntry: 'http://localhost:4201/remoteEntry.js',
remoteName: 'mfe1',
exposedModule: './Module2'
})
.then(m => m.HelloWorldModule)
}
];
I get the error: Error: Uncaught (in promise): ChunkLoadError: Loading chunk default-src_app_helloworld_helloworld_module_ts failed.
I did notice there are two network requests:
http://localhost:4201/remoteEntry.js (expected)
http://localhost:5000/default-src_app_helloworld_helloworld_module_ts.js (unexpected)
Any ideas on why there would a second network request on my shell app (port 5000)?
We are trying to build a shared library project to be loaded once for every microfrontend.
We followed steps from the blog, and used shared mappings to add the index.ts path as a shared module from tsconfig.json.
The microfrontend builds and works fine with the library, but we expected them to be bundled in separate chunks.
Instead, the library code is built inside the microfrontend chunk.
How can we correctly separate the two bundles?
Hi ,
I am really new to module federation. I have installed this plugin and successfully loaded my Remote(mfe) in Shell.
But I had loaded a static resource in Remote like below , which loads perfectly fine in Remote but failed in Shell.
<img src="assets/sample.jpg">
In Remote it made request with Remote port (4300) http://localhost:4300/assets/sample.jpg and loaded the image successfully but once I loaded this in Shell, request is going for this asset with Shell port(4200).
http://localhost:4200/assets/sample.jpg -- failed.
Is this expected behavior or did I miss something..? I am attaching my Remote and Shell webpack configs
Remote
webpack.config.txt
Shell
webpack.config .txt
I am loading Remote in Shell dynamically
`const routes: Routes = [
{
path: 'flights',
loadChildren: () =>
loadRemoteModule({
remoteEntry: 'http://localhost:4300/remoteEntry.js',
remoteName: 'mfe',
exposedModule: './FlightsModule'
})
.then(m => m.FlightsModule)
}
];`
Hi, ngx-build-plus has no builder for extract-i18n. Please check the possibility of including @angular-builders/custom-webpack instead of ngx-build-plus. Or an option to choose by the user
Currently, the file name of the remote entry (remoteEntry.js in the examples) is fixed. When building the MFE with browser support requiring both es5 (IE) and es2015 (modern browsers) this leads to most chunk files being generated twice (es5 and es2015) but only one remoteEntry.js file. In my case, this happens to be the es2015 variant, which IE does not understand.
From the yarn build log:
Initial Chunk Files | Names | Size
polyfills-es5.8708f858c867e6a0dd1e.js | polyfills-es5 | 196.21 kB
styles-es2015.0a3903fa3827b16066ce.js | styles | 192.21 kB
styles-es5.0a3903fa3827b16066ce.js | styles | 192.21 kB
polyfills-es2015.7a38b8dd65b103288781.js | polyfills | 171.44 kB
remoteEntry_mfe.js | mfe | 15.42 kB // NO es2015
remoteEntry_mfe.js | mfe | 15.38 kB // NO es5
main-es5.63a2713a22969121bd91.js | main | 14.89 kB
main-es2015.63a2713a22969121bd91.js | main | 14.87 kB
In order to enable IE support it would be great if there were a way to have both variants of the remoteEntry.js file and allow the shell to pick the right one depending on which browser is being used.
As a workaround I effectively disabled es2015 by only having IE11 in the .browserslistrc file and setting the target to es5 in the tsconfig.
After executing ng add @angular-architects/module-federation command, live reload not working anymore. Nx based project.
Inf.
os: Ubuntu 20
node: v14.16.1
npm: 7.11.2
yarn: 1.22.5
How do I go about rendering a remote component that has dependencies to it?
Or depends on initialization in the feature module like initializing a state in Ngxs?
Hi,
I have upgraded my project to angular 12 and when I run the below command
ng add @angular-architects/module-federation --project shell --port 4200
I am getting "Mf" schema is using the keyword "id" which its support is deprecated. Use "$id" for schema ID.
Hello @manfredsteyer
I have an issue when I add module-federation-plugin using ng add @angular-architects/module-federation
with nx projects it add webpack.config.js for each project
but when I run npm start I get this issue :
any idea about this plz ?
A declarative, efficient, and flexible JavaScript library for building user interfaces.
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google ❤️ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.