I would like to know if it is possible to use different angular elements (custom elements) built with different versions of Angular. I have heard that zone.js was polluting the global scope.
Thanks for your answer.
I would like to know if it is possible to use different angular elements (custom elements) built with different versions of Angular. I have heard that zone.js was polluting the global scope.
Thanks for your answer.
Yes, you have heard it correct. We cannot use multiple angular elements if each angular element created from a specific version is trying to load zonejs.
Having said that it is 100% possible to have multiple angular elements of different versions on a single page. All we need to take care of is loading zone js only once and sharing it across all the web-components(Angular Elements).
While bootstrapping multiple elements we can add the logic of not loading/patching zonejs if already loaded as below:
Remove zonejs polyfill from polyfill.ts for all Angular Elements
Create a file in main.ts
level. Let's say bootstraper.ts :
export class Bootstrapper {
constructor(
private bootstrapFunction: (bootstrapper: Bootstrapper) => void
) {}
/**
* Before bootstrapping the app, we need to determine if Zone has already
* been loaded and if not, load it before bootstrapping the application.
*/
startup(): void {
console.log('NG: Bootstrapping app...');
if (!window['Zone']) {
// we need to load zone.js
console.group('Zone: has not been loaded. Loading now...');
// This is the minified version of zone
const zoneFile = `/some/shared/location/zone.min.js`;
const filesToLoad = [zoneFile];
const req = window['require'];
if (typeof req !== 'undefined') {
req(filesToLoad, () => {
this.bootstrapFunction(this);
console.groupEnd();
});
} else {
let sequence: Promise<any> = Promise.resolve();
filesToLoad.forEach((file: string) => {
sequence = sequence.then(() => {
return this.loadScript(file);
});
});
sequence.then(
() => {
this.bootstrapFunction(this);
console.groupEnd();
},
(error: any) => {
console.error('Error occurred loading necessary files', error);
console.groupEnd();
}
);
}
} else {
// zone already exists
this.bootstrapFunction(this);
}
}
/**
* Loads a script and adds it to the head.
* @param fileName
* @returns a Promise that will resolve with the file name
*/
loadScript(fileName: string): Promise<any> {
return new Promise(resolve => {
console.log('Zone: Loading file... ' + fileName);
const script = document.createElement('script');
script.src = fileName;
script.type = 'text/javascript';
script.onload = () => {
console.log('\tDone');
resolve(fileName);
};
document.getElementsByTagName('head')[0].appendChild(script);
});
}
}
And in main.ts
we can change the bootstrap logic to the below one :
import { enableProdMode } from '@angular/core';
import { platformBrowserDynamic } from '@angular/platform-browser-dynamic';
import { AppModule } from './app/app.module';
import { Bootstrapper } from './bootstraper';
const bootstrapApp = function(): void {
platformBrowserDynamic()
.bootstrapModule(AppModule)
.then(() => {})
.catch(err => console.error(err));
};
const bootstrapper = new Bootstrapper(bootstrapApp);
bootstrapper.startup();
This way we can definitely create multiple Angular Elements (Web Components) and use in a SPA.
Thanks
© 2022 - 2024 — McMap. All rights reserved.