Angular新手请求详解JIT编译的内部工作机制
Hey there! Let's break down exactly how Angular 2's JIT (Just-in-Time) compilation works in the browser, including those two client-side compilation phases you mentioned and why they add that extra performance overhead.
Step 1: Initial Resource Loading
First, the browser pulls in your app's index.html file. This file includes references to:
- Core Angular libraries (like
@angular/core,@angular/platform-browser-dynamic) bundled as JavaScript - Zone.js (Angular's tool for handling change detection and async operations)
- Your app's entry point, usually
main.ts(yes, raw TypeScript!) - A module loader like SystemJS (the standard tool for Angular 2 JIT setups to handle dynamic imports)
Step 2: First Compilation: TypeScript → JavaScript
Since browsers can't run TypeScript natively, the module loader uses a browser-side transpiler (like ts-loader) to convert your .ts files to plain JavaScript right inside the browser. This step handles:
- Converting TypeScript-specific syntax (decorators, type annotations, class-based components) to ES5/ES6 JavaScript that browsers understand
- Resolving import statements to map to the correct Angular library or app files
This is the first source of overhead—transpiling TS to JS uses the user's CPU and memory before your app even starts doing useful work.
Step 3: Bootstrapping the JIT Compiler
Once your main.ts is transpiled to JS, it runs code like this:
import { platformBrowserDynamic } from '@angular/platform-browser-dynamic'; import { AppModule } from './app.module'; platformBrowserDynamic().bootstrapModule(AppModule);
The platformBrowserDynamic() call fires up Angular's full JIT compiler in the browser—this is a heavyweight part of the Angular core that's only included in JIT mode.
Step 4: Second Compilation: Angular Code/Templates → Executable Instructions
This is the most resource-intensive phase. Here's what the JIT compiler does:
- Scans your root
AppModuleand all imported components, directives, pipes, and services - Parses every component's template (either inline
template: ''or externaltemplateUrl) into an abstract syntax tree (AST) - Validates the template: checks for correct directive usage, valid binding syntax, and Angular-specific rules (like ensuring
*ngIfisn't misspelled) - Compiles the template and component class into low-level renderer instructions—binary-like code that tells Angular exactly how to create DOM elements, update data bindings, and manage change detection
- Resolves dependency injection (DI) tokens, creates factory functions for components/services, and wires up the entire app's dependency graph
All of this work happens after the app is loaded in the user's browser, which is why JIT has such a noticeable startup delay—especially for larger apps. The compiler is doing all the heavy lifting of turning your Angular-specific code into runnable instructions on the fly.
Step 5: App Rendering & Interaction
Once compilation finishes, Angular uses the prepped renderer instructions to build the initial DOM, inject required services, and start the change detection cycle. Finally, your app becomes interactive!
Why JIT Adds Extra Performance Overhead
To wrap up the key pain points:
- Dual client-side compilation: Both TS→JS transpilation and Angular's template/code compilation happen in the browser, consuming user device resources
- Bulky compiler bundle: The JIT compiler itself adds significant size to your initial download, increasing load time
- Runtime processing: Parsing, validation, and compilation steps delay the app's first render, which is especially noticeable on low-powered devices or slow networks
This is exactly why AOT (Ahead-of-Time) compilation was introduced—all that compilation work happens during your build process, so the browser only gets pre-compiled instructions and doesn't need to load the JIT compiler at all.
内容的提问来源于stack exchange,提问作者Samuel

