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