@angular-devkit/build-angular 17.2.3 → 17.3.0-rc.0

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.
Files changed (37) hide show
  1. package/package.json +31 -31
  2. package/src/builders/app-shell/index.js +1 -0
  3. package/src/builders/app-shell/render-worker.js +1 -1
  4. package/src/builders/application/options.d.ts +2 -6
  5. package/src/builders/application/options.js +44 -24
  6. package/src/builders/application/schema.d.ts +6 -0
  7. package/src/builders/application/schema.json +4 -0
  8. package/src/builders/browser/index.js +1 -1
  9. package/src/builders/browser/schema.d.ts +3 -3
  10. package/src/builders/browser/schema.json +1 -2
  11. package/src/builders/browser-esbuild/schema.d.ts +3 -3
  12. package/src/builders/browser-esbuild/schema.json +1 -2
  13. package/src/builders/dev-server/vite-server.js +7 -3
  14. package/src/builders/prerender/index.js +2 -0
  15. package/src/builders/server/schema.d.ts +3 -4
  16. package/src/builders/server/schema.json +1 -2
  17. package/src/builders/web-test-runner/index.js +1 -1
  18. package/src/tools/esbuild/angular/compilation/parallel-compilation.js +1 -0
  19. package/src/tools/esbuild/application-code-bundle.js +0 -1
  20. package/src/tools/esbuild/global-styles.js +1 -2
  21. package/src/tools/esbuild/i18n-inliner.js +1 -0
  22. package/src/tools/esbuild/javascript-transformer.js +1 -0
  23. package/src/tools/sass/sass-service.d.ts +3 -3
  24. package/src/tools/sass/sass-service.js +3 -3
  25. package/src/tools/webpack/plugins/javascript-optimizer-plugin.js +1 -0
  26. package/src/tools/webpack/plugins/javascript-optimizer-worker.d.ts +1 -1
  27. package/src/tools/webpack/utils/stats.js +3 -2
  28. package/src/utils/action-executor.js +1 -0
  29. package/src/utils/color.d.ts +0 -1
  30. package/src/utils/color.js +4 -10
  31. package/src/utils/index-file/html-rewriting-stream.js +9 -26
  32. package/src/utils/index-file/index-html-generator.js +4 -5
  33. package/src/utils/purge-cache.js +17 -12
  34. package/src/utils/server-rendering/prerender.js +2 -0
  35. package/src/utils/version.js +15 -21
  36. package/src/utils/strip-bom.d.ts +0 -8
  37. package/src/utils/strip-bom.js +0 -17
package/package.json CHANGED
@@ -1,92 +1,92 @@
1
1
  {
2
2
  "name": "@angular-devkit/build-angular",
3
- "version": "17.2.3",
3
+ "version": "17.3.0-rc.0",
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
- "@ampproject/remapping": "2.2.1",
10
- "@angular-devkit/architect": "0.1702.3",
11
- "@angular-devkit/build-webpack": "0.1702.3",
12
- "@angular-devkit/core": "17.2.3",
13
- "@babel/core": "7.23.9",
9
+ "@ampproject/remapping": "2.3.0",
10
+ "@angular-devkit/architect": "0.1703.0-rc.0",
11
+ "@angular-devkit/build-webpack": "0.1703.0-rc.0",
12
+ "@angular-devkit/core": "17.3.0-rc.0",
13
+ "@babel/core": "7.24.0",
14
14
  "@babel/generator": "7.23.6",
15
15
  "@babel/helper-annotate-as-pure": "7.22.5",
16
16
  "@babel/helper-split-export-declaration": "7.22.6",
17
17
  "@babel/plugin-transform-async-generator-functions": "7.23.9",
18
18
  "@babel/plugin-transform-async-to-generator": "7.23.3",
19
- "@babel/plugin-transform-runtime": "7.23.9",
20
- "@babel/preset-env": "7.23.9",
21
- "@babel/runtime": "7.23.9",
19
+ "@babel/plugin-transform-runtime": "7.24.0",
20
+ "@babel/preset-env": "7.24.0",
21
+ "@babel/runtime": "7.24.0",
22
22
  "@discoveryjs/json-ext": "0.5.7",
23
- "@ngtools/webpack": "17.2.3",
23
+ "@ngtools/webpack": "17.3.0-rc.0",
24
24
  "@vitejs/plugin-basic-ssl": "1.1.0",
25
25
  "ansi-colors": "4.1.3",
26
- "autoprefixer": "10.4.17",
26
+ "autoprefixer": "10.4.18",
27
27
  "babel-loader": "9.1.3",
28
28
  "babel-plugin-istanbul": "6.1.1",
29
29
  "browserslist": "^4.21.5",
30
30
  "copy-webpack-plugin": "11.0.0",
31
31
  "critters": "0.0.20",
32
32
  "css-loader": "6.10.0",
33
- "esbuild-wasm": "0.20.0",
33
+ "esbuild-wasm": "0.20.1",
34
34
  "fast-glob": "3.3.2",
35
- "https-proxy-agent": "7.0.2",
35
+ "https-proxy-agent": "7.0.4",
36
36
  "http-proxy-middleware": "2.0.6",
37
- "inquirer": "9.2.14",
37
+ "inquirer": "9.2.15",
38
38
  "jsonc-parser": "3.2.1",
39
39
  "karma-source-map-support": "1.4.0",
40
40
  "less": "4.2.0",
41
41
  "less-loader": "11.1.0",
42
42
  "license-webpack-plugin": "4.0.2",
43
43
  "loader-utils": "3.2.1",
44
- "magic-string": "0.30.7",
45
- "mini-css-extract-plugin": "2.8.0",
44
+ "magic-string": "0.30.8",
45
+ "mini-css-extract-plugin": "2.8.1",
46
46
  "mrmime": "2.0.0",
47
47
  "open": "8.4.2",
48
48
  "ora": "5.4.1",
49
49
  "parse5-html-rewriting-stream": "7.0.0",
50
50
  "picomatch": "4.0.1",
51
- "piscina": "4.3.1",
51
+ "piscina": "4.4.0",
52
52
  "postcss": "8.4.35",
53
- "postcss-loader": "8.1.0",
53
+ "postcss-loader": "8.1.1",
54
54
  "resolve-url-loader": "5.0.0",
55
55
  "rxjs": "7.8.1",
56
- "sass": "1.70.0",
57
- "sass-loader": "14.1.0",
56
+ "sass": "1.71.1",
57
+ "sass-loader": "14.1.1",
58
58
  "semver": "7.6.0",
59
59
  "source-map-loader": "5.0.0",
60
60
  "source-map-support": "0.5.21",
61
- "terser": "5.27.0",
61
+ "terser": "5.28.1",
62
62
  "tree-kill": "1.2.2",
63
63
  "tslib": "2.6.2",
64
- "undici": "6.6.2",
65
- "vite": "5.0.12",
64
+ "undici": "6.7.0",
65
+ "vite": "5.1.5",
66
66
  "watchpack": "2.4.0",
67
- "webpack": "5.90.1",
67
+ "webpack": "5.90.3",
68
68
  "webpack-dev-middleware": "6.1.1",
69
69
  "webpack-dev-server": "4.15.1",
70
70
  "webpack-merge": "5.10.0",
71
71
  "webpack-subresource-integrity": "5.1.0"
72
72
  },
73
73
  "optionalDependencies": {
74
- "esbuild": "0.20.0"
74
+ "esbuild": "0.20.1"
75
75
  },
76
76
  "peerDependencies": {
77
- "@angular/compiler-cli": "^17.0.0",
78
- "@angular/localize": "^17.0.0",
79
- "@angular/platform-server": "^17.0.0",
80
- "@angular/service-worker": "^17.0.0",
77
+ "@angular/compiler-cli": "^17.0.0 || ^17.3.0-next.0",
78
+ "@angular/localize": "^17.0.0 || ^17.3.0-next.0",
79
+ "@angular/platform-server": "^17.0.0 || ^17.3.0-next.0",
80
+ "@angular/service-worker": "^17.0.0 || ^17.3.0-next.0",
81
81
  "@web/test-runner": "^0.18.0",
82
82
  "browser-sync": "^3.0.2",
83
83
  "jest": "^29.5.0",
84
84
  "jest-environment-jsdom": "^29.5.0",
85
85
  "karma": "^6.3.0",
86
- "ng-packagr": "^17.0.0",
86
+ "ng-packagr": "^17.0.0 || ^17.3.0-next.0",
87
87
  "protractor": "^7.0.0",
88
88
  "tailwindcss": "^2.0.0 || ^3.0.0",
89
- "typescript": ">=5.2 <5.4"
89
+ "typescript": ">=5.2 <5.5"
90
90
  },
91
91
  "peerDependenciesMeta": {
92
92
  "@angular/localize": {
@@ -69,6 +69,7 @@ async function _renderUniversal(options, context, browserResult, serverResult, s
69
69
  filename: require.resolve('./render-worker'),
70
70
  maxThreads: 1,
71
71
  workerData: { zonePackage },
72
+ recordTiming: false,
72
73
  });
73
74
  try {
74
75
  for (const { path: outputPath, baseHref } of browserResult.outputs) {
@@ -76,7 +76,7 @@ async function render({ serverBundlePath, document, url }) {
76
76
  }
77
77
  // The below should really handled by the framework!!!.
78
78
  let timer;
79
- const renderingTimeout = new Promise((_, reject) => (timer = setTimeout(() => reject(new Error(`Page ${new URL(url, 'resolve://').pathname} did not render in 30 seconds.`)), 30000)));
79
+ const renderingTimeout = new Promise((_, reject) => (timer = setTimeout(() => reject(new Error(`Page ${new URL(url, 'resolve://').pathname} did not render in 30 seconds.`)), 30_000)));
80
80
  return Promise.race([renderAppPromise, renderingTimeout]).finally(() => clearTimeout(timer));
81
81
  }
82
82
  function isBootstrapFn(value) {
@@ -5,7 +5,7 @@
5
5
  * Use of this source code is governed by an MIT-style license that can be
6
6
  * found in the LICENSE file at https://angular.io/license
7
7
  */
8
- import { BuilderContext } from '@angular-devkit/architect';
8
+ import type { BuilderContext } from '@angular-devkit/architect';
9
9
  import type { Plugin } from 'esbuild';
10
10
  import { I18nOptions } from '../../utils/i18n-options';
11
11
  import { IndexHtmlTransform } from '../../utils/index-file/index-html-generator';
@@ -39,10 +39,6 @@ interface InternalOptions {
39
39
  * This is only used by the development server which currently only supports a single locale per build.
40
40
  */
41
41
  forceI18nFlatOutput?: boolean;
42
- /**
43
- * Allows for usage of the deprecated `deployUrl` option with the compatibility builder `browser-esbuild`.
44
- */
45
- deployUrl?: string;
46
42
  }
47
43
  /** Full set of options for `application` builder. */
48
44
  export type ApplicationBuilderInternalOptions = Omit<ApplicationBuilderOptions & InternalOptions, 'browser'> & {
@@ -123,7 +119,7 @@ export declare function normalizeOptions(context: BuilderContext, projectName: s
123
119
  indexHtmlOptions: {
124
120
  input: string;
125
121
  output: string;
126
- insertionOrder: import("../../utils/package-chunk-sort").EntryPointsType[];
122
+ insertionOrder: [string, boolean][];
127
123
  transformer: IndexHtmlTransform | undefined;
128
124
  preloadInitial: boolean;
129
125
  } | undefined;
@@ -15,16 +15,13 @@ const node_fs_1 = require("node:fs");
15
15
  const promises_1 = require("node:fs/promises");
16
16
  const node_module_1 = require("node:module");
17
17
  const node_path_1 = __importDefault(require("node:path"));
18
- const helpers_1 = require("../../tools/webpack/utils/helpers");
19
18
  const utils_1 = require("../../utils");
20
19
  const color_1 = require("../../utils/color");
21
20
  const environment_options_1 = require("../../utils/environment-options");
22
21
  const i18n_options_1 = require("../../utils/i18n-options");
23
22
  const normalize_cache_1 = require("../../utils/normalize-cache");
24
- const package_chunk_sort_1 = require("../../utils/package-chunk-sort");
25
23
  const postcss_configuration_1 = require("../../utils/postcss-configuration");
26
24
  const tailwind_1 = require("../../utils/tailwind");
27
- const webpack_browser_config_1 = require("../../utils/webpack-browser-config");
28
25
  const schema_1 = require("./schema");
29
26
  /**
30
27
  * Normalize the user provided options by creating full paths for all path based options
@@ -116,31 +113,24 @@ async function normalizeOptions(context, projectName, options, extensions) {
116
113
  const tailwindConfiguration = postcssConfiguration
117
114
  ? undefined
118
115
  : await getTailwindConfig(workspaceRoot, projectRoot, context);
119
- const globalStyles = [];
120
- if (options.styles?.length) {
121
- const { entryPoints: stylesheetEntrypoints, noInjectNames } = (0, helpers_1.normalizeGlobalStyles)(options.styles || []);
122
- for (const [name, files] of Object.entries(stylesheetEntrypoints)) {
123
- globalStyles.push({ name, files, initial: !noInjectNames.includes(name) });
124
- }
125
- }
126
- const globalScripts = [];
127
- if (options.scripts?.length) {
128
- for (const { bundleName, paths, inject } of (0, helpers_1.globalScriptsByBundleName)(options.scripts)) {
129
- globalScripts.push({ name: bundleName, files: paths, initial: inject });
130
- }
131
- }
116
+ const globalStyles = normalizeGlobalEntries(options.styles, 'styles');
117
+ const globalScripts = normalizeGlobalEntries(options.scripts, 'scripts');
132
118
  let indexHtmlOptions;
133
119
  // index can never have a value of `true` but in the schema it's of type `boolean`.
134
120
  if (typeof options.index !== 'boolean') {
135
121
  indexHtmlOptions = {
136
- input: node_path_1.default.join(workspaceRoot, (0, webpack_browser_config_1.getIndexInputFile)(options.index)),
122
+ input: node_path_1.default.join(workspaceRoot, typeof options.index === 'string' ? options.index : options.index.input),
137
123
  // The output file will be created within the configured output path
138
- output: (0, webpack_browser_config_1.getIndexOutputFile)(options.index),
139
- // TODO: Use existing information from above to create the insertion order
140
- insertionOrder: (0, package_chunk_sort_1.generateEntryPoints)({
141
- scripts: options.scripts ?? [],
142
- styles: options.styles ?? [],
143
- }),
124
+ output: typeof options.index === 'string'
125
+ ? node_path_1.default.basename(options.index)
126
+ : options.index.output || 'index.html',
127
+ insertionOrder: [
128
+ ['polyfills', true],
129
+ ...globalStyles.filter((s) => s.initial).map((s) => [s.name, false]),
130
+ ...globalScripts.filter((s) => s.initial).map((s) => [s.name, false]),
131
+ ['main', true],
132
+ // [name, esm]
133
+ ],
144
134
  transformer: extensions?.indexHtmlTransformer,
145
135
  // Preload initial defaults to true
146
136
  preloadInitial: typeof options.index !== 'object' || (options.index.preloadInitial ?? true),
@@ -225,7 +215,7 @@ async function normalizeOptions(context, projectName, options, extensions) {
225
215
  i18nOptions,
226
216
  namedChunks,
227
217
  budgets: budgets?.length ? budgets : undefined,
228
- publicPath: deployUrl ? deployUrl : undefined,
218
+ publicPath: deployUrl,
229
219
  plugins: extensions?.codePlugins?.length ? extensions?.codePlugins : undefined,
230
220
  loaderExtensions,
231
221
  jsonLogs: environment_options_1.useJSONBuildLogs,
@@ -324,3 +314,33 @@ function normalizeDirectoryPath(path) {
324
314
  }
325
315
  return path;
326
316
  }
317
+ function normalizeGlobalEntries(rawEntries, defaultName) {
318
+ if (!rawEntries?.length) {
319
+ return [];
320
+ }
321
+ const bundles = new Map();
322
+ for (const rawEntry of rawEntries) {
323
+ let entry;
324
+ if (typeof rawEntry === 'string') {
325
+ // string entries use default bundle name and inject values
326
+ entry = { input: rawEntry };
327
+ }
328
+ else {
329
+ entry = rawEntry;
330
+ }
331
+ const { bundleName, input, inject = true } = entry;
332
+ // Non-injected entries default to the file name
333
+ const name = bundleName || (inject ? defaultName : node_path_1.default.basename(input, node_path_1.default.extname(input)));
334
+ const existing = bundles.get(name);
335
+ if (!existing) {
336
+ bundles.set(name, { name, files: [input], initial: inject });
337
+ continue;
338
+ }
339
+ if (existing.initial !== inject) {
340
+ throw new Error(`The "${name}" bundle is mixing injected and non-injected entries. ` +
341
+ 'Verify that the project options are correct.');
342
+ }
343
+ existing.files.push(input);
344
+ }
345
+ return [...bundles.values()];
346
+ }
@@ -54,6 +54,12 @@ export interface Schema {
54
54
  * Delete the output path before building.
55
55
  */
56
56
  deleteOutputPath?: boolean;
57
+ /**
58
+ * Customize the base path for the URLs of resources in 'index.html' and component
59
+ * stylesheets. This option is only necessary for specific deployment scenarios, such as
60
+ * with Angular Elements or when utilizing different CDN locations.
61
+ */
62
+ deployUrl?: string;
57
63
  /**
58
64
  * Exclude the listed external dependencies from being bundled into the bundle. Instead, the
59
65
  * created bundle relies on these dependencies to be available during runtime.
@@ -33,6 +33,10 @@
33
33
  "type": "string",
34
34
  "description": "The full path for the TypeScript configuration file, relative to the current workspace."
35
35
  },
36
+ "deployUrl": {
37
+ "type": "string",
38
+ "description": "Customize the base path for the URLs of resources in 'index.html' and component stylesheets. This option is only necessary for specific deployment scenarios, such as with Angular Elements or when utilizing different CDN locations."
39
+ },
36
40
  "scripts": {
37
41
  "description": "Global scripts to be included in the build.",
38
42
  "type": "array",
@@ -60,7 +60,7 @@ const webpack_browser_config_1 = require("../../utils/webpack-browser-config");
60
60
  * Maximum time in milliseconds for single build/rebuild
61
61
  * This accounts for CI variability.
62
62
  */
63
- exports.BUILD_TIMEOUT = 30000;
63
+ exports.BUILD_TIMEOUT = 30_000;
64
64
  async function initialize(options, context, webpackConfigurationTransform) {
65
65
  const originalOutputPath = options.outputPath;
66
66
  // Assets are processed directly by the builder except when watching
@@ -41,9 +41,9 @@ export interface Schema {
41
41
  */
42
42
  deleteOutputPath?: boolean;
43
43
  /**
44
- * URL where files will be deployed.
45
- * @deprecated Use "baseHref" option, "APP_BASE_HREF" DI token or a combination of both
46
- * instead. For more information, see https://angular.io/guide/deployment#the-deploy-url.
44
+ * Customize the base path for the URLs of resources in 'index.html' and component
45
+ * stylesheets. This option is only necessary for specific deployment scenarios, such as
46
+ * with Angular Elements or when utilizing different CDN locations.
47
47
  */
48
48
  deployUrl?: string;
49
49
  /**
@@ -270,8 +270,7 @@
270
270
  },
271
271
  "deployUrl": {
272
272
  "type": "string",
273
- "description": "URL where files will be deployed.",
274
- "x-deprecated": "Use \"baseHref\" option, \"APP_BASE_HREF\" DI token or a combination of both instead. For more information, see https://angular.io/guide/deployment#the-deploy-url."
273
+ "description": "Customize the base path for the URLs of resources in 'index.html' and component stylesheets. This option is only necessary for specific deployment scenarios, such as with Angular Elements or when utilizing different CDN locations."
275
274
  },
276
275
  "verbose": {
277
276
  "type": "boolean",
@@ -41,9 +41,9 @@ export interface Schema {
41
41
  */
42
42
  deleteOutputPath?: boolean;
43
43
  /**
44
- * URL where files will be deployed.
45
- * @deprecated Use "baseHref" option, "APP_BASE_HREF" DI token or a combination of both
46
- * instead. For more information, see https://angular.io/guide/deployment#the-deploy-url.
44
+ * Customize the base path for the URLs of resources in 'index.html' and component
45
+ * stylesheets. This option is only necessary for specific deployment scenarios, such as
46
+ * with Angular Elements or when utilizing different CDN locations.
47
47
  */
48
48
  deployUrl?: string;
49
49
  /**
@@ -277,8 +277,7 @@
277
277
  },
278
278
  "deployUrl": {
279
279
  "type": "string",
280
- "description": "URL where files will be deployed.",
281
- "x-deprecated": "Use \"baseHref\" option, \"APP_BASE_HREF\" DI token or a combination of both instead. For more information, see https://angular.io/guide/deployment#the-deploy-url."
280
+ "description": "Customize the base path for the URLs of resources in 'index.html' and component stylesheets. This option is only necessary for specific deployment scenarios, such as with Angular Elements or when utilizing different CDN locations."
282
281
  },
283
282
  "verbose": {
284
283
  "type": "boolean",
@@ -373,6 +373,10 @@ async function setupServer(serverOptions, outputFiles, assets, preserveSymlinks,
373
373
  // the Vite client-side code for browser reloading. These would be available by default but when
374
374
  // the `allow` option is explicitly configured, they must be included manually.
375
375
  allow: [cacheDir, (0, node_path_1.join)(serverOptions.workspaceRoot, 'node_modules'), ...assets.values()],
376
+ // Temporary disable cached FS checks.
377
+ // This is because we configure `config.base` to a virtual directory which causes `getRealPath` to fail.
378
+ // See: https://github.com/vitejs/vite/blob/b2873ac3936de25ca8784327cb9ef16bd4881805/packages/vite/src/node/fsUtils.ts#L45-L67
379
+ cachedChecks: false,
376
380
  },
377
381
  // This is needed when `externalDependencies` is used to prevent Vite load errors.
378
382
  // NOTE: If Vite adds direct support for externals, this can be removed.
@@ -474,12 +478,12 @@ function getDepOptimizationConfig({ disabled, exclude, include, target, prebundl
474
478
  plugins.unshift((0, rxjs_esm_resolution_plugin_1.createRxjsEsmResolutionPlugin)());
475
479
  }
476
480
  return {
477
- // Only enable with caching since it causes prebundle dependencies to be cached
478
- disabled,
479
481
  // Exclude any explicitly defined dependencies (currently build defined externals)
480
482
  exclude,
483
+ // NB: to disable the deps optimizer, set optimizeDeps.noDiscovery to true and optimizeDeps.include as undefined.
481
484
  // Include all implict dependencies from the external packages internal option
482
- include,
485
+ include: disabled ? undefined : include,
486
+ noDiscovery: disabled,
483
487
  // Add an esbuild plugin to run the Angular linker on dependencies
484
488
  esbuildOptions: {
485
489
  // Set esbuild supported targets.
@@ -69,6 +69,7 @@ async function getRoutes(indexFile, outputPath, serverBundlePath, options, works
69
69
  serverBundlePath,
70
70
  zonePackage: require.resolve('zone.js', { paths: [workspaceRoot] }),
71
71
  },
72
+ recordTiming: false,
72
73
  });
73
74
  const extractedRoutes = await renderWorker
74
75
  .run({})
@@ -140,6 +141,7 @@ async function _renderUniversal(options, context, browserResult, serverResult, b
140
141
  filename: path.join(__dirname, 'render-worker.js'),
141
142
  maxThreads: environment_options_1.maxWorkers,
142
143
  workerData: { zonePackage },
144
+ recordTiming: false,
143
145
  });
144
146
  let routes;
145
147
  try {
@@ -12,10 +12,9 @@ export interface Schema {
12
12
  */
13
13
  deleteOutputPath?: boolean;
14
14
  /**
15
- * URL where files will be deployed.
16
- * @deprecated Use "baseHref" browser builder option, "APP_BASE_HREF" DI token or a
17
- * combination of both instead. For more information, see
18
- * https://angular.io/guide/deployment#the-deploy-url.
15
+ * Customize the base path for the URLs of resources in 'index.html' and component
16
+ * stylesheets. This option is only necessary for specific deployment scenarios, such as
17
+ * with Angular Elements or when utilizing different CDN locations.
19
18
  */
20
19
  deployUrl?: string;
21
20
  /**
@@ -121,8 +121,7 @@
121
121
  },
122
122
  "deployUrl": {
123
123
  "type": "string",
124
- "description": "URL where files will be deployed.",
125
- "x-deprecated": "Use \"baseHref\" browser builder option, \"APP_BASE_HREF\" DI token or a combination of both instead. For more information, see https://angular.io/guide/deployment#the-deploy-url."
124
+ "description": "Customize the base path for the URLs of resources in 'index.html' and component stylesheets. This option is only necessary for specific deployment scenarios, such as with Angular Elements or when utilizing different CDN locations."
126
125
  },
127
126
  "vendorChunk": {
128
127
  "type": "boolean",
@@ -110,7 +110,7 @@ async function runTests(wtr, testDir, options) {
110
110
  ],
111
111
  testFramework: {
112
112
  config: {
113
- defaultTimeoutInterval: 5000,
113
+ defaultTimeoutInterval: 5_000,
114
114
  },
115
115
  },
116
116
  nodeResolve: true,
@@ -39,6 +39,7 @@ class ParallelCompilation extends angular_compilation_1.AngularCompilation {
39
39
  // is used when the Atomics based wait loop is enable.
40
40
  useAtomics: !process.versions.webcontainer,
41
41
  filename: localRequire.resolve('./parallel-worker'),
42
+ recordTiming: false,
42
43
  });
43
44
  }
44
45
  initialize(tsconfig, hostOptions, compilerOptionsTransformer) {
@@ -276,7 +276,6 @@ function getEsBuildCommonOptions(options) {
276
276
  },
277
277
  loader: loaderExtensions,
278
278
  footer,
279
- publicPath: options.publicPath,
280
279
  };
281
280
  }
282
281
  function getEsBuildCommonPolyfillsOptions(options, namespace, tryToResolvePolyfillsAsRelative, sourceFileCache) {
@@ -15,7 +15,7 @@ const node_assert_1 = __importDefault(require("node:assert"));
15
15
  const bundle_options_1 = require("./stylesheets/bundle-options");
16
16
  const virtual_module_plugin_1 = require("./virtual-module-plugin");
17
17
  function createGlobalStylesBundleOptions(options, target, initial) {
18
- const { workspaceRoot, optimizationOptions, sourcemapOptions, outputNames, globalStyles, preserveSymlinks, externalDependencies, stylePreprocessorOptions, tailwindConfiguration, postcssConfiguration, cacheOptions, publicPath, } = options;
18
+ const { workspaceRoot, optimizationOptions, sourcemapOptions, outputNames, globalStyles, preserveSymlinks, externalDependencies, stylePreprocessorOptions, tailwindConfiguration, postcssConfiguration, cacheOptions, } = options;
19
19
  const namespace = 'angular:styles/global';
20
20
  const entryPoints = {};
21
21
  let found = false;
@@ -48,7 +48,6 @@ function createGlobalStylesBundleOptions(options, target, initial) {
48
48
  tailwindConfiguration,
49
49
  postcssConfiguration,
50
50
  cacheOptions,
51
- publicPath,
52
51
  }, loadCache);
53
52
  // Keep special CSS comments `/*! comment */` in place when `removeSpecialComments` is disabled.
54
53
  // These comments are special for a number of CSS tools such as Critters and PurgeCSS.
@@ -83,6 +83,7 @@ class I18nInliner {
83
83
  shouldOptimize: options.shouldOptimize,
84
84
  files,
85
85
  },
86
+ recordTiming: false,
86
87
  });
87
88
  }
88
89
  /**
@@ -47,6 +47,7 @@ class JavaScriptTransformer {
47
47
  maxThreads: this.maxThreads,
48
48
  // Shutdown idle threads after 1 second of inactivity
49
49
  idleTimeout: 1000,
50
+ recordTiming: false,
50
51
  });
51
52
  return this.#workerPool;
52
53
  }
@@ -5,7 +5,7 @@
5
5
  * Use of this source code is governed by an MIT-style license that can be
6
6
  * found in the LICENSE file at https://angular.io/license
7
7
  */
8
- import { CompileResult, StringOptionsWithImporter, StringOptionsWithoutImporter } from 'sass';
8
+ import { CompileResult, StringOptions } from 'sass';
9
9
  /**
10
10
  * A Sass renderer implementation that provides an interface that can be used by Webpack's
11
11
  * `sass-loader`. The implementation uses a Worker thread to perform the Sass rendering
@@ -36,7 +36,7 @@ export declare class SassWorkerImplementation {
36
36
  * @param source The contents to compile.
37
37
  * @param options The `dart-sass` options to use when rendering the stylesheet.
38
38
  */
39
- compileStringAsync(source: string, options: StringOptionsWithImporter<'async'> | StringOptionsWithoutImporter<'async'>): Promise<CompileResult>;
39
+ compileStringAsync(source: string, options: StringOptions<'async'>): Promise<CompileResult>;
40
40
  /**
41
41
  * Shutdown the Sass render worker.
42
42
  * Executing this method will stop any pending render requests.
@@ -45,5 +45,5 @@ export declare class SassWorkerImplementation {
45
45
  private createWorker;
46
46
  private processImporters;
47
47
  private createRequest;
48
- private isImporter;
48
+ private isFileImporter;
49
49
  }
@@ -185,7 +185,7 @@ class SassWorkerImplementation {
185
185
  }
186
186
  async processImporters(importers, url, options) {
187
187
  for (const importer of importers) {
188
- if (this.isImporter(importer)) {
188
+ if (!this.isFileImporter(importer)) {
189
189
  // Importer
190
190
  throw new Error('Only File Importers are supported.');
191
191
  }
@@ -206,8 +206,8 @@ class SassWorkerImplementation {
206
206
  importers,
207
207
  };
208
208
  }
209
- isImporter(value) {
210
- return 'canonicalize' in value && 'load' in value;
209
+ isFileImporter(value) {
210
+ return 'findFileUrl' in value;
211
211
  }
212
212
  }
213
213
  exports.SassWorkerImplementation = SassWorkerImplementation;
@@ -116,6 +116,7 @@ class JavaScriptOptimizerPlugin {
116
116
  const workerPool = new piscina_1.default({
117
117
  filename: workerPath,
118
118
  maxThreads: MAX_OPTIMIZE_WORKERS,
119
+ recordTiming: false,
119
120
  });
120
121
  // Enqueue script optimization tasks and update compilation assets as the tasks complete
121
122
  try {
@@ -84,7 +84,7 @@ export default function ({ asset, options }: OptimizeRequest): Promise<{
84
84
  } | {
85
85
  name: string;
86
86
  code: string;
87
- map: import("@ampproject/remapping/dist/types/source-map").default | undefined;
87
+ map: import("@ampproject/remapping").SourceMap | undefined;
88
88
  errors?: undefined;
89
89
  }>;
90
90
  export {};
@@ -36,6 +36,7 @@ Object.defineProperty(exports, "__esModule", { value: true });
36
36
  exports.webpackStatsLogger = exports.generateBuildEventStats = exports.createWebpackLoggingCallback = exports.statsHasWarnings = exports.statsHasErrors = exports.statsErrorsToString = exports.statsWarningsToString = exports.generateBuildStatsTable = exports.generateEsbuildBuildStatsTable = exports.formatSize = void 0;
37
37
  const node_assert_1 = __importDefault(require("node:assert"));
38
38
  const path = __importStar(require("node:path"));
39
+ const node_util_1 = require("node:util");
39
40
  const utils_1 = require("../../../utils");
40
41
  const color_1 = require("../../../utils/color");
41
42
  const async_chunks_1 = require("./async-chunks");
@@ -237,7 +238,7 @@ function generateTableText(bundleInfo, colors) {
237
238
  continue;
238
239
  }
239
240
  const currentLongest = (longest[i] ??= 0);
240
- const currentItemLength = (0, color_1.removeColor)(currentItem).length;
241
+ const currentItemLength = (0, node_util_1.stripVTControlCharacters)(currentItem).length;
241
242
  if (currentLongest < currentItemLength) {
242
243
  longest[i] = currentItemLength;
243
244
  }
@@ -254,7 +255,7 @@ function generateTableText(bundleInfo, colors) {
254
255
  if (skipText(currentItem)) {
255
256
  continue;
256
257
  }
257
- const currentItemLength = (0, color_1.removeColor)(currentItem).length;
258
+ const currentItemLength = (0, node_util_1.stripVTControlCharacters)(currentItem).length;
258
259
  const stringPad = ' '.repeat(longest[i] - currentItemLength);
259
260
  // Values in columns at index 2 and 3 (Raw and Estimated sizes) are always right aligned.
260
261
  item[i] = i >= 2 ? stringPad + currentItem : currentItem + stringPad;
@@ -29,6 +29,7 @@ class BundleActionExecutor {
29
29
  name: 'inlineLocales',
30
30
  workerData: this.workerOptions,
31
31
  maxThreads: environment_options_1.maxWorkers,
32
+ recordTiming: false,
32
33
  });
33
34
  return this.workerPool;
34
35
  }
@@ -6,6 +6,5 @@
6
6
  * found in the LICENSE file at https://angular.io/license
7
7
  */
8
8
  import * as ansiColors from 'ansi-colors';
9
- export declare function removeColor(text: string): string;
10
9
  declare const colors: typeof ansiColors;
11
10
  export { colors };
@@ -30,9 +30,9 @@ var __importStar = (this && this.__importStar) || function (mod) {
30
30
  return result;
31
31
  };
32
32
  Object.defineProperty(exports, "__esModule", { value: true });
33
- exports.colors = exports.removeColor = void 0;
33
+ exports.colors = void 0;
34
34
  const ansiColors = __importStar(require("ansi-colors"));
35
- const tty_1 = require("tty");
35
+ const node_tty_1 = require("node:tty");
36
36
  function supportColor() {
37
37
  if (process.env.FORCE_COLOR !== undefined) {
38
38
  // 2 colors: FORCE_COLOR = 0 (Disables colors), depth 1
@@ -52,17 +52,11 @@ function supportColor() {
52
52
  return false;
53
53
  }
54
54
  }
55
- if (process.stdout instanceof tty_1.WriteStream) {
56
- return process.stdout.getColorDepth() > 1;
55
+ if (process.stdout instanceof node_tty_1.WriteStream) {
56
+ return process.stdout.hasColors();
57
57
  }
58
58
  return false;
59
59
  }
60
- function removeColor(text) {
61
- // This has been created because when colors.enabled is false unstyle doesn't work
62
- // see: https://github.com/doowb/ansi-colors/blob/a4794363369d7b4d1872d248fc43a12761640d8e/index.js#L38
63
- return text.replace(ansiColors.ansiRegex, '');
64
- }
65
- exports.removeColor = removeColor;
66
60
  // Create a separate instance to prevent unintended global changes to the color configuration
67
61
  const colors = ansiColors.create();
68
62
  exports.colors = colors;
@@ -8,38 +8,21 @@
8
8
  */
9
9
  Object.defineProperty(exports, "__esModule", { value: true });
10
10
  exports.htmlRewritingStream = void 0;
11
- const stream_1 = require("stream");
11
+ const node_stream_1 = require("node:stream");
12
+ const promises_1 = require("node:stream/promises");
12
13
  const load_esm_1 = require("../load-esm");
13
14
  async function htmlRewritingStream(content) {
14
15
  const { RewritingStream } = await (0, load_esm_1.loadEsmModule)('parse5-html-rewriting-stream');
15
- const chunks = [];
16
16
  const rewriter = new RewritingStream();
17
17
  return {
18
18
  rewriter,
19
- transformedContent: () => {
20
- return new Promise((resolve) => {
21
- new stream_1.Readable({
22
- encoding: 'utf8',
23
- read() {
24
- this.push(Buffer.from(content));
25
- this.push(null);
26
- },
27
- })
28
- .pipe(rewriter)
29
- .pipe(new stream_1.Writable({
30
- write(chunk, encoding, callback) {
31
- chunks.push(typeof chunk === 'string'
32
- ? Buffer.from(chunk, encoding)
33
- : chunk);
34
- callback();
35
- },
36
- final(callback) {
37
- callback();
38
- resolve(Buffer.concat(chunks).toString());
39
- },
40
- }));
41
- });
42
- },
19
+ transformedContent: () => (0, promises_1.pipeline)(node_stream_1.Readable.from(content), rewriter, async function (source) {
20
+ const chunks = [];
21
+ for await (const chunk of source) {
22
+ chunks.push(Buffer.from(chunk));
23
+ }
24
+ return Buffer.concat(chunks).toString('utf-8');
25
+ }),
43
26
  };
44
27
  }
45
28
  exports.htmlRewritingStream = htmlRewritingStream;
@@ -10,7 +10,6 @@ Object.defineProperty(exports, "__esModule", { value: true });
10
10
  exports.IndexHtmlGenerator = void 0;
11
11
  const promises_1 = require("node:fs/promises");
12
12
  const node_path_1 = require("node:path");
13
- const strip_bom_1 = require("../strip-bom");
14
13
  const augment_index_html_1 = require("./augment-index-html");
15
14
  const inline_critical_css_1 = require("./inline-critical-css");
16
15
  const inline_fonts_1 = require("./inline-fonts");
@@ -37,7 +36,7 @@ class IndexHtmlGenerator {
37
36
  ];
38
37
  }
39
38
  async process(options) {
40
- let content = (0, strip_bom_1.stripBom)(await this.readIndex(this.options.indexPath));
39
+ let content = await this.readIndex(this.options.indexPath);
41
40
  const warnings = [];
42
41
  const errors = [];
43
42
  for (const plugin of this.plugins) {
@@ -71,10 +70,10 @@ class IndexHtmlGenerator {
71
70
  }
72
71
  async readIndex(path) {
73
72
  try {
74
- return await (0, promises_1.readFile)(path, 'utf-8');
73
+ return new TextDecoder('utf-8').decode(await (0, promises_1.readFile)(path));
75
74
  }
76
- catch {
77
- throw new Error(`Failed to read index HTML file "${path}".`);
75
+ catch (cause) {
76
+ throw new Error(`Failed to read index HTML file "${path}".`, { cause });
78
77
  }
79
78
  }
80
79
  }
@@ -8,8 +8,8 @@
8
8
  */
9
9
  Object.defineProperty(exports, "__esModule", { value: true });
10
10
  exports.purgeStaleBuildCache = void 0;
11
- const fs_1 = require("fs");
12
- const path_1 = require("path");
11
+ const promises_1 = require("node:fs/promises");
12
+ const node_path_1 = require("node:path");
13
13
  const normalize_cache_1 = require("./normalize-cache");
14
14
  /** Delete stale cache directories used by previous versions of build-angular. */
15
15
  async function purgeStaleBuildCache(context) {
@@ -19,17 +19,22 @@ async function purgeStaleBuildCache(context) {
19
19
  }
20
20
  const metadata = await context.getProjectMetadata(projectName);
21
21
  const { basePath, path, enabled } = (0, normalize_cache_1.normalizeCacheOptions)(metadata, context.workspaceRoot);
22
- if (!enabled || !(0, fs_1.existsSync)(basePath)) {
22
+ if (!enabled) {
23
23
  return;
24
24
  }
25
- const entriesToDelete = (await fs_1.promises.readdir(basePath, { withFileTypes: true }))
26
- .filter((d) => (0, path_1.join)(basePath, d.name) !== path && d.isDirectory())
27
- .map((d) => {
28
- const subPath = (0, path_1.join)(basePath, d.name);
29
- return fs_1.promises
30
- .rm(subPath, { force: true, recursive: true, maxRetries: 3 })
31
- .catch(() => void 0);
32
- });
33
- await Promise.all(entriesToDelete);
25
+ let baseEntries;
26
+ try {
27
+ baseEntries = await (0, promises_1.readdir)(basePath, { withFileTypes: true });
28
+ }
29
+ catch {
30
+ // No purging possible if base path does not exist or cannot otherwise be accessed
31
+ return;
32
+ }
33
+ const entriesToDelete = baseEntries
34
+ .filter((d) => d.isDirectory())
35
+ .map((d) => (0, node_path_1.join)(basePath, d.name))
36
+ .filter((cachePath) => cachePath !== path)
37
+ .map((stalePath) => (0, promises_1.rm)(stalePath, { force: true, recursive: true, maxRetries: 3 }));
38
+ await Promise.allSettled(entriesToDelete);
34
39
  }
35
40
  exports.purgeStaleBuildCache = purgeStaleBuildCache;
@@ -97,6 +97,7 @@ async function renderPages(sourcemap, allRoutes, maxThreads, workspaceRoot, outp
97
97
  document,
98
98
  },
99
99
  execArgv: workerExecArgv,
100
+ recordTiming: false,
100
101
  });
101
102
  try {
102
103
  const renderingPromises = [];
@@ -163,6 +164,7 @@ async function getAllRoutes(workspaceRoot, outputFilesForWorker, assetFilesForWo
163
164
  verbose,
164
165
  },
165
166
  execArgv: workerExecArgv,
167
+ recordTiming: false,
166
168
  });
167
169
  const { routes: extractedRoutes, warnings } = await renderWorker
168
170
  .run({})
@@ -9,32 +9,30 @@
9
9
  Object.defineProperty(exports, "__esModule", { value: true });
10
10
  exports.assertCompatibleAngularVersion = void 0;
11
11
  /* eslint-disable no-console */
12
- const core_1 = require("@angular-devkit/core");
12
+ const node_module_1 = require("node:module");
13
13
  const semver_1 = require("semver");
14
14
  function assertCompatibleAngularVersion(projectRoot) {
15
15
  let angularCliPkgJson;
16
16
  let angularPkgJson;
17
- const resolveOptions = { paths: [projectRoot] };
17
+ // Create a custom require function for ESM compliance.
18
+ // NOTE: The trailing slash is significant.
19
+ const projectRequire = (0, node_module_1.createRequire)(projectRoot + '/');
18
20
  try {
19
- const angularPackagePath = require.resolve('@angular/core/package.json', resolveOptions);
20
- angularPkgJson = require(angularPackagePath);
21
+ const angularPackagePath = projectRequire.resolve('@angular/core/package.json');
22
+ angularPkgJson = projectRequire(angularPackagePath);
21
23
  }
22
24
  catch {
23
- console.error(core_1.tags.stripIndents `
24
- You seem to not be depending on "@angular/core". This is an error.
25
- `);
25
+ console.error('You seem to not be depending on "@angular/core". This is an error.');
26
26
  process.exit(2);
27
27
  }
28
28
  if (!(angularPkgJson && angularPkgJson['version'])) {
29
- console.error(core_1.tags.stripIndents `
30
- Cannot determine versions of "@angular/core".
31
- This likely means your local installation is broken. Please reinstall your packages.
32
- `);
29
+ console.error('Cannot determine versions of "@angular/core".\n' +
30
+ 'This likely means your local installation is broken. Please reinstall your packages.');
33
31
  process.exit(2);
34
32
  }
35
33
  try {
36
- const angularCliPkgPath = require.resolve('@angular/cli/package.json', resolveOptions);
37
- angularCliPkgJson = require(angularCliPkgPath);
34
+ const angularCliPkgPath = projectRequire.resolve('@angular/cli/package.json');
35
+ angularCliPkgJson = projectRequire(angularCliPkgPath);
38
36
  if (!(angularCliPkgJson && angularCliPkgJson['version'])) {
39
37
  return;
40
38
  }
@@ -49,16 +47,12 @@ function assertCompatibleAngularVersion(projectRoot) {
49
47
  // repository with the generated development @angular/core npm package which is versioned "0.0.0".
50
48
  return;
51
49
  }
52
- const supportedAngularSemver = require('../../package.json')['peerDependencies']['@angular/compiler-cli'];
50
+ const supportedAngularSemver = projectRequire('@angular-devkit/build-angular/package.json')['peerDependencies']['@angular/compiler-cli'];
53
51
  const angularVersion = new semver_1.SemVer(angularPkgJson['version']);
54
52
  if (!(0, semver_1.satisfies)(angularVersion, supportedAngularSemver, { includePrerelease: true })) {
55
- console.error(core_1.tags.stripIndents `
56
- This version of CLI is only compatible with Angular versions ${supportedAngularSemver},
57
- but Angular version ${angularVersion} was found instead.
58
-
59
- Please visit the link below to find instructions on how to update Angular.
60
- https://update.angular.io/
61
- ` + '\n');
53
+ console.error(`This version of CLI is only compatible with Angular versions ${supportedAngularSemver},\n` +
54
+ `but Angular version ${angularVersion} was found instead.\n` +
55
+ 'Please visit the link below to find instructions on how to update Angular.\nhttps://update.angular.io/');
62
56
  process.exit(3);
63
57
  }
64
58
  }
@@ -1,8 +0,0 @@
1
- /**
2
- * @license
3
- * Copyright Google LLC All Rights Reserved.
4
- *
5
- * Use of this source code is governed by an MIT-style license that can be
6
- * found in the LICENSE file at https://angular.io/license
7
- */
8
- export declare function stripBom(data: string): string;
@@ -1,17 +0,0 @@
1
- "use strict";
2
- /**
3
- * @license
4
- * Copyright Google LLC All Rights Reserved.
5
- *
6
- * Use of this source code is governed by an MIT-style license that can be
7
- * found in the LICENSE file at https://angular.io/license
8
- */
9
- Object.defineProperty(exports, "__esModule", { value: true });
10
- exports.stripBom = void 0;
11
- // TODO: cleanup this file, it's copied as is from Angular CLI.
12
- // Strip BOM from file data.
13
- // https://stackoverflow.com/questions/24356713
14
- function stripBom(data) {
15
- return data.replace(/^\uFEFF/, '');
16
- }
17
- exports.stripBom = stripBom;