@ngtools/webpack 12.0.0-rc.3 → 12.0.3
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.js +1 -1
- package/src/ivy/plugin.js +43 -31
- package/src/resource_loader.d.ts +2 -2
- package/src/resource_loader.js +42 -20
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@ngtools/webpack",
|
|
3
|
-
"version": "12.0.
|
|
3
|
+
"version": "12.0.3",
|
|
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",
|
|
@@ -28,12 +28,12 @@
|
|
|
28
28
|
"enhanced-resolve": "5.7.0"
|
|
29
29
|
},
|
|
30
30
|
"peerDependencies": {
|
|
31
|
-
"@angular/compiler-cli": "^12.0.0
|
|
31
|
+
"@angular/compiler-cli": "^12.0.0",
|
|
32
32
|
"typescript": "~4.2.3",
|
|
33
33
|
"webpack": "^5.30.0"
|
|
34
34
|
},
|
|
35
35
|
"engines": {
|
|
36
|
-
"node": "^12.14.1 ||
|
|
36
|
+
"node": "^12.14.1 || >=14.0.0",
|
|
37
37
|
"npm": "^6.11.0 || ^7.5.6",
|
|
38
38
|
"yarn": ">= 1.13.0"
|
|
39
39
|
}
|
package/src/ivy/host.js
CHANGED
|
@@ -42,7 +42,7 @@ function augmentHostWithResources(host, resourceLoader, options = {}) {
|
|
|
42
42
|
return null;
|
|
43
43
|
}
|
|
44
44
|
if (options.inlineStyleMimeType) {
|
|
45
|
-
const content = await resourceLoader.process(data, options.inlineStyleMimeType);
|
|
45
|
+
const content = await resourceLoader.process(data, options.inlineStyleMimeType, context.type, context.containingFile);
|
|
46
46
|
return { content };
|
|
47
47
|
}
|
|
48
48
|
return null;
|
package/src/ivy/plugin.js
CHANGED
|
@@ -171,8 +171,9 @@ class AngularWebpackPlugin {
|
|
|
171
171
|
if (internalFiles === null || internalFiles === void 0 ? void 0 : internalFiles.has(sourceFile)) {
|
|
172
172
|
continue;
|
|
173
173
|
}
|
|
174
|
-
// Ensure all program files are considered part of the compilation and will be watched
|
|
175
|
-
|
|
174
|
+
// Ensure all program files are considered part of the compilation and will be watched.
|
|
175
|
+
// Webpack does not normalize paths. Therefore, we need to normalize the path with FS seperators.
|
|
176
|
+
compilation.fileDependencies.add(paths_1.externalizePath(sourceFile.fileName));
|
|
176
177
|
// Add all non-declaration files to the initial set of unused files. The set will be
|
|
177
178
|
// analyzed and pruned after all Webpack modules are finished building.
|
|
178
179
|
if (!sourceFile.isDeclarationFile) {
|
|
@@ -258,7 +259,7 @@ class AngularWebpackPlugin {
|
|
|
258
259
|
this.requiredFilesToEmitCache.clear();
|
|
259
260
|
}
|
|
260
261
|
loadConfiguration(compilation) {
|
|
261
|
-
const { options: compilerOptions, rootNames, errors } = compiler_cli_1.readConfiguration(this.pluginOptions.tsconfig, this.pluginOptions.compilerOptions);
|
|
262
|
+
const { options: compilerOptions, rootNames, errors, } = compiler_cli_1.readConfiguration(this.pluginOptions.tsconfig, this.pluginOptions.compilerOptions);
|
|
262
263
|
compilerOptions.enableIvy = true;
|
|
263
264
|
compilerOptions.noEmitOnError = false;
|
|
264
265
|
compilerOptions.suppressOutputPathCheck = true;
|
|
@@ -287,39 +288,46 @@ class AngularWebpackPlugin {
|
|
|
287
288
|
// The wrapped host inside NgtscProgram adds additional files that will not have versions.
|
|
288
289
|
const typeScriptProgram = angularProgram.getTsProgram();
|
|
289
290
|
host_1.augmentProgramWithVersioning(typeScriptProgram);
|
|
290
|
-
|
|
291
|
-
// Save for next rebuild
|
|
291
|
+
let builder;
|
|
292
292
|
if (this.watchMode) {
|
|
293
|
-
this.builder = builder;
|
|
293
|
+
builder = this.builder = ts.createEmitAndSemanticDiagnosticsBuilderProgram(typeScriptProgram, host, this.builder);
|
|
294
294
|
this.ngtscNextProgram = angularProgram;
|
|
295
295
|
}
|
|
296
|
+
else {
|
|
297
|
+
// When not in watch mode, the startup cost of the incremental analysis can be avoided by
|
|
298
|
+
// using an abstract builder that only wraps a TypeScript program.
|
|
299
|
+
builder = ts.createAbstractBuilder(typeScriptProgram, host);
|
|
300
|
+
}
|
|
296
301
|
// Update semantic diagnostics cache
|
|
297
302
|
const affectedFiles = new Set();
|
|
298
|
-
//
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
|
|
307
|
-
|
|
308
|
-
|
|
309
|
-
|
|
310
|
-
|
|
311
|
-
|
|
312
|
-
|
|
313
|
-
|
|
303
|
+
// Analyze affected files when in watch mode for incremental type checking
|
|
304
|
+
if ('getSemanticDiagnosticsOfNextAffectedFile' in builder) {
|
|
305
|
+
// eslint-disable-next-line no-constant-condition
|
|
306
|
+
while (true) {
|
|
307
|
+
const result = builder.getSemanticDiagnosticsOfNextAffectedFile(undefined, (sourceFile) => {
|
|
308
|
+
// If the affected file is a TTC shim, add the shim's original source file.
|
|
309
|
+
// This ensures that changes that affect TTC are typechecked even when the changes
|
|
310
|
+
// are otherwise unrelated from a TS perspective and do not result in Ivy codegen changes.
|
|
311
|
+
// For example, changing @Input property types of a directive used in another component's
|
|
312
|
+
// template.
|
|
313
|
+
if (ignoreForDiagnostics.has(sourceFile) &&
|
|
314
|
+
sourceFile.fileName.endsWith('.ngtypecheck.ts')) {
|
|
315
|
+
// This file name conversion relies on internal compiler logic and should be converted
|
|
316
|
+
// to an official method when available. 15 is length of `.ngtypecheck.ts`
|
|
317
|
+
const originalFilename = sourceFile.fileName.slice(0, -15) + '.ts';
|
|
318
|
+
const originalSourceFile = builder.getSourceFile(originalFilename);
|
|
319
|
+
if (originalSourceFile) {
|
|
320
|
+
affectedFiles.add(originalSourceFile);
|
|
321
|
+
}
|
|
322
|
+
return true;
|
|
314
323
|
}
|
|
315
|
-
return
|
|
324
|
+
return false;
|
|
325
|
+
});
|
|
326
|
+
if (!result) {
|
|
327
|
+
break;
|
|
316
328
|
}
|
|
317
|
-
|
|
318
|
-
});
|
|
319
|
-
if (!result) {
|
|
320
|
-
break;
|
|
329
|
+
affectedFiles.add(result.affected);
|
|
321
330
|
}
|
|
322
|
-
affectedFiles.add(result.affected);
|
|
323
331
|
}
|
|
324
332
|
// Collect non-semantic diagnostics
|
|
325
333
|
const diagnostics = [
|
|
@@ -399,10 +407,14 @@ class AngularWebpackPlugin {
|
|
|
399
407
|
};
|
|
400
408
|
}
|
|
401
409
|
updateJitProgram(compilerOptions, rootNames, host, diagnosticsReporter) {
|
|
402
|
-
|
|
403
|
-
// Save for next rebuild
|
|
410
|
+
let builder;
|
|
404
411
|
if (this.watchMode) {
|
|
405
|
-
this.builder = builder;
|
|
412
|
+
builder = this.builder = ts.createEmitAndSemanticDiagnosticsBuilderProgram(rootNames, compilerOptions, host, this.builder);
|
|
413
|
+
}
|
|
414
|
+
else {
|
|
415
|
+
// When not in watch mode, the startup cost of the incremental analysis can be avoided by
|
|
416
|
+
// using an abstract builder that only wraps a TypeScript program.
|
|
417
|
+
builder = ts.createAbstractBuilder(rootNames, compilerOptions, host);
|
|
406
418
|
}
|
|
407
419
|
const diagnostics = [
|
|
408
420
|
...builder.getOptionsDiagnostics(),
|
package/src/resource_loader.d.ts
CHANGED
|
@@ -11,7 +11,7 @@ export declare class WebpackResourceLoader {
|
|
|
11
11
|
private _fileDependencies;
|
|
12
12
|
private _reverseDependencies;
|
|
13
13
|
private fileCache?;
|
|
14
|
-
private
|
|
14
|
+
private assetCache?;
|
|
15
15
|
private modifiedResources;
|
|
16
16
|
private outputPathCounter;
|
|
17
17
|
constructor(shouldCache: boolean);
|
|
@@ -24,5 +24,5 @@ export declare class WebpackResourceLoader {
|
|
|
24
24
|
private _compile;
|
|
25
25
|
private _evaluate;
|
|
26
26
|
get(filePath: string): Promise<string>;
|
|
27
|
-
process(data: string, mimeType: string): Promise<string>;
|
|
27
|
+
process(data: string, mimeType: string, resourceType: 'template' | 'style', containingFile?: string): Promise<string>;
|
|
28
28
|
}
|
package/src/resource_loader.js
CHANGED
|
@@ -21,24 +21,37 @@ class WebpackResourceLoader {
|
|
|
21
21
|
this.outputPathCounter = 1;
|
|
22
22
|
if (shouldCache) {
|
|
23
23
|
this.fileCache = new Map();
|
|
24
|
-
this.
|
|
24
|
+
this.assetCache = new Map();
|
|
25
25
|
}
|
|
26
26
|
}
|
|
27
27
|
update(parentCompilation, changedFiles) {
|
|
28
|
-
var _a, _b;
|
|
28
|
+
var _a, _b, _c, _d, _e;
|
|
29
29
|
this._parentCompilation = parentCompilation;
|
|
30
30
|
// Update resource cache and modified resources
|
|
31
31
|
this.modifiedResources.clear();
|
|
32
32
|
if (changedFiles) {
|
|
33
33
|
for (const changedFile of changedFiles) {
|
|
34
|
+
const changedFileNormalized = paths_1.normalizePath(changedFile);
|
|
35
|
+
(_a = this.assetCache) === null || _a === void 0 ? void 0 : _a.delete(changedFileNormalized);
|
|
34
36
|
for (const affectedResource of this.getAffectedResources(changedFile)) {
|
|
35
|
-
|
|
37
|
+
const affectedResourceNormalized = paths_1.normalizePath(affectedResource);
|
|
38
|
+
(_b = this.fileCache) === null || _b === void 0 ? void 0 : _b.delete(affectedResourceNormalized);
|
|
36
39
|
this.modifiedResources.add(affectedResource);
|
|
40
|
+
for (const effectedDependencies of this.getResourceDependencies(affectedResourceNormalized)) {
|
|
41
|
+
(_c = this.assetCache) === null || _c === void 0 ? void 0 : _c.delete(paths_1.normalizePath(effectedDependencies));
|
|
42
|
+
}
|
|
37
43
|
}
|
|
38
44
|
}
|
|
39
45
|
}
|
|
40
46
|
else {
|
|
41
|
-
(
|
|
47
|
+
(_d = this.fileCache) === null || _d === void 0 ? void 0 : _d.clear();
|
|
48
|
+
(_e = this.assetCache) === null || _e === void 0 ? void 0 : _e.clear();
|
|
49
|
+
}
|
|
50
|
+
// Re-emit all assets for un-effected files
|
|
51
|
+
if (this.assetCache) {
|
|
52
|
+
for (const [, { name, source, info }] of this.assetCache) {
|
|
53
|
+
this._parentCompilation.emitAsset(name, source, info);
|
|
54
|
+
}
|
|
42
55
|
}
|
|
43
56
|
}
|
|
44
57
|
clearParentCompilation() {
|
|
@@ -56,12 +69,14 @@ class WebpackResourceLoader {
|
|
|
56
69
|
setAffectedResources(file, resources) {
|
|
57
70
|
this._reverseDependencies.set(file, new Set(resources));
|
|
58
71
|
}
|
|
59
|
-
async _compile(filePath, data, mimeType) {
|
|
72
|
+
async _compile(filePath, data, mimeType, resourceType, containingFile) {
|
|
60
73
|
if (!this._parentCompilation) {
|
|
61
74
|
throw new Error('WebpackResourceLoader cannot be used without parentCompilation');
|
|
62
75
|
}
|
|
63
76
|
// Create a special URL for reading the resource from memory
|
|
64
|
-
const entry = data
|
|
77
|
+
const entry = data
|
|
78
|
+
? `angular-resource:${resourceType},${crypto_1.createHash('md5').update(data).digest('hex')}`
|
|
79
|
+
: filePath;
|
|
65
80
|
if (!entry) {
|
|
66
81
|
throw new Error(`"filePath" or "data" must be specified.`);
|
|
67
82
|
}
|
|
@@ -69,7 +84,8 @@ class WebpackResourceLoader {
|
|
|
69
84
|
if (filePath === null || filePath === void 0 ? void 0 : filePath.match(/\.[jt]s$/)) {
|
|
70
85
|
throw new Error(`Cannot use a JavaScript or TypeScript file (${filePath}) in a component's styleUrls or templateUrl.`);
|
|
71
86
|
}
|
|
72
|
-
const outputFilePath = filePath ||
|
|
87
|
+
const outputFilePath = filePath ||
|
|
88
|
+
`${containingFile}-angular-inline--${this.outputPathCounter++}.${resourceType === 'template' ? 'html' : 'css'}`;
|
|
73
89
|
const outputOptions = {
|
|
74
90
|
filename: outputFilePath,
|
|
75
91
|
library: {
|
|
@@ -133,7 +149,7 @@ class WebpackResourceLoader {
|
|
|
133
149
|
});
|
|
134
150
|
return new Promise((resolve, reject) => {
|
|
135
151
|
childCompiler.runAsChild((error, _, childCompilation) => {
|
|
136
|
-
var _a;
|
|
152
|
+
var _a, _b;
|
|
137
153
|
if (error) {
|
|
138
154
|
reject(error);
|
|
139
155
|
return;
|
|
@@ -148,12 +164,26 @@ class WebpackResourceLoader {
|
|
|
148
164
|
const parent = childCompiler.parentCompilation;
|
|
149
165
|
if (parent) {
|
|
150
166
|
parent.children = parent.children.filter((child) => child !== childCompilation);
|
|
151
|
-
|
|
167
|
+
for (const fileDependency of childCompilation.fileDependencies) {
|
|
168
|
+
if (data && containingFile && fileDependency.endsWith(entry)) {
|
|
169
|
+
// use containing file if the resource was inline
|
|
170
|
+
parent.fileDependencies.add(containingFile);
|
|
171
|
+
}
|
|
172
|
+
else {
|
|
173
|
+
parent.fileDependencies.add(fileDependency);
|
|
174
|
+
}
|
|
175
|
+
}
|
|
152
176
|
parent.contextDependencies.addAll(childCompilation.contextDependencies);
|
|
153
177
|
parent.missingDependencies.addAll(childCompilation.missingDependencies);
|
|
154
178
|
parent.buildDependencies.addAll(childCompilation.buildDependencies);
|
|
155
179
|
parent.warnings.push(...childCompilation.warnings);
|
|
156
180
|
parent.errors.push(...childCompilation.errors);
|
|
181
|
+
for (const { info, name, source } of childCompilation.getAssets()) {
|
|
182
|
+
if (info.sourceFilename === undefined) {
|
|
183
|
+
throw new Error(`'${name}' asset info 'sourceFilename' is 'undefined'.`);
|
|
184
|
+
}
|
|
185
|
+
(_a = this.assetCache) === null || _a === void 0 ? void 0 : _a.set(info.sourceFilename, { info, name, source });
|
|
186
|
+
}
|
|
157
187
|
}
|
|
158
188
|
// Save the dependencies for this resource.
|
|
159
189
|
if (filePath) {
|
|
@@ -177,7 +207,7 @@ class WebpackResourceLoader {
|
|
|
177
207
|
}
|
|
178
208
|
resolve({
|
|
179
209
|
content: finalContent !== null && finalContent !== void 0 ? finalContent : '',
|
|
180
|
-
success: ((
|
|
210
|
+
success: ((_b = childCompilation.errors) === null || _b === void 0 ? void 0 : _b.length) === 0,
|
|
181
211
|
});
|
|
182
212
|
});
|
|
183
213
|
});
|
|
@@ -215,19 +245,11 @@ class WebpackResourceLoader {
|
|
|
215
245
|
}
|
|
216
246
|
return compilationResult.content;
|
|
217
247
|
}
|
|
218
|
-
async process(data, mimeType) {
|
|
219
|
-
var _a;
|
|
248
|
+
async process(data, mimeType, resourceType, containingFile) {
|
|
220
249
|
if (data.trim().length === 0) {
|
|
221
250
|
return '';
|
|
222
251
|
}
|
|
223
|
-
const
|
|
224
|
-
let compilationResult = (_a = this.inlineCache) === null || _a === void 0 ? void 0 : _a.get(cacheKey);
|
|
225
|
-
if (compilationResult === undefined) {
|
|
226
|
-
compilationResult = await this._compile(undefined, data, mimeType);
|
|
227
|
-
if (this.inlineCache && compilationResult.success) {
|
|
228
|
-
this.inlineCache.set(cacheKey, compilationResult);
|
|
229
|
-
}
|
|
230
|
-
}
|
|
252
|
+
const compilationResult = await this._compile(undefined, data, mimeType, resourceType, containingFile);
|
|
231
253
|
return compilationResult.content;
|
|
232
254
|
}
|
|
233
255
|
}
|