@angular-devkit/build-angular 15.0.0-next.6 → 15.0.0-rc.1

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,37 +1,37 @@
1
1
  {
2
2
  "name": "@angular-devkit/build-angular",
3
- "version": "15.0.0-next.6",
3
+ "version": "15.0.0-rc.1",
4
4
  "description": "Angular Webpack Build Facade",
5
5
  "main": "src/index.js",
6
6
  "typings": "src/index.d.ts",
7
7
  "builders": "builders.json",
8
8
  "dependencies": {
9
9
  "@ampproject/remapping": "2.2.0",
10
- "@angular-devkit/architect": "0.1500.0-next.6",
11
- "@angular-devkit/build-webpack": "0.1500.0-next.6",
12
- "@angular-devkit/core": "15.0.0-next.6",
13
- "@babel/core": "7.19.3",
14
- "@babel/generator": "7.19.5",
10
+ "@angular-devkit/architect": "0.1500.0-rc.1",
11
+ "@angular-devkit/build-webpack": "0.1500.0-rc.1",
12
+ "@angular-devkit/core": "15.0.0-rc.1",
13
+ "@babel/core": "7.19.6",
14
+ "@babel/generator": "7.19.6",
15
15
  "@babel/helper-annotate-as-pure": "7.18.6",
16
16
  "@babel/plugin-proposal-async-generator-functions": "7.19.1",
17
17
  "@babel/plugin-transform-async-to-generator": "7.18.6",
18
- "@babel/plugin-transform-runtime": "7.19.1",
18
+ "@babel/plugin-transform-runtime": "7.19.6",
19
19
  "@babel/preset-env": "7.19.4",
20
20
  "@babel/runtime": "7.19.4",
21
21
  "@babel/template": "7.18.10",
22
22
  "@discoveryjs/json-ext": "0.5.7",
23
- "@ngtools/webpack": "15.0.0-next.6",
23
+ "@ngtools/webpack": "15.0.0-rc.1",
24
24
  "ansi-colors": "4.1.3",
25
25
  "autoprefixer": "10.4.12",
26
26
  "babel-loader": "8.2.5",
27
27
  "babel-plugin-istanbul": "6.1.1",
28
28
  "browserslist": "^4.9.1",
29
- "cacache": "17.0.0",
29
+ "cacache": "17.0.1",
30
30
  "chokidar": "3.5.3",
31
31
  "copy-webpack-plugin": "11.0.0",
32
32
  "critters": "0.0.16",
33
33
  "css-loader": "6.7.1",
34
- "esbuild-wasm": "0.15.10",
34
+ "esbuild-wasm": "0.15.12",
35
35
  "glob": "8.0.3",
36
36
  "https-proxy-agent": "5.0.1",
37
37
  "inquirer": "8.2.4",
@@ -68,7 +68,7 @@
68
68
  "webpack-subresource-integrity": "5.1.0"
69
69
  },
70
70
  "optionalDependencies": {
71
- "esbuild": "0.15.10"
71
+ "esbuild": "0.15.12"
72
72
  },
73
73
  "peerDependencies": {
74
74
  "@angular/compiler-cli": "^15.0.0-next",
@@ -11,6 +11,7 @@ import { BundleStylesheetOptions } from './stylesheets';
11
11
  export declare class SourceFileCache extends Map<string, ts.SourceFile> {
12
12
  readonly modifiedFiles: Set<string>;
13
13
  readonly babelFileCache: Map<string, Uint8Array>;
14
+ readonly typeScriptFileCache: Map<string, Uint8Array>;
14
15
  invalidate(files: Iterable<string>): void;
15
16
  }
16
17
  export interface CompilerPluginOptions {
@@ -35,10 +35,11 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
35
35
  Object.defineProperty(exports, "__esModule", { value: true });
36
36
  exports.createCompilerPlugin = exports.SourceFileCache = void 0;
37
37
  const core_1 = require("@babel/core");
38
- const assert = __importStar(require("assert"));
39
- const fs_1 = require("fs");
40
- const os_1 = require("os");
41
- const path = __importStar(require("path"));
38
+ const assert = __importStar(require("node:assert"));
39
+ const fs = __importStar(require("node:fs/promises"));
40
+ const node_os_1 = require("node:os");
41
+ const path = __importStar(require("node:path"));
42
+ const node_url_1 = require("node:url");
42
43
  const typescript_1 = __importDefault(require("typescript"));
43
44
  const application_1 = __importDefault(require("../../babel/presets/application"));
44
45
  const webpack_loader_1 = require("../../babel/webpack-loader");
@@ -108,18 +109,20 @@ function convertTypeScriptDiagnostic(diagnostic, host) {
108
109
  }
109
110
  return message;
110
111
  }
111
- const USING_WINDOWS = (0, os_1.platform)() === 'win32';
112
+ const USING_WINDOWS = (0, node_os_1.platform)() === 'win32';
112
113
  const WINDOWS_SEP_REGEXP = new RegExp(`\\${path.win32.sep}`, 'g');
113
114
  class SourceFileCache extends Map {
114
115
  constructor() {
115
116
  super(...arguments);
116
117
  this.modifiedFiles = new Set();
117
118
  this.babelFileCache = new Map();
119
+ this.typeScriptFileCache = new Map();
118
120
  }
119
121
  invalidate(files) {
120
122
  this.modifiedFiles.clear();
121
123
  for (let file of files) {
122
124
  this.babelFileCache.delete(file);
125
+ this.typeScriptFileCache.delete((0, node_url_1.pathToFileURL)(file).href);
123
126
  // Normalize separators to allow matching TypeScript Host paths
124
127
  if (USING_WINDOWS) {
125
128
  file = file.replace(WINDOWS_SEP_REGEXP, path.posix.sep);
@@ -186,7 +189,7 @@ function createCompilerPlugin(pluginOptions, styleOptions) {
186
189
  notes: [
187
190
  {
188
191
  text: `To control ECMA version and features use the Browerslist configuration. ' +
189
- 'For more information, see https://github.com/browserslist/browserslist#queries'`,
192
+ 'For more information, see https://angular.io/guide/build#configuring-browser-compatibility'`,
190
193
  },
191
194
  ],
192
195
  });
@@ -269,6 +272,12 @@ function createCompilerPlugin(pluginOptions, styleOptions) {
269
272
  const builder = typescript_1.default.createEmitAndSemanticDiagnosticsBuilderProgram(typeScriptProgram, host, previousBuilder, configurationDiagnostics);
270
273
  previousBuilder = builder;
271
274
  await (0, profiling_1.profileAsync)('NG_ANALYZE_PROGRAM', () => angularCompiler.analyzeAsync());
275
+ const affectedFiles = (0, profiling_1.profileSync)('NG_FIND_AFFECTED', () => findAffectedFiles(builder, angularCompiler));
276
+ if (pluginOptions.sourceFileCache) {
277
+ for (const affected of affectedFiles) {
278
+ pluginOptions.sourceFileCache.typeScriptFileCache.delete((0, node_url_1.pathToFileURL)(affected.fileName).href);
279
+ }
280
+ }
272
281
  function* collectDiagnostics() {
273
282
  // Collect program level diagnostics
274
283
  yield* builder.getConfigFileParsingDiagnostics();
@@ -276,7 +285,6 @@ function createCompilerPlugin(pluginOptions, styleOptions) {
276
285
  yield* builder.getOptionsDiagnostics();
277
286
  yield* builder.getGlobalDiagnostics();
278
287
  // Collect source file specific diagnostics
279
- const affectedFiles = findAffectedFiles(builder, angularCompiler);
280
288
  const optimizeFor = affectedFiles.size > 1 ? OptimizeFor.WholeProgram : OptimizeFor.SingleFile;
281
289
  for (const sourceFile of builder.getSourceFiles()) {
282
290
  if (angularCompiler.ignoreForDiagnostics.has(sourceFile)) {
@@ -286,6 +294,10 @@ function createCompilerPlugin(pluginOptions, styleOptions) {
286
294
  // changed or affected for this build when using incremental building.
287
295
  yield* (0, profiling_1.profileSync)('NG_DIAGNOSTICS_SYNTACTIC', () => builder.getSyntacticDiagnostics(sourceFile), true);
288
296
  yield* (0, profiling_1.profileSync)('NG_DIAGNOSTICS_SEMANTIC', () => builder.getSemanticDiagnostics(sourceFile), true);
297
+ // Declaration files cannot have template diagnostics
298
+ if (sourceFile.isDeclarationFile) {
299
+ continue;
300
+ }
289
301
  // Only request Angular template diagnostics for affected files to avoid
290
302
  // overhead of template diagnostics for unchanged files.
291
303
  if (affectedFiles.has(sourceFile)) {
@@ -319,39 +331,47 @@ function createCompilerPlugin(pluginOptions, styleOptions) {
319
331
  return result;
320
332
  });
321
333
  build.onLoad({ filter: compilerOptions.allowJs ? /\.[cm]?[jt]sx?$/ : /\.[cm]?tsx?$/ }, (args) => (0, profiling_1.profileAsync)('NG_EMIT_TS*', async () => {
322
- var _a, _b, _c;
334
+ var _a, _b, _c, _d, _e;
323
335
  assert.ok(fileEmitter, 'Invalid plugin execution order');
324
- const typescriptResult = await fileEmitter((_b = (_a = pluginOptions.fileReplacements) === null || _a === void 0 ? void 0 : _a[args.path]) !== null && _b !== void 0 ? _b : args.path);
325
- if (!typescriptResult) {
326
- // No TS result indicates the file is not part of the TypeScript program.
327
- // If allowJs is enabled and the file is JS then defer to the next load hook.
328
- if (compilerOptions.allowJs && /\.[cm]?js$/.test(args.path)) {
329
- return undefined;
330
- }
331
- // Otherwise return an error
332
- return {
333
- errors: [
334
- {
335
- text: `File '${args.path}' is missing from the TypeScript compilation.`,
336
- notes: [
337
- {
338
- text: `Ensure the file is part of the TypeScript program via the 'files' or 'include' property.`,
339
- },
340
- ],
341
- },
342
- ],
343
- };
344
- }
345
- const data = (_c = typescriptResult.content) !== null && _c !== void 0 ? _c : '';
346
- // The pre-transformed data is used as a cache key. Since the cache is memory only,
336
+ // The filename is currently used as a cache key. Since the cache is memory only,
347
337
  // the options cannot change and do not need to be represented in the key. If the
348
338
  // cache is later stored to disk, then the options that affect transform output
349
- // would need to be added to the key as well.
350
- let contents = babelDataCache.get(data);
339
+ // would need to be added to the key as well as a check for any change of content.
340
+ let contents = (_a = pluginOptions.sourceFileCache) === null || _a === void 0 ? void 0 : _a.typeScriptFileCache.get((0, node_url_1.pathToFileURL)(args.path).href);
351
341
  if (contents === undefined) {
352
- const transformedData = await transformWithBabel(args.path, data, pluginOptions);
353
- contents = Buffer.from(transformedData, 'utf-8');
354
- babelDataCache.set(data, contents);
342
+ const typescriptResult = await fileEmitter((_c = (_b = pluginOptions.fileReplacements) === null || _b === void 0 ? void 0 : _b[args.path]) !== null && _c !== void 0 ? _c : args.path);
343
+ if (!typescriptResult) {
344
+ // No TS result indicates the file is not part of the TypeScript program.
345
+ // If allowJs is enabled and the file is JS then defer to the next load hook.
346
+ if (compilerOptions.allowJs && /\.[cm]?js$/.test(args.path)) {
347
+ return undefined;
348
+ }
349
+ // Otherwise return an error
350
+ return {
351
+ errors: [
352
+ {
353
+ text: `File '${args.path}' is missing from the TypeScript compilation.`,
354
+ notes: [
355
+ {
356
+ text: `Ensure the file is part of the TypeScript program via the 'files' or 'include' property.`,
357
+ },
358
+ ],
359
+ },
360
+ ],
361
+ };
362
+ }
363
+ const data = (_d = typescriptResult.content) !== null && _d !== void 0 ? _d : '';
364
+ // The pre-transformed data is used as a cache key. Since the cache is memory only,
365
+ // the options cannot change and do not need to be represented in the key. If the
366
+ // cache is later stored to disk, then the options that affect transform output
367
+ // would need to be added to the key as well.
368
+ contents = babelDataCache.get(data);
369
+ if (contents === undefined) {
370
+ const transformedData = await transformWithBabel(args.path, data, pluginOptions);
371
+ contents = Buffer.from(transformedData, 'utf-8');
372
+ babelDataCache.set(data, contents);
373
+ }
374
+ (_e = pluginOptions.sourceFileCache) === null || _e === void 0 ? void 0 : _e.typeScriptFileCache.set((0, node_url_1.pathToFileURL)(args.path).href, contents);
355
375
  }
356
376
  return {
357
377
  contents,
@@ -366,7 +386,7 @@ function createCompilerPlugin(pluginOptions, styleOptions) {
366
386
  // would need to be added to the key as well as a check for any change of content.
367
387
  let contents = (_a = pluginOptions.sourceFileCache) === null || _a === void 0 ? void 0 : _a.babelFileCache.get(args.path);
368
388
  if (contents === undefined) {
369
- const data = await fs_1.promises.readFile(args.path, 'utf-8');
389
+ const data = await fs.readFile(args.path, 'utf-8');
370
390
  const transformedData = await transformWithBabel(args.path, data, pluginOptions);
371
391
  contents = Buffer.from(transformedData, 'utf-8');
372
392
  (_b = pluginOptions.sourceFileCache) === null || _b === void 0 ? void 0 : _b.babelFileCache.set(args.path, contents);
@@ -352,8 +352,8 @@ async function* buildEsbuildBrowser(initialOptions, context) {
352
352
  const watcher = (0, watcher_1.createWatcher)({
353
353
  polling: typeof initialOptions.poll === 'number',
354
354
  interval: initialOptions.poll,
355
- // Ignore the output path to avoid infinite rebuild cycles
356
- ignored: [normalizedOptions.outputPath],
355
+ // Ignore the output and cache paths to avoid infinite rebuild cycles
356
+ ignored: [normalizedOptions.outputPath, normalizedOptions.cacheOptions.basePath],
357
357
  });
358
358
  // Temporarily watch the entire project
359
359
  watcher.add(normalizedOptions.projectRoot);
@@ -21,6 +21,7 @@ export declare type NormalizedBrowserOptions = Awaited<ReturnType<typeof normali
21
21
  export declare function normalizeOptions(context: BuilderContext, projectName: string, options: BrowserBuilderOptions): Promise<{
22
22
  advancedOptimizations: boolean | undefined;
23
23
  baseHref: string | undefined;
24
+ cacheOptions: import("../../utils/normalize-cache").NormalizedCachedOptions;
24
25
  crossOrigin: import("./schema").CrossOrigin | undefined;
25
26
  externalDependencies: string[] | undefined;
26
27
  poll: number | undefined;
@@ -33,6 +33,7 @@ Object.defineProperty(exports, "__esModule", { value: true });
33
33
  exports.normalizeOptions = void 0;
34
34
  const path = __importStar(require("path"));
35
35
  const utils_1 = require("../../utils");
36
+ const normalize_cache_1 = require("../../utils/normalize-cache");
36
37
  const normalize_polyfills_1 = require("../../utils/normalize-polyfills");
37
38
  const package_chunk_sort_1 = require("../../utils/package-chunk-sort");
38
39
  const webpack_browser_config_1 = require("../../utils/webpack-browser-config");
@@ -54,7 +55,7 @@ async function normalizeOptions(context, projectName, options) {
54
55
  const projectMetadata = await context.getProjectMetadata(projectName);
55
56
  const projectRoot = path.join(workspaceRoot, (_a = projectMetadata.root) !== null && _a !== void 0 ? _a : '');
56
57
  const projectSourceRoot = path.join(workspaceRoot, (_b = projectMetadata.sourceRoot) !== null && _b !== void 0 ? _b : 'src');
57
- // Normalize options
58
+ const cacheOptions = (0, normalize_cache_1.normalizeCacheOptions)(projectMetadata, workspaceRoot);
58
59
  const mainEntryPoint = path.join(workspaceRoot, options.main);
59
60
  // Currently esbuild do not support multiple files per entry-point
60
61
  const [polyfillsEntryPoint, ...remainingPolyfills] = (0, normalize_polyfills_1.normalizePolyfills)(options.polyfills, workspaceRoot);
@@ -126,6 +127,7 @@ async function normalizeOptions(context, projectName, options) {
126
127
  return {
127
128
  advancedOptimizations: buildOptimizer,
128
129
  baseHref,
130
+ cacheOptions,
129
131
  crossOrigin,
130
132
  externalDependencies,
131
133
  poll,
@@ -18,9 +18,22 @@ function logCumulativeDurations() {
18
18
  if (!environment_options_1.debugPerformance || !cumulativeDurations) {
19
19
  return;
20
20
  }
21
- for (const [name, duration] of cumulativeDurations) {
21
+ for (const [name, durations] of cumulativeDurations) {
22
+ let total = 0;
23
+ let min;
24
+ let max;
25
+ for (const duration of durations) {
26
+ total += duration;
27
+ if (min === undefined || duration < min) {
28
+ min = duration;
29
+ }
30
+ if (max === undefined || duration > max) {
31
+ max = duration;
32
+ }
33
+ }
34
+ const average = total / durations.length;
22
35
  // eslint-disable-next-line no-console
23
- console.log(`DURATION[${name}]: ${duration.toFixed(9)} seconds`);
36
+ console.log(`DURATION[${name}]: ${total.toFixed(9)}s [count: ${durations.length}; avg: ${average.toFixed(9)}s; min: ${min === null || min === void 0 ? void 0 : min.toFixed(9)}s; max: ${max === null || max === void 0 ? void 0 : max.toFixed(9)}s]`);
24
37
  }
25
38
  }
26
39
  exports.logCumulativeDurations = logCumulativeDurations;
@@ -29,11 +42,13 @@ function recordDuration(name, startTime, cumulative) {
29
42
  const duration = Number(process.hrtime.bigint() - startTime) / 10 ** 9;
30
43
  if (cumulative) {
31
44
  cumulativeDurations !== null && cumulativeDurations !== void 0 ? cumulativeDurations : (cumulativeDurations = new Map());
32
- cumulativeDurations.set(name, ((_a = cumulativeDurations.get(name)) !== null && _a !== void 0 ? _a : 0) + duration);
45
+ const durations = (_a = cumulativeDurations.get(name)) !== null && _a !== void 0 ? _a : [];
46
+ durations.push(duration);
47
+ cumulativeDurations.set(name, durations);
33
48
  }
34
49
  else {
35
50
  // eslint-disable-next-line no-console
36
- console.log(`DURATION[${name}]: ${duration.toFixed(9)} seconds`);
51
+ console.log(`DURATION[${name}]: ${duration.toFixed(9)}s`);
37
52
  }
38
53
  }
39
54
  async function profileAsync(name, action, cumulative) {
@@ -114,6 +114,12 @@ function serveWebpackBrowser(options, context, transforms = {}) {
114
114
  const metadata = await context.getProjectMetadata(projectName);
115
115
  const cacheOptions = (0, normalize_cache_1.normalizeCacheOptions)(metadata, context.workspaceRoot);
116
116
  const browserName = await context.getBuilderNameForTarget(browserTarget);
117
+ // Issue a warning that the dev-server does not currently support the experimental esbuild-
118
+ // based builder and will use Webpack.
119
+ if (browserName === '@angular-devkit/build-angular:browser-esbuild') {
120
+ logger.warn('WARNING: The experimental esbuild-based builder is not currently supported ' +
121
+ 'by the dev-server. The stable Webpack-based builder will be used instead.');
122
+ }
117
123
  const browserOptions = (await context.validateOptions({
118
124
  ...rawBrowserOptions,
119
125
  watch: options.watch,
@@ -28,7 +28,7 @@ function createIvyPlugin(wco, aot, tsconfig) {
28
28
  (_a = (_c = tsConfig.options).useDefineForClassFields) !== null && _a !== void 0 ? _a : (_c.useDefineForClassFields = false);
29
29
  wco.logger.warn('TypeScript compiler options "target" and "useDefineForClassFields" are set to "ES2022" and ' +
30
30
  '"false" respectively by the Angular CLI. To control ECMA version and features use the Browerslist configuration. ' +
31
- 'For more information, see https://github.com/browserslist/browserslist');
31
+ 'For more information, see https://angular.io/guide/build#configuring-browser-compatibility');
32
32
  }
33
33
  if (buildOptions.preserveSymlinks !== undefined) {
34
34
  compilerOptions.preserveSymlinks = buildOptions.preserveSymlinks;