@ngtools/webpack 11.2.1 → 11.2.5
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/package.json +3 -3
- package/src/ivy/host.d.ts +15 -0
- package/src/ivy/host.js +55 -1
- package/src/ivy/plugin.d.ts +2 -0
- package/src/ivy/plugin.js +74 -36
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@ngtools/webpack",
|
|
3
|
-
"version": "11.2.
|
|
3
|
+
"version": "11.2.5",
|
|
4
4
|
"description": "Webpack plugin that AoT compiles your Angular components and modules.",
|
|
5
5
|
"main": "./src/index.js",
|
|
6
6
|
"typings": "src/index.d.ts",
|
|
@@ -25,7 +25,7 @@
|
|
|
25
25
|
},
|
|
26
26
|
"homepage": "https://github.com/angular/angular-cli",
|
|
27
27
|
"dependencies": {
|
|
28
|
-
"@angular-devkit/core": "11.2.
|
|
28
|
+
"@angular-devkit/core": "11.2.5",
|
|
29
29
|
"enhanced-resolve": "5.7.0",
|
|
30
30
|
"webpack-sources": "2.2.0"
|
|
31
31
|
},
|
|
@@ -36,7 +36,7 @@
|
|
|
36
36
|
},
|
|
37
37
|
"engines": {
|
|
38
38
|
"node": ">= 10.13.0",
|
|
39
|
-
"npm": "^6.11.0",
|
|
39
|
+
"npm": "^6.11.0 || ^7.5.6",
|
|
40
40
|
"yarn": ">= 1.13.0"
|
|
41
41
|
}
|
|
42
42
|
}
|
package/src/ivy/host.d.ts
CHANGED
|
@@ -4,6 +4,21 @@ import { WebpackResourceLoader } from '../resource_loader';
|
|
|
4
4
|
export declare function augmentHostWithResources(host: ts.CompilerHost, resourceLoader: WebpackResourceLoader, options?: {
|
|
5
5
|
directTemplateLoading?: boolean;
|
|
6
6
|
}): void;
|
|
7
|
+
/**
|
|
8
|
+
* Augments a TypeScript Compiler Host's resolveModuleNames function to collect dependencies
|
|
9
|
+
* of the containing file passed to the resolveModuleNames function. This process assumes
|
|
10
|
+
* that consumers of the Compiler Host will only call resolveModuleNames with modules that are
|
|
11
|
+
* actually present in a containing file.
|
|
12
|
+
* This process is a workaround for gathering a TypeScript SourceFile's dependencies as there
|
|
13
|
+
* is no currently exposed public method to do so. A BuilderProgram does have a `getAllDependencies`
|
|
14
|
+
* function. However, that function returns all transitive dependencies as well which can cause
|
|
15
|
+
* excessive Webpack rebuilds.
|
|
16
|
+
*
|
|
17
|
+
* @param host The CompilerHost to augment.
|
|
18
|
+
* @param dependencies A Map which will be used to store file dependencies.
|
|
19
|
+
* @param moduleResolutionCache An optional resolution cache to use when the host resolves a module.
|
|
20
|
+
*/
|
|
21
|
+
export declare function augmentHostWithDependencyCollection(host: ts.CompilerHost, dependencies: Map<string, Set<string>>, moduleResolutionCache?: ts.ModuleResolutionCache): void;
|
|
7
22
|
export declare function augmentHostWithNgcc(host: ts.CompilerHost, ngcc: NgccProcessor, moduleResolutionCache?: ts.ModuleResolutionCache): void;
|
|
8
23
|
export declare function augmentHostWithReplacements(host: ts.CompilerHost, replacements: Record<string, string>, moduleResolutionCache?: ts.ModuleResolutionCache): void;
|
|
9
24
|
export declare function augmentHostWithSubstitutions(host: ts.CompilerHost, substitutions: Record<string, string>): void;
|
package/src/ivy/host.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.augmentHostWithCaching = exports.augmentProgramWithVersioning = exports.augmentHostWithVersioning = exports.augmentHostWithSubstitutions = exports.augmentHostWithReplacements = exports.augmentHostWithNgcc = exports.augmentHostWithResources = void 0;
|
|
3
|
+
exports.augmentHostWithCaching = exports.augmentProgramWithVersioning = exports.augmentHostWithVersioning = exports.augmentHostWithSubstitutions = exports.augmentHostWithReplacements = exports.augmentHostWithNgcc = exports.augmentHostWithDependencyCollection = exports.augmentHostWithResources = void 0;
|
|
4
4
|
const crypto_1 = require("crypto");
|
|
5
5
|
const path = require("path");
|
|
6
6
|
const ts = require("typescript");
|
|
@@ -49,6 +49,60 @@ function augmentResolveModuleNames(host, resolvedModuleModifier, moduleResolutio
|
|
|
49
49
|
};
|
|
50
50
|
}
|
|
51
51
|
}
|
|
52
|
+
/**
|
|
53
|
+
* Augments a TypeScript Compiler Host's resolveModuleNames function to collect dependencies
|
|
54
|
+
* of the containing file passed to the resolveModuleNames function. This process assumes
|
|
55
|
+
* that consumers of the Compiler Host will only call resolveModuleNames with modules that are
|
|
56
|
+
* actually present in a containing file.
|
|
57
|
+
* This process is a workaround for gathering a TypeScript SourceFile's dependencies as there
|
|
58
|
+
* is no currently exposed public method to do so. A BuilderProgram does have a `getAllDependencies`
|
|
59
|
+
* function. However, that function returns all transitive dependencies as well which can cause
|
|
60
|
+
* excessive Webpack rebuilds.
|
|
61
|
+
*
|
|
62
|
+
* @param host The CompilerHost to augment.
|
|
63
|
+
* @param dependencies A Map which will be used to store file dependencies.
|
|
64
|
+
* @param moduleResolutionCache An optional resolution cache to use when the host resolves a module.
|
|
65
|
+
*/
|
|
66
|
+
function augmentHostWithDependencyCollection(host, dependencies, moduleResolutionCache) {
|
|
67
|
+
if (host.resolveModuleNames) {
|
|
68
|
+
const baseResolveModuleNames = host.resolveModuleNames;
|
|
69
|
+
host.resolveModuleNames = function (moduleNames, containingFile, ...parameters) {
|
|
70
|
+
const results = baseResolveModuleNames.call(host, moduleNames, containingFile, ...parameters);
|
|
71
|
+
const containingFilePath = paths_1.normalizePath(containingFile);
|
|
72
|
+
for (const result of results) {
|
|
73
|
+
if (result) {
|
|
74
|
+
const containingFileDependencies = dependencies.get(containingFilePath);
|
|
75
|
+
if (containingFileDependencies) {
|
|
76
|
+
containingFileDependencies.add(result.resolvedFileName);
|
|
77
|
+
}
|
|
78
|
+
else {
|
|
79
|
+
dependencies.set(containingFilePath, new Set([result.resolvedFileName]));
|
|
80
|
+
}
|
|
81
|
+
}
|
|
82
|
+
}
|
|
83
|
+
return results;
|
|
84
|
+
};
|
|
85
|
+
}
|
|
86
|
+
else {
|
|
87
|
+
host.resolveModuleNames = function (moduleNames, containingFile, _reusedNames, redirectedReference, options) {
|
|
88
|
+
return moduleNames.map((name) => {
|
|
89
|
+
const result = ts.resolveModuleName(name, containingFile, options, host, moduleResolutionCache, redirectedReference).resolvedModule;
|
|
90
|
+
if (result) {
|
|
91
|
+
const containingFilePath = paths_1.normalizePath(containingFile);
|
|
92
|
+
const containingFileDependencies = dependencies.get(containingFilePath);
|
|
93
|
+
if (containingFileDependencies) {
|
|
94
|
+
containingFileDependencies.add(result.resolvedFileName);
|
|
95
|
+
}
|
|
96
|
+
else {
|
|
97
|
+
dependencies.set(containingFilePath, new Set([result.resolvedFileName]));
|
|
98
|
+
}
|
|
99
|
+
}
|
|
100
|
+
return result;
|
|
101
|
+
});
|
|
102
|
+
};
|
|
103
|
+
}
|
|
104
|
+
}
|
|
105
|
+
exports.augmentHostWithDependencyCollection = augmentHostWithDependencyCollection;
|
|
52
106
|
function augmentHostWithNgcc(host, ngcc, moduleResolutionCache) {
|
|
53
107
|
augmentResolveModuleNames(host, (resolvedModule, moduleName) => {
|
|
54
108
|
if (resolvedModule && ngcc) {
|
package/src/ivy/plugin.d.ts
CHANGED
|
@@ -26,6 +26,7 @@ export declare class AngularWebpackPlugin {
|
|
|
26
26
|
private sourceFileCache?;
|
|
27
27
|
private buildTimestamp;
|
|
28
28
|
private readonly lazyRouteMap;
|
|
29
|
+
private readonly fileDependencies;
|
|
29
30
|
private readonly requiredFilesToEmit;
|
|
30
31
|
private readonly requiredFilesToEmitCache;
|
|
31
32
|
private readonly fileEmitHistory;
|
|
@@ -34,6 +35,7 @@ export declare class AngularWebpackPlugin {
|
|
|
34
35
|
apply(compiler: Compiler & {
|
|
35
36
|
watchMode?: boolean;
|
|
36
37
|
}): void;
|
|
38
|
+
private markResourceUsed;
|
|
37
39
|
private rebuildRequiredFiles;
|
|
38
40
|
private loadConfiguration;
|
|
39
41
|
private updateAotProgram;
|
package/src/ivy/plugin.js
CHANGED
|
@@ -14,6 +14,7 @@ const crypto_1 = require("crypto");
|
|
|
14
14
|
const path = require("path");
|
|
15
15
|
const ts = require("typescript");
|
|
16
16
|
const webpack_1 = require("webpack");
|
|
17
|
+
const lazy_routes_1 = require("../lazy_routes");
|
|
17
18
|
const ngcc_processor_1 = require("../ngcc_processor");
|
|
18
19
|
const paths_plugin_1 = require("../paths-plugin");
|
|
19
20
|
const resource_loader_1 = require("../resource_loader");
|
|
@@ -42,6 +43,7 @@ const PLUGIN_NAME = 'angular-compiler';
|
|
|
42
43
|
class AngularWebpackPlugin {
|
|
43
44
|
constructor(options = {}) {
|
|
44
45
|
this.lazyRouteMap = {};
|
|
46
|
+
this.fileDependencies = new Map();
|
|
45
47
|
this.requiredFilesToEmit = new Set();
|
|
46
48
|
this.requiredFilesToEmitCache = new Map();
|
|
47
49
|
this.fileEmitHistory = new Map();
|
|
@@ -120,6 +122,10 @@ class AngularWebpackPlugin {
|
|
|
120
122
|
if (cache) {
|
|
121
123
|
// Invalidate existing cache based on compiler file timestamps
|
|
122
124
|
changedFiles = cache.invalidate(compiler.fileTimestamps, this.buildTimestamp);
|
|
125
|
+
// Invalidate file dependencies of changed files
|
|
126
|
+
for (const changedFile of changedFiles) {
|
|
127
|
+
this.fileDependencies.delete(paths_1.normalizePath(changedFile));
|
|
128
|
+
}
|
|
123
129
|
}
|
|
124
130
|
else {
|
|
125
131
|
// Initialize a new cache
|
|
@@ -132,6 +138,8 @@ class AngularWebpackPlugin {
|
|
|
132
138
|
this.buildTimestamp = Date.now();
|
|
133
139
|
host_1.augmentHostWithCaching(host, cache);
|
|
134
140
|
const moduleResolutionCache = ts.createModuleResolutionCache(host.getCurrentDirectory(), host.getCanonicalFileName.bind(host), compilerOptions);
|
|
141
|
+
// Setup source file dependency collection
|
|
142
|
+
host_1.augmentHostWithDependencyCollection(host, this.fileDependencies, moduleResolutionCache);
|
|
135
143
|
// Setup on demand ngcc
|
|
136
144
|
host_1.augmentHostWithNgcc(host, ngccProcessor, moduleResolutionCache);
|
|
137
145
|
// Setup resource loading
|
|
@@ -144,7 +152,7 @@ class AngularWebpackPlugin {
|
|
|
144
152
|
host_1.augmentHostWithSubstitutions(host, this.pluginOptions.substitutions);
|
|
145
153
|
// Create the file emitter used by the webpack loader
|
|
146
154
|
const { fileEmitter, builder, internalFiles } = this.pluginOptions.jitMode
|
|
147
|
-
? this.updateJitProgram(compilerOptions, rootNames, host, diagnosticsReporter)
|
|
155
|
+
? this.updateJitProgram(compilerOptions, rootNames, host, diagnosticsReporter, changedFiles)
|
|
148
156
|
: this.updateAotProgram(compilerOptions, rootNames, host, diagnosticsReporter, resourceLoader);
|
|
149
157
|
const allProgramFiles = builder
|
|
150
158
|
.getSourceFiles()
|
|
@@ -165,13 +173,11 @@ class AngularWebpackPlugin {
|
|
|
165
173
|
}
|
|
166
174
|
const currentUnused = new Set(allProgramFiles
|
|
167
175
|
.filter((sourceFile) => !sourceFile.isDeclarationFile)
|
|
168
|
-
.map((sourceFile) => sourceFile.fileName));
|
|
176
|
+
.map((sourceFile) => paths_1.normalizePath(sourceFile.fileName)));
|
|
169
177
|
modules.forEach(({ resource }) => {
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
return;
|
|
178
|
+
if (resource) {
|
|
179
|
+
this.markResourceUsed(paths_1.normalizePath(resource), currentUnused);
|
|
173
180
|
}
|
|
174
|
-
builder.getAllDependencies(sourceFile).forEach((dep) => currentUnused.delete(dep));
|
|
175
181
|
});
|
|
176
182
|
for (const unused of currentUnused) {
|
|
177
183
|
if (previousUnused && previousUnused.has(unused)) {
|
|
@@ -186,6 +192,19 @@ class AngularWebpackPlugin {
|
|
|
186
192
|
compilation[symbol_1.AngularPluginSymbol] = fileEmitter;
|
|
187
193
|
});
|
|
188
194
|
}
|
|
195
|
+
markResourceUsed(normalizedResourcePath, currentUnused) {
|
|
196
|
+
if (!currentUnused.has(normalizedResourcePath)) {
|
|
197
|
+
return;
|
|
198
|
+
}
|
|
199
|
+
currentUnused.delete(normalizedResourcePath);
|
|
200
|
+
const dependencies = this.fileDependencies.get(normalizedResourcePath);
|
|
201
|
+
if (!dependencies) {
|
|
202
|
+
return;
|
|
203
|
+
}
|
|
204
|
+
for (const dependency of dependencies) {
|
|
205
|
+
this.markResourceUsed(paths_1.normalizePath(dependency), currentUnused);
|
|
206
|
+
}
|
|
207
|
+
}
|
|
189
208
|
async rebuildRequiredFiles(modules, compilation, fileEmitter) {
|
|
190
209
|
if (this.requiredFilesToEmit.size === 0) {
|
|
191
210
|
return;
|
|
@@ -319,7 +338,7 @@ class AngularWebpackPlugin {
|
|
|
319
338
|
if (!sourceFile.isDeclarationFile &&
|
|
320
339
|
!ignoreForEmit.has(sourceFile) &&
|
|
321
340
|
!angularCompiler.incrementalDriver.safeToSkipEmit(sourceFile)) {
|
|
322
|
-
this.requiredFilesToEmit.add(sourceFile.fileName);
|
|
341
|
+
this.requiredFilesToEmit.add(paths_1.normalizePath(sourceFile.fileName));
|
|
323
342
|
}
|
|
324
343
|
}
|
|
325
344
|
// NOTE: This can be removed once support for the deprecated lazy route string format is removed
|
|
@@ -328,7 +347,7 @@ class AngularWebpackPlugin {
|
|
|
328
347
|
this.lazyRouteMap[routeKey] = lazyRoute.referencedModule.filePath;
|
|
329
348
|
}
|
|
330
349
|
return this.createFileEmitter(builder, transformation_1.mergeTransformers(angularCompiler.prepareEmit().transformers, transformers), getDependencies, (sourceFile) => {
|
|
331
|
-
this.requiredFilesToEmit.delete(sourceFile.fileName);
|
|
350
|
+
this.requiredFilesToEmit.delete(paths_1.normalizePath(sourceFile.fileName));
|
|
332
351
|
angularCompiler.incrementalDriver.recordSuccessfulEmit(sourceFile);
|
|
333
352
|
});
|
|
334
353
|
});
|
|
@@ -342,7 +361,7 @@ class AngularWebpackPlugin {
|
|
|
342
361
|
internalFiles: ignoreForEmit,
|
|
343
362
|
};
|
|
344
363
|
}
|
|
345
|
-
updateJitProgram(compilerOptions, rootNames, host, diagnosticsReporter) {
|
|
364
|
+
updateJitProgram(compilerOptions, rootNames, host, diagnosticsReporter, changedFiles) {
|
|
346
365
|
const builder = ts.createEmitAndSemanticDiagnosticsBuilderProgram(rootNames, compilerOptions, host, this.builder);
|
|
347
366
|
// Save for next rebuild
|
|
348
367
|
if (this.watchMode) {
|
|
@@ -357,37 +376,56 @@ class AngularWebpackPlugin {
|
|
|
357
376
|
];
|
|
358
377
|
diagnosticsReporter(diagnostics);
|
|
359
378
|
const transformers = transformation_1.createJitTransformers(builder, this.pluginOptions);
|
|
360
|
-
//
|
|
361
|
-
//
|
|
362
|
-
|
|
363
|
-
|
|
364
|
-
|
|
365
|
-
|
|
366
|
-
|
|
367
|
-
|
|
368
|
-
|
|
379
|
+
// Only do a full, expensive Angular compiler string lazy route analysis on the first build
|
|
380
|
+
// `changedFiles` will be undefined on a first build
|
|
381
|
+
if (!changedFiles) {
|
|
382
|
+
// Required to support asynchronous resource loading
|
|
383
|
+
// Must be done before listing lazy routes
|
|
384
|
+
// NOTE: This can be removed once support for the deprecated lazy route string format is removed
|
|
385
|
+
const angularProgram = new program_1.NgtscProgram(rootNames, compilerOptions, host);
|
|
386
|
+
const angularCompiler = angularProgram.compiler;
|
|
387
|
+
const pendingAnalysis = angularCompiler.analyzeAsync().then(() => {
|
|
388
|
+
for (const lazyRoute of angularCompiler.listLazyRoutes()) {
|
|
389
|
+
const [routeKey] = lazyRoute.route.split('#');
|
|
390
|
+
this.lazyRouteMap[routeKey] = lazyRoute.referencedModule.filePath;
|
|
391
|
+
}
|
|
392
|
+
return this.createFileEmitter(builder, transformers, () => []);
|
|
393
|
+
});
|
|
394
|
+
const analyzingFileEmitter = async (file) => {
|
|
395
|
+
const innerFileEmitter = await pendingAnalysis;
|
|
396
|
+
return innerFileEmitter(file);
|
|
397
|
+
};
|
|
398
|
+
return {
|
|
399
|
+
fileEmitter: analyzingFileEmitter,
|
|
400
|
+
builder,
|
|
401
|
+
internalFiles: undefined,
|
|
402
|
+
};
|
|
403
|
+
}
|
|
404
|
+
else {
|
|
405
|
+
// Update lazy route map for changed files using fast but less accurate method
|
|
406
|
+
for (const changedFile of changedFiles) {
|
|
407
|
+
if (!builder.getSourceFile(changedFile)) {
|
|
408
|
+
continue;
|
|
409
|
+
}
|
|
410
|
+
const routes = lazy_routes_1.findLazyRoutes(changedFile, host, builder.getProgram());
|
|
411
|
+
for (const [routeKey, filePath] of Object.entries(routes)) {
|
|
412
|
+
this.lazyRouteMap[routeKey] = filePath;
|
|
413
|
+
}
|
|
369
414
|
}
|
|
370
|
-
return
|
|
371
|
-
|
|
372
|
-
|
|
373
|
-
|
|
374
|
-
|
|
375
|
-
};
|
|
376
|
-
if (this.watchMode) {
|
|
377
|
-
this.ngtscNextProgram = angularProgram;
|
|
415
|
+
return {
|
|
416
|
+
fileEmitter: this.createFileEmitter(builder, transformers, () => []),
|
|
417
|
+
builder,
|
|
418
|
+
internalFiles: undefined,
|
|
419
|
+
};
|
|
378
420
|
}
|
|
379
|
-
return {
|
|
380
|
-
fileEmitter: analyzingFileEmitter,
|
|
381
|
-
builder,
|
|
382
|
-
internalFiles: undefined,
|
|
383
|
-
};
|
|
384
421
|
}
|
|
385
422
|
createFileEmitter(program, transformers = {}, getExtraDependencies, onAfterEmit) {
|
|
386
423
|
return async (file) => {
|
|
387
|
-
|
|
388
|
-
|
|
424
|
+
const filePath = paths_1.normalizePath(file);
|
|
425
|
+
if (this.requiredFilesToEmitCache.has(filePath)) {
|
|
426
|
+
return this.requiredFilesToEmitCache.get(filePath);
|
|
389
427
|
}
|
|
390
|
-
const sourceFile = program.getSourceFile(
|
|
428
|
+
const sourceFile = program.getSourceFile(filePath);
|
|
391
429
|
if (!sourceFile) {
|
|
392
430
|
return undefined;
|
|
393
431
|
}
|
|
@@ -406,10 +444,10 @@ class AngularWebpackPlugin {
|
|
|
406
444
|
if (content !== undefined && this.watchMode) {
|
|
407
445
|
// Capture emit history info for Angular rebuild analysis
|
|
408
446
|
hash = hashContent(content);
|
|
409
|
-
this.fileEmitHistory.set(
|
|
447
|
+
this.fileEmitHistory.set(filePath, { length: content.length, hash });
|
|
410
448
|
}
|
|
411
449
|
const dependencies = [
|
|
412
|
-
...
|
|
450
|
+
...(this.fileDependencies.get(filePath) || []),
|
|
413
451
|
...getExtraDependencies(sourceFile),
|
|
414
452
|
].map(paths_1.externalizePath);
|
|
415
453
|
return { content, map, dependencies, hash };
|