@analogjs/angular-compiler 2.5.0-beta.1 → 2.5.0-beta.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/COMPILER.md +69 -61
- package/package.json +1 -1
- package/src/index.d.ts +1 -0
- package/src/index.js +1 -0
- package/src/index.js.map +1 -1
- package/src/lib/hmr.d.ts +11 -7
- package/src/lib/hmr.js +50 -19
- package/src/lib/hmr.js.map +1 -1
package/COMPILER.md
CHANGED
|
@@ -12,9 +12,9 @@ Peer dependencies: `@angular/compiler` >=19, `@angular/compiler-cli` >=19, `@ang
|
|
|
12
12
|
|
|
13
13
|
## Entry Point
|
|
14
14
|
|
|
15
|
-
| Import | Exports
|
|
16
|
-
| ---------------------------- |
|
|
17
|
-
| `@analogjs/angular-compiler` | `compile()`, `scanFile()`, `scanDtsFile()`, `scanPackageDts()`, `collectImportedPackages()`, `jitTransform()`, `inlineResourceUrls()`, `extractInlineStyles()` | Programmatic compiler API |
|
|
15
|
+
| Import | Exports | Use case |
|
|
16
|
+
| ---------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ------------------------- |
|
|
17
|
+
| `@analogjs/angular-compiler` | `compile()`, `scanFile()`, `scanDtsFile()`, `scanPackageDts()`, `collectImportedPackages()`, `jitTransform()`, `inlineResourceUrls()`, `extractInlineStyles()`, `generateHmrCode()` | Programmatic compiler API |
|
|
18
18
|
|
|
19
19
|
The compiler is integrated into `@analogjs/vite-plugin-angular` via the `experimental.useAnalogCompiler` flag — there is no separate Vite plugin entry point.
|
|
20
20
|
|
|
@@ -121,28 +121,28 @@ The compiler is integrated into `@analogjs/vite-plugin-angular` as an alternativ
|
|
|
121
121
|
2. Inlines external resources (`templateUrl`, `styleUrl`) via OXC AST rewriting before compilation
|
|
122
122
|
3. Compiles each file on-demand with `compile()` during Vite's transform phase (runs with `enforce: 'pre'`)
|
|
123
123
|
4. Strips TypeScript syntax from the output via `vite.transformWithOxc()` (handles `import type`, generics, interfaces, `implements`, etc.)
|
|
124
|
-
5. Appends HMR code for
|
|
124
|
+
5. Appends HMR code for Angular declarations in dev mode (components via `ɵɵreplaceMetadata`, directives/pipes via field-swap + invalidate)
|
|
125
125
|
6. Injects synthetic imports for NgModule-exported classes
|
|
126
126
|
|
|
127
127
|
The existing vite-plugin-angular plugins (build optimizer, router, vitest, etc.) continue to work alongside the analog compiler.
|
|
128
128
|
|
|
129
129
|
## Source Files
|
|
130
130
|
|
|
131
|
-
| File | Purpose
|
|
132
|
-
| --------------------- |
|
|
133
|
-
| `compile.ts` | Single-file AOT compiler: Ivy codegen via `@angular/compiler` APIs
|
|
134
|
-
| `registry.ts` | OXC-based file scanner, extracts selectors, inputs, outputs
|
|
135
|
-
| `metadata.ts` | Decorator metadata extraction (`extractMetadata`, `detectSignals`, `detectFieldDecorators`)
|
|
136
|
-
| `js-emitter.ts` | Angular output AST → JavaScript string emitter (~4x faster than `ts.Printer`)
|
|
137
|
-
| `ast-translator.ts` | Angular output AST → TypeScript AST translator (for complex expressions)
|
|
138
|
-
| `resource-inliner.ts` | OXC-based `templateUrl`/`styleUrl` inlining and inline style extraction
|
|
139
|
-
| `dts-reader.ts` | OXC-based `.d.ts` scanner for pre-compiled Angular packages (selectors, inputs, outputs)
|
|
140
|
-
| `jit-transform.ts` | JIT mode: decorator metadata arrays + constructor DI + signal downleveling + decorator removal
|
|
141
|
-
| `jit-metadata.ts` | JIT metadata helpers (constructor parameters, property decorators)
|
|
142
|
-
| `defer.ts` | `@defer` dependency map builder
|
|
143
|
-
| `hmr.ts` | HMR code generation
|
|
144
|
-
| `styles.ts` | Style preprocessing via Vite's `preprocessCSS` (OXC-based extraction)
|
|
145
|
-
| `utils.ts` | Type-only import detection, class finder, `forwardRef` unwrapper
|
|
131
|
+
| File | Purpose |
|
|
132
|
+
| --------------------- | ----------------------------------------------------------------------------------------------------- |
|
|
133
|
+
| `compile.ts` | Single-file AOT compiler: Ivy codegen via `@angular/compiler` APIs |
|
|
134
|
+
| `registry.ts` | OXC-based file scanner, extracts selectors, inputs, outputs |
|
|
135
|
+
| `metadata.ts` | Decorator metadata extraction (`extractMetadata`, `detectSignals`, `detectFieldDecorators`) |
|
|
136
|
+
| `js-emitter.ts` | Angular output AST → JavaScript string emitter (~4x faster than `ts.Printer`) |
|
|
137
|
+
| `ast-translator.ts` | Angular output AST → TypeScript AST translator (for complex expressions) |
|
|
138
|
+
| `resource-inliner.ts` | OXC-based `templateUrl`/`styleUrl` inlining and inline style extraction |
|
|
139
|
+
| `dts-reader.ts` | OXC-based `.d.ts` scanner for pre-compiled Angular packages (selectors, inputs, outputs) |
|
|
140
|
+
| `jit-transform.ts` | JIT mode: decorator metadata arrays + constructor DI + signal downleveling + decorator removal |
|
|
141
|
+
| `jit-metadata.ts` | JIT metadata helpers (constructor parameters, property decorators) |
|
|
142
|
+
| `defer.ts` | `@defer` dependency map builder |
|
|
143
|
+
| `hmr.ts` | HMR code generation: `ɵɵreplaceMetadata` for components, field-swap + invalidate for directives/pipes |
|
|
144
|
+
| `styles.ts` | Style preprocessing via Vite's `preprocessCSS` (OXC-based extraction) |
|
|
145
|
+
| `utils.ts` | Type-only import detection, class finder, `forwardRef` unwrapper |
|
|
146
146
|
|
|
147
147
|
## What's Supported
|
|
148
148
|
|
|
@@ -267,13 +267,21 @@ The existing vite-plugin-angular plugins (build optimizer, router, vitest, etc.)
|
|
|
267
267
|
|
|
268
268
|
## HMR (Hot Module Replacement)
|
|
269
269
|
|
|
270
|
-
|
|
270
|
+
HMR code is generated by `generateHmrCode()` (exported from `@analogjs/angular-compiler`) and handles all Angular declaration types:
|
|
271
|
+
|
|
272
|
+
**Components** — true HMR via Angular's `ɵɵreplaceMetadata`:
|
|
271
273
|
|
|
272
274
|
1. Vite hot-replaces the module
|
|
273
|
-
2. The `
|
|
274
|
-
3.
|
|
275
|
+
2. The `ɵhmr_` callback dynamically copies all `ɵ`-prefixed static fields from the new class to the old
|
|
276
|
+
3. `ɵɵreplaceMetadata` merges old/new definitions and recreates matching LViews without page reload
|
|
277
|
+
4. File-local Angular class names are passed as local dependencies
|
|
278
|
+
|
|
279
|
+
**Directives and pipes** — field-swap + invalidation:
|
|
280
|
+
|
|
281
|
+
1. The `ɵhmr_` callback copies all `ɵ`-prefixed fields (same dynamic approach)
|
|
282
|
+
2. Since `ɵɵreplaceMetadata` only supports components, the module is invalidated to trigger a full reload
|
|
275
283
|
|
|
276
|
-
Root components (e.g. `App`) fall back to page reload since they can't be hot-replaced without re-bootstrapping
|
|
284
|
+
**Root components** (e.g. `App`) fall back to page reload since they can't be hot-replaced without re-bootstrapping. Non-Angular files use Vite's default HMR.
|
|
277
285
|
|
|
278
286
|
External template and style changes invalidate the parent `.ts` module, triggering re-compilation and HMR. Preprocessed styles are cached by mtime for fast re-compilation.
|
|
279
287
|
|
|
@@ -297,26 +305,26 @@ The `inlineStyleLanguage` option (default: `'scss'`) controls the file extension
|
|
|
297
305
|
|
|
298
306
|
Both produce identical Ivy output because both call the same `@angular/compiler` APIs (`compileComponentFromMetadata`, `parseTemplate`, `compileFactoryFunction`, etc.). The template instructions are byte-for-byte equivalent.
|
|
299
307
|
|
|
300
|
-
| | ngtsc | This compiler
|
|
301
|
-
| ------------------------------- | ---------------------------------------- |
|
|
302
|
-
| Size | ~200,000+ lines | ~2,000 lines
|
|
303
|
-
| Requires `ts.Program` | Yes (reads all files, resolves modules) | No
|
|
304
|
-
| Type checking | Full TS + template type checking | None (use Angular Language Service)
|
|
305
|
-
| Template compilation | Full Ivy instructions | Full Ivy instructions (same APIs)
|
|
306
|
-
| Output format | `ɵɵdefineComponent` (final) | `ɵɵdefineComponent` (final)
|
|
307
|
-
| Global analysis | Via type checker (full scope resolution) | Via tsconfig + OXC registry scan
|
|
308
|
-
| Constructor DI | Full (via type checker) | Full (via AST parameter analysis)
|
|
309
|
-
| `setClassMetadata` | Yes | Yes
|
|
310
|
-
| Source maps | Yes (via TS emitter) | Yes (via MagicString surgical edits + inline string emitter)
|
|
311
|
-
| HMR | Full (with tracking metadata) |
|
|
312
|
-
| `@defer` lazy loading | Yes | Yes
|
|
313
|
-
| SCSS preprocessing | Via `@angular/build` | Via Vite `preprocessCSS` + LmdbCacheStore
|
|
314
|
-
| i18n | Full ICU extraction + localization | Not supported
|
|
315
|
-
| Template type checking | Full (`strictTemplates`) | Not supported
|
|
316
|
-
| Incremental compilation | `ts.Program` reuse | Per-file (Vite handles caching)
|
|
317
|
-
| Diagnostic messages | Hundreds of template/binding errors | Unresolved selector warnings only
|
|
318
|
-
| Partial compilation (libraries) | `ɵɵngDeclareComponent` | Not in scope
|
|
319
|
-
| Declaration files (`.d.ts`) | Yes | Not in scope
|
|
308
|
+
| | ngtsc | This compiler |
|
|
309
|
+
| ------------------------------- | ---------------------------------------- | --------------------------------------------------------------- |
|
|
310
|
+
| Size | ~200,000+ lines | ~2,000 lines |
|
|
311
|
+
| Requires `ts.Program` | Yes (reads all files, resolves modules) | No |
|
|
312
|
+
| Type checking | Full TS + template type checking | None (use Angular Language Service) |
|
|
313
|
+
| Template compilation | Full Ivy instructions | Full Ivy instructions (same APIs) |
|
|
314
|
+
| Output format | `ɵɵdefineComponent` (final) | `ɵɵdefineComponent` (final) |
|
|
315
|
+
| Global analysis | Via type checker (full scope resolution) | Via tsconfig + OXC registry scan |
|
|
316
|
+
| Constructor DI | Full (via type checker) | Full (via AST parameter analysis) |
|
|
317
|
+
| `setClassMetadata` | Yes | Yes |
|
|
318
|
+
| Source maps | Yes (via TS emitter) | Yes (via MagicString surgical edits + inline string emitter) |
|
|
319
|
+
| HMR | Full (with tracking metadata) | Components (full), directives/pipes (invalidate), root (reload) |
|
|
320
|
+
| `@defer` lazy loading | Yes | Yes |
|
|
321
|
+
| SCSS preprocessing | Via `@angular/build` | Via Vite `preprocessCSS` + LmdbCacheStore |
|
|
322
|
+
| i18n | Full ICU extraction + localization | Not supported |
|
|
323
|
+
| Template type checking | Full (`strictTemplates`) | Not supported |
|
|
324
|
+
| Incremental compilation | `ts.Program` reuse | Per-file (Vite handles caching) |
|
|
325
|
+
| Diagnostic messages | Hundreds of template/binding errors | Unresolved selector warnings only |
|
|
326
|
+
| Partial compilation (libraries) | `ɵɵngDeclareComponent` | Not in scope |
|
|
327
|
+
| Declaration files (`.d.ts`) | Yes | Not in scope |
|
|
320
328
|
|
|
321
329
|
#### Performance
|
|
322
330
|
|
|
@@ -413,24 +421,24 @@ This compiler's architecture — single-file transforms using `@angular/compiler
|
|
|
413
421
|
|
|
414
422
|
## Test Suite
|
|
415
423
|
|
|
416
|
-
| File | Tests | Coverage
|
|
417
|
-
| ------------------------------- | ----- |
|
|
418
|
-
| `jit-transform.spec.ts` | 32 | Decorator conversion, member decorator removal (@Input, @Output, @ViewChild, @ContentChild), constructor parameter decorator removal (@Inject, @Optional), constructor DI, signal API downleveling, external resources, edge cases, ReflectionCapabilities integration
|
|
419
|
-
| `integration.spec.ts` |
|
|
420
|
-
| `dts-reader.spec.ts` | 7 | Directive/component/pipe extraction from `.d.ts`, signal inputs, aliased inputs, multiple classes
|
|
421
|
-
| `component.spec.ts` | 48 | All @Component features, signals (including required variants), control flow, defer, pipes, content projection, external resources, resource dependencies, providers, source maps
|
|
422
|
-
| `ast-translator.spec.ts` | 43 | Every AST visitor method (expressions + statements), ngDevMode global
|
|
423
|
-
| `decorator-fields.spec.ts` | 15 | @Input, @Output, @ViewChild, @ContentChild, @HostBinding, @HostListener field decorators
|
|
424
|
-
| `constructor-di.spec.ts` | 8 | Constructor DI: @Inject, @Optional, inheritance, union types, multiple params
|
|
425
|
-
| `error-handling.spec.ts` | 7 | Unknown decorators, undecorated classes, selectorless components, forwardRef, invalid templates
|
|
426
|
-
| `registry.spec.ts` | 6 | All decorator types, multi-declaration, NgModule exports
|
|
427
|
-
| `cross-file-resolution.spec.ts` | 5 | Cross-file component, pipe, directive resolution
|
|
428
|
-
| `ngmodule.spec.ts` | 3 | Compilation, providers, export resolution
|
|
429
|
-
| `injectable.spec.ts` | 3 | `providedIn` variants
|
|
430
|
-
| `directive.spec.ts` | 2 | Host bindings, exportAs
|
|
431
|
-
| `pipe.spec.ts` | 2 | Pure and impure
|
|
432
|
-
| `compile.spec.ts` | 2 | Original smoke tests
|
|
433
|
-
| `conformance.spec.ts` | 161 | Angular compliance test suite (v17-v21, 87%+ Ivy instruction match)
|
|
424
|
+
| File | Tests | Coverage |
|
|
425
|
+
| ------------------------------- | ----- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
|
|
426
|
+
| `jit-transform.spec.ts` | 32 | Decorator conversion, member decorator removal (@Input, @Output, @ViewChild, @ContentChild), constructor parameter decorator removal (@Inject, @Optional), constructor DI, signal API downleveling, external resources, edge cases, ReflectionCapabilities integration |
|
|
427
|
+
| `integration.spec.ts` | 57 | Registry input/output extraction, cross-component binding, constant pool ordering, assignment precedence, templateUrl inlining, content projection, pipe chaining, template refs, two-way binding, computed signals, safe navigation, @defer triggers, @if alias, multi-component files, duplicate i0 prevention, OXC resource inlining, arrow object literal wrapping, .d.ts extraction, signal field preservation, decorator stripping, collectImportedPackages, non-Angular passthrough, template `<style>` merging, NgModule export expansion, member decorator removal, self-referencing components, .d.ts NgModule scanning, TS syntax preservation, lazy dependency arrays, directive compilation, recursive NgModule expansion, circular NgModule handling, HMR code generation (dynamic field copying, component/directive/pipe handling, local deps) |
|
|
428
|
+
| `dts-reader.spec.ts` | 7 | Directive/component/pipe extraction from `.d.ts`, signal inputs, aliased inputs, multiple classes |
|
|
429
|
+
| `component.spec.ts` | 48 | All @Component features, signals (including required variants), control flow, defer, pipes, content projection, external resources, resource dependencies, providers, source maps |
|
|
430
|
+
| `ast-translator.spec.ts` | 43 | Every AST visitor method (expressions + statements), ngDevMode global |
|
|
431
|
+
| `decorator-fields.spec.ts` | 15 | @Input, @Output, @ViewChild, @ContentChild, @HostBinding, @HostListener field decorators |
|
|
432
|
+
| `constructor-di.spec.ts` | 8 | Constructor DI: @Inject, @Optional, inheritance, union types, multiple params |
|
|
433
|
+
| `error-handling.spec.ts` | 7 | Unknown decorators, undecorated classes, selectorless components, forwardRef, invalid templates |
|
|
434
|
+
| `registry.spec.ts` | 6 | All decorator types, multi-declaration, NgModule exports |
|
|
435
|
+
| `cross-file-resolution.spec.ts` | 5 | Cross-file component, pipe, directive resolution |
|
|
436
|
+
| `ngmodule.spec.ts` | 3 | Compilation, providers, export resolution |
|
|
437
|
+
| `injectable.spec.ts` | 3 | `providedIn` variants |
|
|
438
|
+
| `directive.spec.ts` | 2 | Host bindings, exportAs |
|
|
439
|
+
| `pipe.spec.ts` | 2 | Pure and impure |
|
|
440
|
+
| `compile.spec.ts` | 2 | Original smoke tests |
|
|
441
|
+
| `conformance.spec.ts` | 161 | Angular compliance test suite (v17-v21, 87%+ Ivy instruction match) |
|
|
434
442
|
|
|
435
443
|
### Conformance Testing
|
|
436
444
|
|
package/package.json
CHANGED
package/src/index.d.ts
CHANGED
|
@@ -2,4 +2,5 @@ export { compile, type CompileResult, type CompileOptions, } from './lib/compile
|
|
|
2
2
|
export { scanFile, type RegistryEntry, type ComponentRegistry, } from './lib/registry.js';
|
|
3
3
|
export { scanDtsFile, scanPackageDts, collectImportedPackages, } from './lib/dts-reader.js';
|
|
4
4
|
export { jitTransform, type JitTransformResult } from './lib/jit-transform.js';
|
|
5
|
+
export { generateHmrCode } from './lib/hmr.js';
|
|
5
6
|
export { inlineResourceUrls, extractInlineStyles, } from './lib/resource-inliner.js';
|
package/src/index.js
CHANGED
|
@@ -2,5 +2,6 @@ export { compile, } from './lib/compile.js';
|
|
|
2
2
|
export { scanFile, } from './lib/registry.js';
|
|
3
3
|
export { scanDtsFile, scanPackageDts, collectImportedPackages, } from './lib/dts-reader.js';
|
|
4
4
|
export { jitTransform } from './lib/jit-transform.js';
|
|
5
|
+
export { generateHmrCode } from './lib/hmr.js';
|
|
5
6
|
export { inlineResourceUrls, extractInlineStyles, } from './lib/resource-inliner.js';
|
|
6
7
|
//# sourceMappingURL=index.js.map
|
package/src/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../../../packages/angular-compiler/src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,OAAO,GAGR,MAAM,kBAAkB,CAAC;AAC1B,OAAO,EACL,QAAQ,GAGT,MAAM,mBAAmB,CAAC;AAC3B,OAAO,EACL,WAAW,EACX,cAAc,EACd,uBAAuB,GACxB,MAAM,qBAAqB,CAAC;AAC7B,OAAO,EAAE,YAAY,EAA2B,MAAM,wBAAwB,CAAC;AAC/E,OAAO,EACL,kBAAkB,EAClB,mBAAmB,GACpB,MAAM,2BAA2B,CAAC"}
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../../../packages/angular-compiler/src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,OAAO,GAGR,MAAM,kBAAkB,CAAC;AAC1B,OAAO,EACL,QAAQ,GAGT,MAAM,mBAAmB,CAAC;AAC3B,OAAO,EACL,WAAW,EACX,cAAc,EACd,uBAAuB,GACxB,MAAM,qBAAqB,CAAC;AAC7B,OAAO,EAAE,YAAY,EAA2B,MAAM,wBAAwB,CAAC;AAC/E,OAAO,EAAE,eAAe,EAAE,MAAM,cAAc,CAAC;AAC/C,OAAO,EACL,kBAAkB,EAClB,mBAAmB,GACpB,MAAM,2BAA2B,CAAC"}
|
package/src/lib/hmr.d.ts
CHANGED
|
@@ -1,12 +1,16 @@
|
|
|
1
1
|
import type { RegistryEntry } from './registry.js';
|
|
2
2
|
/**
|
|
3
|
-
* Generate HMR code using Angular's ɵɵreplaceMetadata
|
|
3
|
+
* Generate HMR code using Angular's ɵɵreplaceMetadata for components,
|
|
4
|
+
* and simple field-swap + invalidation for directives/pipes.
|
|
4
5
|
*
|
|
5
|
-
* The applyMetadata callback
|
|
6
|
-
*
|
|
7
|
-
*
|
|
8
|
-
* matching LViews in the component tree.
|
|
6
|
+
* The applyMetadata callback dynamically copies all ɵ-prefixed static
|
|
7
|
+
* fields (ɵcmp, ɵfac, ɵdir, ɵpipe, etc.) from the newly compiled class
|
|
8
|
+
* to the old class reference that Angular's runtime is tracking.
|
|
9
9
|
*
|
|
10
|
-
*
|
|
10
|
+
* For components, ɵɵreplaceMetadata then merges the old/new definitions
|
|
11
|
+
* and recreates matching LViews in the component tree.
|
|
12
|
+
*
|
|
13
|
+
* For directives and pipes, ɵɵreplaceMetadata does not support them, so
|
|
14
|
+
* we fall back to a full page reload via import.meta.hot.invalidate().
|
|
11
15
|
*/
|
|
12
|
-
export declare function generateHmrCode(
|
|
16
|
+
export declare function generateHmrCode(declarations: RegistryEntry[], localDepClassNames?: string[]): string;
|
package/src/lib/hmr.js
CHANGED
|
@@ -1,22 +1,33 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* Generate HMR code using Angular's ɵɵreplaceMetadata
|
|
2
|
+
* Generate HMR code using Angular's ɵɵreplaceMetadata for components,
|
|
3
|
+
* and simple field-swap + invalidation for directives/pipes.
|
|
3
4
|
*
|
|
4
|
-
* The applyMetadata callback
|
|
5
|
-
*
|
|
6
|
-
*
|
|
7
|
-
* matching LViews in the component tree.
|
|
5
|
+
* The applyMetadata callback dynamically copies all ɵ-prefixed static
|
|
6
|
+
* fields (ɵcmp, ɵfac, ɵdir, ɵpipe, etc.) from the newly compiled class
|
|
7
|
+
* to the old class reference that Angular's runtime is tracking.
|
|
8
8
|
*
|
|
9
|
-
*
|
|
9
|
+
* For components, ɵɵreplaceMetadata then merges the old/new definitions
|
|
10
|
+
* and recreates matching LViews in the component tree.
|
|
11
|
+
*
|
|
12
|
+
* For directives and pipes, ɵɵreplaceMetadata does not support them, so
|
|
13
|
+
* we fall back to a full page reload via import.meta.hot.invalidate().
|
|
10
14
|
*/
|
|
11
|
-
export function generateHmrCode(
|
|
12
|
-
|
|
13
|
-
const
|
|
15
|
+
export function generateHmrCode(declarations, localDepClassNames = []) {
|
|
16
|
+
const components = declarations.filter((d) => d.kind === 'component');
|
|
17
|
+
const nonComponents = declarations.filter((d) => d.kind !== 'component');
|
|
18
|
+
// Export applyMetadata functions so the accept callback can access them.
|
|
19
|
+
// Dynamically copy all ɵ-prefixed static fields to handle ɵcmp, ɵfac,
|
|
20
|
+
// ɵdir, ɵpipe, ɵmod, ɵinj, ɵprov, and any future Ivy fields.
|
|
21
|
+
const applyFns = declarations
|
|
14
22
|
.map((c) => `
|
|
15
|
-
export function ɵhmr_${c.className}(type
|
|
16
|
-
|
|
17
|
-
|
|
23
|
+
export function ɵhmr_${c.className}(type) {
|
|
24
|
+
for (const key of Object.getOwnPropertyNames(${c.className})) {
|
|
25
|
+
if (key.startsWith('ɵ')) type[key] = ${c.className}[key];
|
|
26
|
+
}
|
|
18
27
|
}`)
|
|
19
28
|
.join('\n');
|
|
29
|
+
// Components: use ɵɵreplaceMetadata for full LView recreation
|
|
30
|
+
const localDepsArray = localDepClassNames.length > 0 ? `[${localDepClassNames.join(', ')}]` : '[]';
|
|
20
31
|
const replaceBlocks = components
|
|
21
32
|
.map((c) => `
|
|
22
33
|
try {
|
|
@@ -24,7 +35,7 @@ export function ɵhmr_${c.className}(type, namespaces) {
|
|
|
24
35
|
${c.className},
|
|
25
36
|
newModule.ɵhmr_${c.className},
|
|
26
37
|
{ i0 },
|
|
27
|
-
|
|
38
|
+
${localDepsArray},
|
|
28
39
|
import.meta,
|
|
29
40
|
"${c.className}"
|
|
30
41
|
);
|
|
@@ -33,16 +44,36 @@ export function ɵhmr_${c.className}(type, namespaces) {
|
|
|
33
44
|
// ɵɵreplaceMetadata failed — will fall back to page reload
|
|
34
45
|
}`)
|
|
35
46
|
.join('\n');
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
47
|
+
// Directives/pipes: swap static fields and invalidate
|
|
48
|
+
const swapBlocks = nonComponents
|
|
49
|
+
.map((c) => `
|
|
50
|
+
try {
|
|
51
|
+
newModule.ɵhmr_${c.className}(${c.className});
|
|
52
|
+
swapped = true;
|
|
53
|
+
} catch(e) {}`)
|
|
54
|
+
.join('\n');
|
|
55
|
+
let acceptBody = `
|
|
56
|
+
if (!newModule) return;`;
|
|
57
|
+
if (components.length > 0) {
|
|
58
|
+
acceptBody += `
|
|
40
59
|
let replaced = false;${replaceBlocks}
|
|
41
60
|
if (!replaced) {
|
|
42
|
-
// Fallback: if no component was successfully replaced (e.g. root component),
|
|
43
|
-
// trigger a full page reload
|
|
44
61
|
import.meta.hot.invalidate('Component HMR failed, reloading');
|
|
62
|
+
return;
|
|
63
|
+
}`;
|
|
64
|
+
}
|
|
65
|
+
if (nonComponents.length > 0) {
|
|
66
|
+
acceptBody += `
|
|
67
|
+
let swapped = false;${swapBlocks}
|
|
68
|
+
if (swapped) {
|
|
69
|
+
// Directive/pipe definitions updated — full reload needed for Angular
|
|
70
|
+
// to pick up the new behavior since ɵɵreplaceMetadata only supports components.
|
|
71
|
+
import.meta.hot.invalidate('Directive/pipe changed, reloading');
|
|
72
|
+
}`;
|
|
45
73
|
}
|
|
74
|
+
return `\n${applyFns}
|
|
75
|
+
if (import.meta.hot) {
|
|
76
|
+
import.meta.hot.accept((newModule) => {${acceptBody}
|
|
46
77
|
});
|
|
47
78
|
}`;
|
|
48
79
|
}
|
package/src/lib/hmr.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"hmr.js","sourceRoot":"","sources":["../../../../../packages/angular-compiler/src/lib/hmr.ts"],"names":[],"mappings":"AAEA
|
|
1
|
+
{"version":3,"file":"hmr.js","sourceRoot":"","sources":["../../../../../packages/angular-compiler/src/lib/hmr.ts"],"names":[],"mappings":"AAEA;;;;;;;;;;;;;GAaG;AACH,MAAM,UAAU,eAAe,CAC7B,YAA6B,EAC7B,qBAA+B,EAAE;IAEjC,MAAM,UAAU,GAAG,YAAY,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,KAAK,WAAW,CAAC,CAAC;IACtE,MAAM,aAAa,GAAG,YAAY,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,KAAK,WAAW,CAAC,CAAC;IAEzE,yEAAyE;IACzE,sEAAsE;IACtE,6DAA6D;IAC7D,MAAM,QAAQ,GAAG,YAAY;SAC1B,GAAG,CACF,CAAC,CAAC,EAAE,EAAE,CAAC;uBACU,CAAC,CAAC,SAAS;iDACe,CAAC,CAAC,SAAS;2CACjB,CAAC,CAAC,SAAS;;EAEpD,CACG;SACA,IAAI,CAAC,IAAI,CAAC,CAAC;IAEd,8DAA8D;IAC9D,MAAM,cAAc,GAClB,kBAAkB,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC,CAAC,IAAI,kBAAkB,CAAC,IAAI,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC,IAAI,CAAC;IAE9E,MAAM,aAAa,GAAG,UAAU;SAC7B,GAAG,CACF,CAAC,CAAC,EAAE,EAAE,CAAC;;;YAGD,CAAC,CAAC,SAAS;2BACI,CAAC,CAAC,SAAS;;YAE1B,cAAc;;aAEb,CAAC,CAAC,SAAS;;;;;QAKhB,CACH;SACA,IAAI,CAAC,IAAI,CAAC,CAAC;IAEd,sDAAsD;IACtD,MAAM,UAAU,GAAG,aAAa;SAC7B,GAAG,CACF,CAAC,CAAC,EAAE,EAAE,CAAC;;yBAEY,CAAC,CAAC,SAAS,IAAI,CAAC,CAAC,SAAS;;oBAE/B,CACf;SACA,IAAI,CAAC,IAAI,CAAC,CAAC;IAEd,IAAI,UAAU,GAAG;4BACS,CAAC;IAE3B,IAAI,UAAU,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;QAC1B,UAAU,IAAI;2BACS,aAAa;;;;MAIlC,CAAC;IACL,CAAC;IAED,IAAI,aAAa,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;QAC7B,UAAU,IAAI;0BACQ,UAAU;;;;;MAK9B,CAAC;IACL,CAAC;IAED,OAAO,KAAK,QAAQ;;2CAEqB,UAAU;;EAEnD,CAAC;AACH,CAAC"}
|