-
-
Notifications
You must be signed in to change notification settings - Fork 2k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
fix(component): detect zone.js using instanceof comparison #2547
fix(component): detect zone.js using instanceof comparison #2547
Conversation
Preview docs changes for e8aa70a at https://previews.ngrx.io/pr2547-e8aa70a/ |
@chrisguttandin will you rebase on master, and fix the merge conflicts? |
class NgZone {} | ||
class NoopNgZone {} | ||
class NgZone { | ||
public runOutsideAngular(fn: Function) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
public
not needed, they are public by default
|
||
z.runOutsideAngular(fn); | ||
|
||
return isNgZone; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This feels overly complex.
Would the check for instanceof
work? Or are none of those classes exported?
Also, Zone?.current?.name === 'angular'
might work. Needs a bit of testing, since this is just guessing right now.
@chrisguttandin So this is a good enough check: export function hasZone(z: NgZone): boolean {
return z instanceof NgZone;
} With a little caveat. User might provide their own Alternatively this can be checked: export function hasZone(z: NgZone): boolean {
return !(z instanceof ɵNoopNgZone);
} However this uses "private" API. 🤷♂️ So maybe the first one is good enough. Here are the actual proper tests for describe('hasZone', () => {
async function setup({ defaultZone }: { defaultZone: boolean }) {
@Component({
selector: 'body',
template: '<div></div>',
})
class NgZoneTestComponent {
checkNgZone = hasZone(this.ngZone);
constructor(readonly ngZone: NgZone) {}
}
@NgModule({
declarations: [NgZoneTestComponent],
exports: [NgZoneTestComponent],
bootstrap: [NgZoneTestComponent],
imports: [NoopAnimationsModule],
})
class MyAppModule {}
const platform = getTestBed().platform;
const moduleRef = defaultZone
? await platform.bootstrapModule(MyAppModule)
: await platform.bootstrapModule(MyAppModule, { ngZone: 'noop' });
const appRef = moduleRef.injector.get(ApplicationRef);
const testComp = appRef.components[0].instance;
return { hasZone: testComp.checkNgZone };
}
it('returns false when default zone is used', async () => {
expect(await setup({ defaultZone: true })).toEqual({ hasZone: true });
});
it('returns true when noop zone is chosen', async () => {
expect(await setup({ defaultZone: false })).toEqual({ hasZone: false });
});
}); |
Hi @brandonroberts, hi @alex-okrushko, thanks for your feedback. I just rebased my changes on top of the master branch. That did reduce the number of changes made by this PR as some of the original changes are obsolete now. @alex-okrushko I chose not to use The only argument I have for checking Anyway besides that I don't have a strong preference for either solution. Should I still make the changes you suggested, Alex? What about using an |
We are still pulling it in, so Thanks for working on it @chrisguttandin 👍 |
Now that I updated Should I delete |
Having "dead code" at this point of the library that should be fairly light-weight is surprising. I'd suggest removing
|
Hi @AlexOkrushko I really like the test of ngZone over the component! 👍 My 2 cent on importing zone to check it is i would also go for a method check. Imho the less dependencies on zone related stuff the better. |
Angular is importing |
I updated the code to replace any occurrence of |
Corner case: But both is fine. |
PR Checklist
Please check if your PR fulfills the following requirements:
PR Type
What kind of change does this PR introduce?
What is the current behavior?
Currently the detection of zone.js doesn't work when building a production build with the Angular CLI. The classname of the
NoopNgZone
class doesn't survive the minification.What is the new behavior?
The new detection introduced in this PR uses the fact that
NgZone
callsapply()
on a function that is passed torunOutsideAngular()
. TheNoopNgZone
doesn't do that.https://github.com/angular/angular/blob/master/packages/core/src/zone/ng_zone.ts#L226
https://github.com/angular/angular/blob/master/packages/core/src/zone/ng_zone.ts#L381
Does this PR introduce a breaking change?
Other information
Another approach that I tried is to use
runGuarded()
. TheNgZone
will catch errors while theNoopNgZone
doesn't do that. Therefore something like this will also work.However, when using zone.js the error will still be logged which is probably not wanted.
I'm not sure if this new test will trigger a change detection run when using zone.js. It might be beneficial to memoize the result. Please let me know if you want me to add that functionality.