Angular Core Modules Source Code
NgModule Loading and Initialization
NgModule Loading Process:
- Bootstrap Phase:
platformBrowserDynamic().bootstrapModule(AppModule) - Compilation Phase: Compiler compiles templates into view factories
- Instantiation Phase: Creates NgModuleRef and initializes
Key Source Code Points:
// @angular/core/src/application_ref.ts
bootstrapModule<M>(
moduleType: Type<M>,
compilerOptions?: CompilerOptions
): Promise<NgModuleRef<M>> {
// 1. Create compiler factory
const compilerFactory = compiler.getCompilerFactory();
const compiler = compilerFactory.createCompiler([/* compiler options */]);
// 2. Compile NgModule
return compiler.compileModuleAndAllComponentsAsync(moduleType).then(({ ngModuleFactory }) => {
// 3. Create NgModuleRef
const moduleRef = ngModuleFactory.create(injector);
// 4. Initiate change detection
moduleRef.injector.get(ApplicationInitStatus).runInitializers();
moduleRef.injector.get(PlatformRef).tick();
return moduleRef;
});
}NgModule Initialization Order:
- Providers registration
- Declarations processing
- Imports resolution
- Exports handling
- Bootstrap components initialization
Component and Template Compilation Process
Compiler Module Architecture:
Compiler
├── TemplateParser // Parses templates into AST
├── ViewCompiler // Generates view factories
├── StyleCompiler // Compiles styles
└── DirectiveNormalizer // Normalizes directives/pipesTemplate Compilation Process:
// 1. Parse template to generate AST
const templateParser = new TemplateParser(
/* dependency-injected services */
);
const ast = templateParser.parse(template, directives, pipes);
// 2. Generate view factory
const viewCompiler = new ViewCompiler(/* configuration */);
const viewFactory = viewCompiler.compileComponent(
componentType,
ast,
/* other parameters */
);
// 3. Create component view
const componentFactory = new ComponentFactory(
componentType,
viewFactory
);AST Node Types:
ElementAst: Element nodesTextAst: Text nodesBoundEventAst: Event bindingsBoundPropertyAst: Property bindingsReferenceAst: Template reference variables
Dependency Injection Container Implementation
Injector Hierarchy:
NullInjector (root)
├── PlatformInjector
├── AppModuleInjector
└── ComponentInjector
Key Source Code Implementation:
// @angular/core/src/di/injector.ts
class Injector {
get(token: any, notFoundValue?: any): any {
// 1. Check if current Injector has provider
const provider = this._providers.get(token);
if (provider) {
return this._instantiateProvider(provider);
}
// 2. Delegate to parent Injector
if (this._parent) {
return this._parent.get(token, notFoundValue);
}
// 3. Throw error if not found
if (notFoundValue === Injector.THROW_IF_NOT_FOUND) {
throw new Error(`No provider for ${token}`);
}
return notFoundValue;
}
private _instantiateProvider(provider: Provider): any {
// Handle different provider types (ClassProvider, ValueProvider, etc.)
}
}Dependency Resolution Strategies:
- Immediate Resolution: Resolves all dependencies during component initialization
- Deferred Resolution: Uses
@Optional()or@SkipSelf()decorators - Circular Dependency Handling: Resolves via
forwardRef()
Change Detection Mechanism
Change Detection Strategy Comparison:
| Strategy | Trigger Conditions | Performance Characteristics |
|---|---|---|
| Default | Any async event | Full check |
| OnPush | Input changes or event triggers | Partial check |
Change Detection Process:
// @angular/core/src/change_detection/change_detection.ts
function detectChangesInternal(
view: ViewData,
CheckType: CheckType
): void {
// 1. Check if skip is needed (OnPush strategy)
if (view.def.flags & ViewFlags.OnPush &&
!view.state & ViewState.ChecksEnabled) {
return;
}
// 2. Perform change detection
ViewAction.checkNoChangesView(view);
ViewAction.detectChangesView(view);
// 3. Recursively check child views
if (view.child) {
detectChangesInternal(view.child, CheckType);
}
// 4. Check projected views
if (view.projection) {
detectChangesInternal(view.projection, CheckType);
}
}Change Detection Optimizations:
- TrackBy Function: Reduces DOM operations
- Pure Pipes: Caches computation results
- OnPush Strategy: Narrows detection scope
Routing Module Implementation
Route Configuration Parsing:
// @angular/router/src/config/config_loader.ts
class RouterConfigLoader {
load(parentInjector: Injector, route: Route): Promise<Route> {
if (route.loadChildren) {
// Dynamically load feature module
return this.loadModuleFactory(route.loadChildren).then(factory => {
route._loadedConfig = {
module: factory.create(parentInjector).instance,
routes: factory.create(parentInjector).instance.routes
};
return route;
});
}
return Promise.resolve(route);
}
}Route Matching Process:
- URL Parsing: Splits URL into segments
- Path Matching: Matches route configurations in order
- Parameter Extraction: Extracts parameters from URL
- Redirect Handling: Processes redirect routes
- Component Resolution: Loads component factories
Route Guard Execution Order:
CanActivateChildCanActivateResolveCanDeactivate
Angular Compiler Source Code
Template Parsing and AST Generation
Template Parsing Process:
// @angular/compiler/src/template_parser/template_parser.ts
class TemplateParser {
parse(
template: string,
directives: Directive[],
pipes: Pipe[]
): TemplateAst[] {
// 1. Lexical analysis
const tokens = this._lexer.tokenize(template);
// 2. Syntax analysis
const parser = new TemplateParserVisitor(directives, pipes);
return parser.visitAll(tokens);
}
}
// AST node example
class BoundEventAst implements TemplateAst {
name: string; // Event name
target: string; // Event target (optional)
handler: AST; // Event handler expression
phase: EventPhase; // Event phase
}AST Transformation Process:
- Element AST → View Node
- Binding AST → Property/Event Listener
- Directive AST → Directive Instantiation Logic
View Factory Generation and Optimization
View Factory Generation Process:
// @angular/compiler/src/view_compiler/view_compiler.ts
class ViewCompiler {
compileComponent(
component: CompileComponent,
template: TemplateAst[]
): ViewFactory {
// 1. Create view nodes
const viewNodes = this._createViewNodes(template);
// 2. Generate event listeners
const eventListeners = this._generateEventListeners(template);
// 3. Generate binding update code
const updateInstructions = this._generateUpdateInstructions(template);
// 4. Generate view factory function
return new ViewFactory(
viewNodes,
eventListeners,
updateInstructions
);
}
}View Factory Optimization Techniques:
- Static Content Hoisting: Extracts static nodes outside the view
- Binding Code Inlining: Reduces function call overhead
- Directive Merging: Consolidates multiple applications of the same directive
Dynamic Component Compilation and Loading
Dynamic Component Compilation Process:
// @angular/core/src/linker/dynamic_component_loader.ts
class DynamicComponentLoader {
loadNextToLocation(
componentType: Type<any>,
location: ViewContainerRef
): Promise<ComponentRef<any>> {
// 1. Get component factory
const factory = this._compiler.resolveComponentFactory(componentType);
// 2. Create component instance
return location.createComponent(factory);
}
}
// Runtime compilation (deprecated, recommend Ahead-of-Time compilation)
class JitCompiler {
compileModuleAndAllComponentsSync(moduleType: Type<any>): ModuleWithComponentFactories<any> {
// JIT compilation implementation
}
}Dynamic Loading Optimizations:
- Precompilation: Use AOT compilation to reduce runtime overhead
- Lazy Loading: Load feature modules on demand
- Caching: Cache compiled component factories
Directive and Pipe Compilation Process
Directive Compilation Process:
- Directive Normalization: Process
@Directivedecorator metadata - Selector Parsing: Parse CSS selectors
- Lifecycle Hook Registration: Generate hook call code
- Input/Output Binding: Generate property access code
Pipe Compilation Process:
// @angular/compiler/src/expression_parser/ast.ts
class PipeAst implements AST {
name: string; // Pipe name
arg: AST; // Pipe arguments
exp: AST; // Input expression
}
// Pipe transformation code generation
function generatePipeCode(pipe: PipeAst): string {
return `${pipe.exp}.pipe(${pipe.name}(${pipe.arg ? pipe.arg.toString() : ''}))`;
}Directive/Pipe Optimizations:
- Pure Directive Marking: Skips unnecessary change detection
- Pipe Caching: Caches pipe computation results
- Compile-Time Optimization: Inlines simple directive logic
Compiler Performance Optimization
Compilation Optimization Strategies:
- Incremental Compilation: Recompile only changed parts
- Parallel Compilation: Utilize multi-core CPUs
- Caching Mechanism: Cache compilation results
- Lazy Compilation: Defer non-critical compilation tasks
AOT Compilation Advantages:
- Faster Rendering: Reduces runtime compilation overhead
- Smaller Bundle Size: Removes compiler code
- Earlier Error Detection: Catches template errors at compile time
- Better Security: Reduces runtime code generation
Angular Change Detection Source Code
Change Detection Strategy Implementation
OnPush Strategy Implementation:
// @angular/core/src/change_detection/change_detection.ts
class ChangeDetectorRef {
markForCheck(): void {
// Mark current view and ancestors for checking
let current: ViewData|null = this._view;
while (current) {
current.state |= ViewState.CheckOnce;
current = current.parent;
}
}
checkNoChanges(): void {
// Strictly check for no changes
ViewAction.checkNoChangesView(this._view);
}
}Default Strategy Implementation:
class DefaultChangeDetector extends ChangeDetectorRef {
detectChanges(): void {
// Full check of all views
ViewAction.detectChangesView(this._view);
}
}Strategy Selection Recommendations:
- OnPush: Suitable for components with stable input properties
- Default: Suitable for frequently changing components
Change Detection Trigger Mechanism
Trigger Source Categories:
- Event Bindings:
(click)="handler()" - Timers:
setTimeout/setInterval - Promises:
then/catch/finally - RxJS:
Observablesubscriptions
Trigger Process:
// @angular/core/src/util/async.ts
class ApplicationRef {
tick(): void {
// 1. Perform change detection
this._zone.run(() => {
this._changeDetectorRefs.forEach(ref => ref.detectChanges());
});
// 2. Process microtask queue
this._zone.runOutsideAngular(() => {
this._microtaskQueue.forEach(task => task());
});
}
}Trigger Optimizations:
- Debouncing: Merge multiple triggers in a short period
- Batch Updates: Use
NgZoneto batch process async events - Manual Control: Use
detach()/reattach()
Change Detection Optimization Strategies
TrackBy Function Implementation:
// @angular/core/src/change_detection/differs/iterable_differs.ts
class DefaultIterableDiffer implements IterableDiffer<any> {
diff(collection: any[]): any {
if (this._trackByFn) {
// Compare items using trackBy function
return this._diffWithTrackBy(collection);
} else {
// Default full comparison
return this._diffWithoutTrackBy(collection);
}
}
}
// Usage in component
@Component({
template: `
<div *ngFor="let item of items; trackBy: trackById">
{{ item.name }}
</div>
`
})
export class MyComponent {
trackById(index: number, item: any): number {
return item.id;
}
}Pure Pipe Optimization:
// @angular/core/src/pipes/pure_pipe.ts
class PurePipeTransform implements PipeTransform {
private _lastInput: any;
private _lastValue: any;
transform(value: any): any {
if (this._lastInput === value) {
return this._lastValue;
}
this._lastInput = value;
this._lastValue = this._doTransform(value);
return this._lastValue;
}
}Performance Analysis and Tuning
Performance Analysis Tools:
- Angular DevTools: Visualizes change detection cycles
- Chrome Performance Panel: Records performance timelines
- Custom Performance Markers:
console.time('changeDetection'); this.changeDetectorRef.detectChanges(); console.timeEnd('changeDetection');
Tuning Recommendations:
- Reduce Detection Scope: Use OnPush strategy
- Optimize Binding Count: Minimize unnecessary bindings
- Avoid Complex Expressions: Simplify template expressions
- Use trackBy: Optimize ngFor performance
Security and Compatibility
Security Measures:
- XSS Protection: Automatically escapes interpolation expressions
- DOM Sanitization: Safely handles
innerHTML - Style Isolation: Encapsulates component styles
Compatibility Handling:
- Legacy Browser Support: Polyfill services
- IE Compatibility:
classlist/promisepolyfills - Mobile Adaptation: Touch event handling
Change Detection Security Mechanisms:
- Immutable Data: Recommend using immutable data structures
- Pure Functions: Ensure pipes and pure directives have no side effects
- Error Boundaries: Use
ErrorBoundarycomponent to catch exceptions
By deeply understanding Angular’s source architecture, developers can build high-performance, maintainable applications more efficiently and perform precise optimizations when encountering performance bottlenecks.



