Question presented to candidate: "Explain what Zone.js actually does to the browser when it loads, how Angular used it to know when to update the screen, and then walk me through taking an existing Zone-based app to zoneless."
What a strong answer should cover:
- Monkey-patching: Zone.js replaces async APIs (
setTimeout,setInterval,Promise,addEventListener, XHR,fetch,requestAnimationFrame) with wrappers that turn each call into a task and keep the original under a__zone_symbol__key. - A zone is an execution context that survives async boundaries;
Zone.current.fork({...})adds hooks likeonScheduleTask,onInvokeTask,onHasTask. Task kinds: microTask, macroTask, eventTask. - Angular's
NgZoneis one such fork; when it settles, Zone-based apps run change detection. - Limits: native
async/awaitcannot be patched, so Zone apps need the build to downlevel it; patching costs bundle size and makes stack traces noisier. - Zoneless migration: remove
provideZoneChangeDetection(), removezone.jsfrompolyfills(build and test), move template state to signals ormarkForCheck(), replaceonStable/onMicrotaskEmptylogic, usePendingTasksfor SSR stability. Zoneless is the default since v21.
Clarifying questions expected:
- "Which Angular version is the app on, and does it use OnPush already?"
- "Do any third-party libraries rely on Zone.js-triggered change detection?"
Code / implementation expected: Optional β a forked zone logging its hooks, and the config diff for going zoneless.