Posted under Angular & Web
Permalink
I have used this pattern here from Manfred Steyer (a Google Developer Expert who has been involved in coding the Angular 8 Ivy release), to allow remote loading of separately developed and packaged Angular Elements, each of which is build like a separate app.
Whilst the application was able to successfully load and display a number of angular elements as separate microapps, the bootstrapping process had issues, manifested with console errors stating ‘zone.js already loaded’.
This post here discusses this kind of issue. Whilst I did not experience the same failure as detailed in the post, it was a related issue.
It has also been raised as an angular issue here.
Rob Wormald’s comment of 14/5/18, after he looked into it, indicated that renaming the global webpackJsonp objects to something unique in each bundle would solve the problem, but was not a recommended solution. From the discussion in the post comments, it looks like Angular 8 and 9 have a better solution to this issue.
I am not yet able to upgrade Angular from the 6.1.7 I am currently using to 8 or 9. PrimeNG has compatibility with the latest Angular version, and also switching to a much later PrimeNG would cause me theming issues as Prime have dropped the legacy theming for a newer, paid for, non open source theme creator, which raises further issues.
As my current work is a POC, I therefore took a pragmatic approach and implemented Rob Wormald’s idea as above. One of the posters in the thread above took this approach using a custom webpack solution as detailed here. I took a similar approach but avoided the custom webpack solution by using a simple NPM post build script, written in javascript, run with Node, which runs after the webpack bundle has been created. The script uses the replace plugin to rename the objects in the files. One reason was that I wanted to be decoupled from any direct webpack customisation via a webpack build plugin as from the comments there can be issues getting this to work depending on the actual Angular version in use. I have seen comments that the angular development team are keen to encapsulate/hide the internals of webpack building to allow them the complete ability to control and change it. In fact this has happened with later angular versions.
Whilst any such solution will be temporary and will need to be swapped out when eventually moving to Angular 9 or later, this solution completely solved the problem, and zone.js was no longer loaded multiple times.
The solution involved the following steps:-
1) Add a postbuild step in package.json, to run the post build script:-
“scripts”: {
“ng”: “ng”,
“start”: “ng serve”,
“prebuild”: “cd src/assets/resources/themes/salient && node-sass theme.scss theme.css –source-map .”,
“build”: “ng build”,
“postbuild”: “node post-build.js”,
The postbuild step is automatically run when you use “npm run build” to do a build. This step edits the built bundle to do the required renaming.
Note also that in the above example I also have a prebuild step, which is used to build SCSS themes which are deployed as static assets outside the bundle, to allow dynamic theme selection. The prebuild step also runs automatically when “npm run build” is done.
2) The post build script uses the npm replace package. Note that using the replace from javascript rather than a CLI command avoids the collision with the standard Windows replace, and also allows a tidier way of handling the various components of the Webpack script bundle. An example of the code follows. Note that as node uses the V8 javascript engine, array maps and lambdas “=>” are available to use:-
var replace = require(“replace”);
/* arguments: Object suffix, project folder name (dist subfolder),
* list of all the generated webpack scripts to be updated */
doWebpackReplace(‘MicroappFabric’,’microapp-fabric-prototype’,
[‘main.js’, ‘polyfills.js’, ‘runtime.js’, ‘styles.js’, ‘vendor.js’]);function doWebpackReplace(name, filename, paths) {
replace({
regex: ‘\\[“webpackJsonp”\\]’,
replacement: `[“webpackJsonp${name}”]`,
paths: paths.map((p) => `dist\\${filename}\\${p}`),
recursive: false,
silent: false,
});
}
3) Make sure the npm file replace package is installed via “npm install –g replace”, and make sure it is listed in the “dependencies” section of package.json:-
“primeng”: “6.1.3”,
“replace”: “^1.1.5”,
“rxjs”: “6.3.2”,
Comments Off on Remote loading of Angular Elements from separate webpack bundle causes unwanted multiple bootstraps