|
1 |
| -// That's the `global.Zone` exposed when the `zone.js` package is used. |
| 1 | +// This would be exposed in the global environment whenever `zone.js` is |
| 2 | +// included in the `polyfills` configuration property. Starting from Angular 17, |
| 3 | +// users can opt-in to use zoneless change detection. |
2 | 4 | // eslint-disable-next-line @typescript-eslint/no-explicit-any
|
3 | 5 | declare const Zone: any;
|
4 | 6 |
|
5 |
| -// There're 2 types of Angular applications: |
6 |
| -// 1) zone-full (by default) |
7 |
| -// 2) zone-less |
8 |
| -// The developer can avoid importing the `zone.js` package and tells Angular that |
9 |
| -// he is responsible for running the change detection by himself. This is done by |
10 |
| -// "nooping" the zone through `CompilerOptions` when bootstrapping the root module. |
| 7 | +// In Angular 17 and future versions, zoneless support is forthcoming. |
| 8 | +// Therefore, it's advisable to safely check whether the `run` function is |
| 9 | +// available in the `<root>` context. |
11 | 10 | // eslint-disable-next-line @typescript-eslint/no-unsafe-member-access
|
12 |
| -const isNgZoneEnabled = typeof Zone !== 'undefined' && !!Zone.current; |
| 11 | +const runInRoot = typeof Zone !== 'undefined' && Zone.root && Zone.root.run; |
13 | 12 |
|
14 | 13 | /**
|
15 | 14 | * The function that does the same job as `NgZone.runOutsideAngular`.
|
| 15 | + * |
| 16 | + * ⚠️ Note: All of the Sentry functionality called from inside the Angular |
| 17 | + * execution context must be wrapped in this function. Angular's rendering |
| 18 | + * relies on asynchronous tasks being scheduled within its execution context. |
| 19 | + * Since Sentry schedules tasks that do not interact with Angular's rendering, |
| 20 | + * it may prevent Angular from functioning reliably. Consequently, it may disrupt |
| 21 | + * processes such as server-side rendering or client-side hydration. |
16 | 22 | */
|
17 | 23 | export function runOutsideAngular<T>(callback: () => T): T {
|
18 |
| - // The `Zone.root.run` basically will run the `callback` in the most parent zone. |
19 |
| - // Any asynchronous API used inside the `callback` won't catch Angular's zone |
20 |
| - // since `Zone.current` will reference `Zone.root`. |
21 |
| - // The Angular's zone is forked from the `Zone.root`. In this case, `zone.js` won't |
22 |
| - // trigger change detection, and `ApplicationRef.tick()` will not be run. |
23 |
| - // Caretaker note: we're using `Zone.root` except `NgZone.runOutsideAngular` since this |
24 |
| - // will require injecting the `NgZone` facade. That will create a breaking change for |
25 |
| - // projects already using the `@sentry/angular`. |
26 |
| - // eslint-disable-next-line @typescript-eslint/no-unsafe-member-access |
27 |
| - return isNgZoneEnabled ? Zone.root.run(callback) : callback(); |
| 24 | + // Running the `callback` within the root execution context enables Angular |
| 25 | + // processes (such as SSR and hydration) to continue functioning normally without |
| 26 | + // timeouts and delays that could affect the user experience. This approach is |
| 27 | + // necessary because some of the Sentry functionality continues to run in the background. |
| 28 | + return runInRoot ? runInRoot(callback) : callback(); |
28 | 29 | }
|
0 commit comments