Skip to content

Commit 4ce8598

Browse files
committed
docs(migrations): more useful & less sloppy info
1 parent 9f73e1f commit 4ce8598

1 file changed

Lines changed: 26 additions & 36 deletions

File tree

  • projects/igniteui-angular/migrations

projects/igniteui-angular/migrations/README.md

Lines changed: 26 additions & 36 deletions
Original file line numberDiff line numberDiff line change
@@ -4,45 +4,43 @@ This directory hosts the migration schematics that run when consumers execute
44
`ng update igniteui-angular`. Each `update-*` folder is a versioned migration
55
listed in [`migration-collection.json`](./migration-collection.json) and
66
implemented in `update-*/index.ts`. Shared helpers live in
7-
[`common/`](./common). The collection has `"encapsulation": true` so every
8-
migration is loaded in its own isolated CommonJS context by the Angular
9-
schematics tooling.
7+
[`common/`](./common).
108

11-
## Dynamic `@angular/compiler` import via `nativeImport`
9+
See [Wiki pages under Migrations & Schematics](https://github.com/IgniteUI/igniteui-angular/wiki#migrations--schematics)
10+
for authoring and testing guidance.
1211

13-
`@angular/compiler` is an ES module. The migrations themselves are emitted as
14-
CommonJS, so they cannot statically `import` it; they have to use a runtime
15-
dynamic `import()`. To avoid TypeScript downleveling that dynamic call into a
16-
synchronous `require()` (which would crash on an ESM target), the call is
17-
routed through a tiny `.cjs` helper:
12+
## Encapsulation and external ESM like `@angular/compiler`
13+
The collection has `"encapsulation": true` so every
14+
migration is loaded in its own isolated VM context by the Angular
15+
schematics tooling. That also restricts some API access/functionality.
16+
17+
See the description of [#13712 — fix(migrations,ng-add): turn on encapsulation for devkit/schematics deps](https://github.com/IgniteUI/igniteui-angular/pull/13712) when encapsulation was first enabled for mechanism details.
18+
19+
### Dynamic `@angular/compiler` import via `nativeImport`
20+
21+
`@angular/compiler` is an ES module. The migrations themselves are emitted and consumed
22+
(`require()`-d) by the Angular schematics as CommonJS, so they cannot statically `import` it;
23+
they have to use a runtime dynamic `import()`.
1824

1925
- [`common/import-helper.cts`](./common/import-helper.cts) — authored as
20-
a TypeScript CJS module. The dynamic `import()` is preserved in the emitted
21-
[`common/import-helper.cjs`](./common/import-helper.cjs) because the file's
22-
forced `.cjs` extension prevents the compiler from rewriting it.
26+
a TypeScript CJS module. The dynamic `import()` is preserved in the emitted.
2327
- Migrations call it via:
2428
```ts
2529
import { nativeImport } from 'igniteui-angular/migrations/common/import-helper.cjs';
2630
// ...
27-
const { HtmlParser } = await nativeImport<typeof import('@angular/compiler')>(
28-
'@angular/compiler'
29-
);
31+
const { HtmlParser } = await nativeImport('@angular/compiler');
3032
```
3133

3234
### Why the bare `igniteui-angular/...` specifier
3335

34-
Schematics encapsulation (`"encapsulation": true` in
35-
[`migration-collection.json`](./migration-collection.json)) wraps every
36-
migration in a sandboxed module loader. Relative requires (`../common/...`)
37-
go through that wrapper and the dynamic `import()` ends up being intercepted
38-
and converted by the wrapper, defeating the purpose of the helper. A **bare
39-
package specifier** bypasses the wrapper because the wrapper only encapsulates
40-
the migration's own files, not requires that resolve to a real package.
36+
Schematics encapsulation being a VM execution is affected by the
37+
[Support of dynamic import() in compilation APIs](https://nodejs.org/api/vm.html#support-of-dynamic-import-in-compilation-apis)
38+
and at this time Angular schematics do not implement [importModuleDynamically](https://github.com/angular/angular-cli/blob/e5eb3e37c9756669b3b91b5b681a73cc9b616cb9/packages/angular/cli/src/command-builder/utilities/schematic-engine-host.ts#L50).
4139

42-
This is the trick PR
43-
[#13712 — fix(migrations,ng-add): turn on encapsulation for devkit/schematics deps](https://github.com/IgniteUI/igniteui-angular/pull/13712)
44-
introduced when encapsulation was first enabled. Every migration that needs
45-
`@angular/compiler` follows the same pattern.
40+
A **bare package specifier** effectively passes through the schematics host encapsulation again and escapes [the relative wrapping ](https://github.com/angular/angular-cli/blob/e5eb3e37c9756669b3b91b5b681a73cc9b616cb9/packages/angular/cli/src/command-builder/utilities/schematic-engine-host.ts#L177-L178) out into [the original schematic require](https://github.com/angular/angular-cli/blob/e5eb3e37c9756669b3b91b5b681a73cc9b616cb9/packages/angular/cli/src/command-builder/utilities/schematic-engine-host.ts#L203-L204).
41+
This means just the `import-helper.cjs` script is ran outside of encapsulation and as such can perform dynamic imports.
42+
43+
Every migration that needs `@angular/compiler` follows the same pattern.
4644

4745
To keep TypeScript happy with the bare specifier at compile time,
4846
[`tsconfig.json`](./tsconfig.json) maps it back to the source:
@@ -57,7 +55,7 @@ To keep TypeScript happy with the bare specifier at compile time,
5755
At consumer install time the specifier resolves naturally through their
5856
`node_modules/igniteui-angular/migrations/common/import-helper.cjs`.
5957

60-
## Running migration tests locally
58+
### Tests setup for the bare specifier
6159

6260
`npm run test:schematics` compiles the migrations with
6361
[`tsconfig.spec.json`](./tsconfig.spec.json) into `dist/igniteui-angular/...`
@@ -69,12 +67,7 @@ would not resolve at runtime.
6967
[`tsconfig-paths-bootstrap.js`](./tsconfig-paths-bootstrap.js) fixes that. It
7068
is loaded with `node --require` before Jasmine starts and installs a runtime
7169
path map (via the `tsconfig-paths` package) that points
72-
`igniteui-angular/*` at `dist/igniteui-angular/*`. The bootstrap deliberately
73-
does **not** read [`tsconfig.json`](./tsconfig.json) because:
74-
75-
- the compile-time map targets source under `../*` (i.e. `.ts` / `.cts`),
76-
which Jasmine cannot execute;
77-
- the runtime map must point at the compiled output in `dist/`.
70+
`igniteui-angular/*` at `./dist/igniteui-angular/*`.
7871

7972
The wiring in [`package.json`](../../../package.json) looks like:
8073

@@ -84,6 +77,3 @@ node -r ./projects/igniteui-angular/migrations/tsconfig-paths-bootstrap.js \
8477
"dist/igniteui-angular/migrations/**/*.spec.js" \
8578
"dist/igniteui-angular/schematics/**/*.spec.js"
8679
```
87-
88-
This setup is internal to the repo's test runner; published migrations are
89-
unaffected and rely on the consumer's regular `node_modules` resolution.

0 commit comments

Comments
 (0)