AngularElements
A POC of Angular Elements
with zone.js
.
In ng-conf 2018, robwormald described the use cases of Angular Elements
.
-
If the
Angular Elements
is used inside an Angular application, thenzone.js
is already loaded, so user can develop theAngular Elements
in normal way.- Pro: User can develop
Angular Element
just like they develop normalAngular Component
, and user can easily expose a lot of existingAngular Component
toAngular Element
. - Con: In this case, there is a limitation that the
Angular Element
need to run in aAngular App Host
.
- Pro: User can develop
-
If the
Angular Elements
is used inside an non-angular application, such as inside a web app which developed with pure js or jquery or react, then we should not usezone.js
, becausezone.js
will monkey-patch a lot ofglobal/window
APIs such assetTimeout/Promise
, so usingzone.js
will impact the APIs outside ofAngular Elements
. Instead, we usenoop zone
.- Pro: Don't need to worry about
zone.js
, no Window API will be patched, and the bundle size is smaller (zone.js
will be 12k). - Con: User need to take care of
Change Detection
themselves, and existingAngular Component
will not be easily exported asAngular Element
in this way.
- Pro: Don't need to worry about
So my idea is add a 3rd option
.
- if there is a way to let
zone.js
only patchglobal/window
APIs when weenter Angular Elements
andrestore the original delegate
when weexit Angular Elements
. We can developAngular Elements with zone.js
without impact outside world.- Pro: Still has
ngZone
, user can still developAngular Element
just like developing normalAngular Component
. And of course, the existingAngular Component
can easily be exported asAngular Element
. And user don't need to worry aboutzone.js
will impact other parts of the webapp which are outside ofAngular Element
. - Con: User still need to load
zone.js
, which will be12k
bundle.
- Pro: Still has
How it works
- First import
zone.js/dist/zone.js
will not monkey-patch anything untilZone.__init__()
is called. - Call
Zone.__init__()
before bootstrapAngular Elements
. - After
BootStrap
, restore all monkey-patched APIs tonative
one.
try {
Zone.__init__(); // monkey patch window APIs
platformBrowserDynamic()
.bootstrapModule(AppModule)
.then(ref => {
// Ensure Angular destroys itself on hot reloads.
if (window['ngRef']) {
window['ngRef'].destroy();
}
window['ngRef'] = ref;
// Otherise, log the boot error
})
.catch(err => console.error(err));
} finally {
Zone.__unloadAll_patch(); // detach the monkey patch, so all window APIs was restored to native one.
}
- Inside
zone.run()/zone.runGuarded()
,reload all patches
before run andunload all patches
after run.
So monkey patched version of window API only exists inside Angular Elements
Here is the demo link DEMO.
In the demo, there is an angular Element with zone.js, and it will run inside of angular
zone, and outside there is a button Click outside of Angular Element
, click the button will check eventHandler/setTimeout/Promise is monkey patched or not, and print error stack traces to verify no zone related stack frames are inside.