@ngtools/webpack 11.2.0-rc.0 → 11.2.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 CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@ngtools/webpack",
3
- "version": "11.2.0-rc.0",
3
+ "version": "11.2.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",
@@ -25,7 +25,7 @@
25
25
  },
26
26
  "homepage": "https://github.com/angular/angular-cli",
27
27
  "dependencies": {
28
- "@angular-devkit/core": "11.2.0-rc.0",
28
+ "@angular-devkit/core": "11.2.2",
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
  }
@@ -27,11 +27,14 @@ export declare class AngularWebpackPlugin {
27
27
  private buildTimestamp;
28
28
  private readonly lazyRouteMap;
29
29
  private readonly requiredFilesToEmit;
30
+ private readonly requiredFilesToEmitCache;
31
+ private readonly fileEmitHistory;
30
32
  constructor(options?: Partial<AngularPluginOptions>);
31
33
  get options(): AngularPluginOptions;
32
34
  apply(compiler: Compiler & {
33
35
  watchMode?: boolean;
34
36
  }): void;
37
+ private rebuildRequiredFiles;
35
38
  private loadConfiguration;
36
39
  private updateAotProgram;
37
40
  private updateJitProgram;
package/src/ivy/plugin.js CHANGED
@@ -10,6 +10,7 @@ exports.AngularWebpackPlugin = void 0;
10
10
  */
11
11
  const compiler_cli_1 = require("@angular/compiler-cli");
12
12
  const program_1 = require("@angular/compiler-cli/src/ngtsc/program");
13
+ const crypto_1 = require("crypto");
13
14
  const path = require("path");
14
15
  const ts = require("typescript");
15
16
  const webpack_1 = require("webpack");
@@ -34,11 +35,16 @@ function initializeNgccProcessor(compiler, tsconfig) {
34
35
  const processor = new ngcc_processor_1.NgccProcessor(mainFields, warnings, errors, compiler.context, tsconfig, inputFileSystem, (_b = webpackOptions.resolve) === null || _b === void 0 ? void 0 : _b.symlinks);
35
36
  return { processor, errors, warnings };
36
37
  }
38
+ function hashContent(content) {
39
+ return crypto_1.createHash('md5').update(content).digest();
40
+ }
37
41
  const PLUGIN_NAME = 'angular-compiler';
38
42
  class AngularWebpackPlugin {
39
43
  constructor(options = {}) {
40
44
  this.lazyRouteMap = {};
41
45
  this.requiredFilesToEmit = new Set();
46
+ this.requiredFilesToEmitCache = new Map();
47
+ this.fileEmitHistory = new Map();
42
48
  this.pluginOptions = {
43
49
  emitClassMetadata: false,
44
50
  emitNgModuleScope: false,
@@ -152,19 +158,7 @@ class AngularWebpackPlugin {
152
158
  }
153
159
  compilation.hooks.finishModules.tapPromise(PLUGIN_NAME, async (modules) => {
154
160
  // Rebuild any remaining AOT required modules
155
- const rebuild = (filename) => new Promise((resolve) => {
156
- const module = modules.find(({ resource }) => resource && paths_1.normalizePath(resource) === filename);
157
- if (!module) {
158
- resolve();
159
- }
160
- else {
161
- compilation.rebuildModule(module, resolve);
162
- }
163
- });
164
- for (const requiredFile of this.requiredFilesToEmit) {
165
- await rebuild(requiredFile);
166
- }
167
- this.requiredFilesToEmit.clear();
161
+ await this.rebuildRequiredFiles(modules, compilation, fileEmitter);
168
162
  // Analyze program for unused files
169
163
  if (compilation.errors.length > 0) {
170
164
  return;
@@ -192,6 +186,41 @@ class AngularWebpackPlugin {
192
186
  compilation[symbol_1.AngularPluginSymbol] = fileEmitter;
193
187
  });
194
188
  }
189
+ async rebuildRequiredFiles(modules, compilation, fileEmitter) {
190
+ if (this.requiredFilesToEmit.size === 0) {
191
+ return;
192
+ }
193
+ const rebuild = (webpackModule) => new Promise((resolve) => compilation.rebuildModule(webpackModule, resolve));
194
+ const filesToRebuild = new Set();
195
+ for (const requiredFile of this.requiredFilesToEmit) {
196
+ const history = this.fileEmitHistory.get(requiredFile);
197
+ if (history) {
198
+ const emitResult = await fileEmitter(requiredFile);
199
+ if ((emitResult === null || emitResult === void 0 ? void 0 : emitResult.content) === undefined ||
200
+ history.length !== emitResult.content.length ||
201
+ emitResult.hash === undefined ||
202
+ Buffer.compare(history.hash, emitResult.hash) !== 0) {
203
+ // New emit result is different so rebuild using new emit result
204
+ this.requiredFilesToEmitCache.set(requiredFile, emitResult);
205
+ filesToRebuild.add(requiredFile);
206
+ }
207
+ }
208
+ else {
209
+ // No emit history so rebuild
210
+ filesToRebuild.add(requiredFile);
211
+ }
212
+ }
213
+ if (filesToRebuild.size > 0) {
214
+ for (const webpackModule of [...modules]) {
215
+ const resource = webpackModule.resource;
216
+ if (resource && filesToRebuild.has(paths_1.normalizePath(resource))) {
217
+ await rebuild(webpackModule);
218
+ }
219
+ }
220
+ }
221
+ this.requiredFilesToEmit.clear();
222
+ this.requiredFilesToEmitCache.clear();
223
+ }
195
224
  loadConfiguration(compilation) {
196
225
  const { options: compilerOptions, rootNames, errors } = compiler_cli_1.readConfiguration(this.pluginOptions.tsconfig, this.pluginOptions.compilerOptions);
197
226
  compilerOptions.enableIvy = true;
@@ -290,7 +319,7 @@ class AngularWebpackPlugin {
290
319
  if (!sourceFile.isDeclarationFile &&
291
320
  !ignoreForEmit.has(sourceFile) &&
292
321
  !angularCompiler.incrementalDriver.safeToSkipEmit(sourceFile)) {
293
- this.requiredFilesToEmit.add(sourceFile.fileName);
322
+ this.requiredFilesToEmit.add(paths_1.normalizePath(sourceFile.fileName));
294
323
  }
295
324
  }
296
325
  // NOTE: This can be removed once support for the deprecated lazy route string format is removed
@@ -299,7 +328,7 @@ class AngularWebpackPlugin {
299
328
  this.lazyRouteMap[routeKey] = lazyRoute.referencedModule.filePath;
300
329
  }
301
330
  return this.createFileEmitter(builder, transformation_1.mergeTransformers(angularCompiler.prepareEmit().transformers, transformers), getDependencies, (sourceFile) => {
302
- this.requiredFilesToEmit.delete(sourceFile.fileName);
331
+ this.requiredFilesToEmit.delete(paths_1.normalizePath(sourceFile.fileName));
303
332
  angularCompiler.incrementalDriver.recordSuccessfulEmit(sourceFile);
304
333
  });
305
334
  });
@@ -355,12 +384,16 @@ class AngularWebpackPlugin {
355
384
  }
356
385
  createFileEmitter(program, transformers = {}, getExtraDependencies, onAfterEmit) {
357
386
  return async (file) => {
358
- const sourceFile = program.getSourceFile(file);
387
+ const filePath = paths_1.normalizePath(file);
388
+ if (this.requiredFilesToEmitCache.has(filePath)) {
389
+ return this.requiredFilesToEmitCache.get(filePath);
390
+ }
391
+ const sourceFile = program.getSourceFile(filePath);
359
392
  if (!sourceFile) {
360
393
  return undefined;
361
394
  }
362
- let content = undefined;
363
- let map = undefined;
395
+ let content;
396
+ let map;
364
397
  program.emit(sourceFile, (filename, data) => {
365
398
  if (filename.endsWith('.map')) {
366
399
  map = data;
@@ -370,11 +403,17 @@ class AngularWebpackPlugin {
370
403
  }
371
404
  }, undefined, undefined, transformers);
372
405
  onAfterEmit === null || onAfterEmit === void 0 ? void 0 : onAfterEmit(sourceFile);
406
+ let hash;
407
+ if (content !== undefined && this.watchMode) {
408
+ // Capture emit history info for Angular rebuild analysis
409
+ hash = hashContent(content);
410
+ this.fileEmitHistory.set(filePath, { length: content.length, hash });
411
+ }
373
412
  const dependencies = [
374
413
  ...program.getAllDependencies(sourceFile),
375
414
  ...getExtraDependencies(sourceFile),
376
415
  ].map(paths_1.externalizePath);
377
- return { content, map, dependencies };
416
+ return { content, map, dependencies, hash };
378
417
  };
379
418
  }
380
419
  }
@@ -10,5 +10,6 @@ export interface EmitFileResult {
10
10
  content?: string;
11
11
  map?: string;
12
12
  dependencies: readonly string[];
13
+ hash?: Uint8Array;
13
14
  }
14
15
  export declare type FileEmitter = (file: string) => Promise<EmitFileResult | undefined>;