@angular/build 20.0.0-next.2 → 20.0.0-next.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 CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@angular/build",
3
- "version": "20.0.0-next.2",
3
+ "version": "20.0.0-next.3",
4
4
  "description": "Official build system for Angular",
5
5
  "keywords": [
6
6
  "Angular CLI",
@@ -23,7 +23,7 @@
23
23
  "builders": "builders.json",
24
24
  "dependencies": {
25
25
  "@ampproject/remapping": "2.3.0",
26
- "@angular-devkit/architect": "0.2000.0-next.2",
26
+ "@angular-devkit/architect": "0.2000.0-next.3",
27
27
  "@babel/core": "7.26.10",
28
28
  "@babel/helper-annotate-as-pure": "7.25.9",
29
29
  "@babel/helper-split-export-declaration": "7.24.7",
@@ -42,12 +42,12 @@
42
42
  "parse5-html-rewriting-stream": "7.0.0",
43
43
  "picomatch": "4.0.2",
44
44
  "piscina": "4.9.2",
45
- "rollup": "4.36.0",
45
+ "rollup": "4.37.0",
46
46
  "sass": "1.86.0",
47
47
  "semver": "7.7.1",
48
48
  "source-map-support": "0.5.21",
49
49
  "tinyglobby": "0.2.12",
50
- "vite": "6.2.2",
50
+ "vite": "6.2.3",
51
51
  "watchpack": "2.4.2"
52
52
  },
53
53
  "optionalDependencies": {
@@ -57,9 +57,10 @@
57
57
  "@angular/compiler": "^20.0.0 || ^20.0.0-next.0",
58
58
  "@angular/compiler-cli": "^20.0.0 || ^20.0.0-next.0",
59
59
  "@angular/localize": "^20.0.0 || ^20.0.0-next.0",
60
+ "@angular/platform-browser": "^20.0.0 || ^20.0.0-next.0",
60
61
  "@angular/platform-server": "^20.0.0 || ^20.0.0-next.0",
61
62
  "@angular/service-worker": "^20.0.0 || ^20.0.0-next.0",
62
- "@angular/ssr": "^20.0.0-next.2",
63
+ "@angular/ssr": "^20.0.0-next.3",
63
64
  "karma": "^6.4.0",
64
65
  "less": "^4.2.0",
65
66
  "ng-packagr": "^20.0.0 || ^20.0.0-next.0",
@@ -71,6 +72,9 @@
71
72
  "@angular/localize": {
72
73
  "optional": true
73
74
  },
75
+ "@angular/platform-browser": {
76
+ "optional": true
77
+ },
74
78
  "@angular/platform-server": {
75
79
  "optional": true
76
80
  },
@@ -102,7 +106,7 @@
102
106
  },
103
107
  "packageManager": "pnpm@9.15.6",
104
108
  "engines": {
105
- "node": "^20.11.1 || >=22.0.0",
109
+ "node": "^20.11.1 || >=22.11.0",
106
110
  "npm": "^6.11.0 || ^7.5.6 || >=8.0.0",
107
111
  "yarn": ">= 1.13.0"
108
112
  },
@@ -27,6 +27,7 @@ const build_action_1 = require("./build-action");
27
27
  const execute_build_1 = require("./execute-build");
28
28
  const options_1 = require("./options");
29
29
  const results_1 = require("./results");
30
+ const isNodeV22orHigher = Number(process.versions.node.split('.', 1)[0]) >= 22;
30
31
  async function* buildApplicationInternal(options,
31
32
  // TODO: Integrate abort signal support into builder system
32
33
  context, extensions) {
@@ -162,7 +163,18 @@ async function* buildApplication(options, context, extensions) {
162
163
  }
163
164
  else {
164
165
  // Copy file contents
165
- await promises_1.default.copyFile(file.inputPath, fullFilePath, promises_1.default.constants.COPYFILE_FICLONE);
166
+ if (isNodeV22orHigher) {
167
+ // Use newer `cp` API on Node.js 22+ (minimum v22 for CLI is 22.11)
168
+ await promises_1.default.cp(file.inputPath, fullFilePath, {
169
+ mode: promises_1.default.constants.COPYFILE_FICLONE,
170
+ preserveTimestamps: true,
171
+ });
172
+ }
173
+ else {
174
+ // For Node.js 20 use `copyFile` (`cp` is not stable for v20)
175
+ // TODO: Remove when Node.js 20 is no longer supported
176
+ await promises_1.default.copyFile(file.inputPath, fullFilePath, promises_1.default.constants.COPYFILE_FICLONE);
177
+ }
166
178
  }
167
179
  });
168
180
  // Delete any removed files if incremental
@@ -163,7 +163,7 @@ async function normalizeOptions(context, projectName, options, extensions) {
163
163
  route: 'shell',
164
164
  };
165
165
  }
166
- const outputPath = options.outputPath;
166
+ const outputPath = options.outputPath ?? node_path_1.default.join(workspaceRoot, 'dist', projectName);
167
167
  const outputOptions = {
168
168
  browser: 'browser',
169
169
  server: 'server',
@@ -128,7 +128,7 @@ export type Schema = {
128
128
  /**
129
129
  * Specify the output path relative to workspace root.
130
130
  */
131
- outputPath: OutputPathUnion;
131
+ outputPath?: OutputPathUnion;
132
132
  /**
133
133
  * Enable and define the file watching poll time period in milliseconds.
134
134
  */
@@ -513,6 +513,10 @@ export type SourceMapClass = {
513
513
  * Output source maps for all scripts.
514
514
  */
515
515
  scripts?: boolean;
516
+ /**
517
+ * Output original source content for files within the source map.
518
+ */
519
+ sourcesContent?: boolean;
516
520
  /**
517
521
  * Output source maps for all styles.
518
522
  */
@@ -370,6 +370,11 @@
370
370
  "type": "boolean",
371
371
  "description": "Resolve vendor packages source maps.",
372
372
  "default": false
373
+ },
374
+ "sourcesContent": {
375
+ "type": "boolean",
376
+ "description": "Output original source content for files within the source map.",
377
+ "default": true
373
378
  }
374
379
  },
375
380
  "additionalProperties": false
@@ -605,7 +610,7 @@
605
610
  }
606
611
  },
607
612
  "additionalProperties": false,
608
- "required": ["outputPath", "index", "browser", "tsConfig"],
613
+ "required": ["index", "browser", "tsConfig"],
609
614
  "definitions": {
610
615
  "assetPattern": {
611
616
  "oneOf": [
@@ -86,6 +86,7 @@ function createComponentStyleBundler(options, target) {
86
86
  // the same as being disabled. Disabling has the advantage of avoiding the overhead
87
87
  // of sourcemap processing.
88
88
  sourcemapOptions.styles && !sourcemapOptions.hidden ? 'linked' : false,
89
+ sourcesContent: sourcemapOptions.sourcesContent,
89
90
  outputNames,
90
91
  includePaths: stylePreprocessorOptions?.includePaths,
91
92
  // string[] | undefined' is not assignable to type '(Version | DeprecationOrId)[] | undefined'.
@@ -54,6 +54,7 @@ const results_1 = require("../application/results");
54
54
  const schema_1 = require("../application/schema");
55
55
  const find_tests_1 = require("./find-tests");
56
56
  const localResolve = (0, node_module_1.createRequire)(__filename).resolve;
57
+ const isWindows = process.platform === 'win32';
57
58
  class ApplicationBuildError extends Error {
58
59
  constructor(message) {
59
60
  super(message);
@@ -74,7 +75,13 @@ class AngularAssetsMiddleware {
74
75
  let err = null;
75
76
  try {
76
77
  const url = new URL(`http://${req.headers['host']}${req.url}`);
77
- const file = this.latestBuildFiles.files[url.pathname.slice(1)];
78
+ // Remove the leading slash from the URL path and convert to platform specific.
79
+ // The latest build files will use the platform path separator.
80
+ let pathname = url.pathname.slice(1);
81
+ if (isWindows) {
82
+ pathname = pathname.replaceAll(path.posix.sep, path.win32.sep);
83
+ }
84
+ const file = this.latestBuildFiles.files[pathname];
78
85
  if (file?.origin === 'disk') {
79
86
  this.serveFile(file.inputPath, undefined, res);
80
87
  return;
@@ -7,13 +7,12 @@
7
7
  */
8
8
 
9
9
  import { getTestBed } from '@angular/core/testing';
10
- import {
11
- BrowserDynamicTestingModule,
12
- platformBrowserDynamicTesting,
13
- } from '@angular/platform-browser-dynamic/testing';
10
+ import { platformBrowser } from '@angular/platform-browser';
11
+ import { BrowserTestingModule } from '@angular/platform-browser/testing';
14
12
 
13
+ // TODO(alanagius): replace with `platformBrowserTesting` once https://github.com/angular/angular/pull/60480 is released.
15
14
  // Initialize the Angular testing environment.
16
- getTestBed().initTestEnvironment(BrowserDynamicTestingModule, platformBrowserDynamicTesting(), {
15
+ getTestBed().initTestEnvironment(BrowserTestingModule, platformBrowser(), {
17
16
  errorOnUnknownElements: true,
18
17
  errorOnUnknownProperties: true,
19
18
  });
@@ -416,6 +416,7 @@ function getEsBuildCommonOptions(options) {
416
416
  outdir: workspaceRoot,
417
417
  outExtension: outExtension ? { '.js': `.${outExtension}` } : undefined,
418
418
  sourcemap: sourcemapOptions.scripts && (sourcemapOptions.hidden ? 'external' : true),
419
+ sourcesContent: sourcemapOptions.sourcesContent,
419
420
  splitting: true,
420
421
  chunkNames: options.namedChunks ? '[name]-[hash]' : 'chunk-[hash]',
421
422
  tsconfig,
@@ -35,6 +35,7 @@ function createGlobalStylesBundleOptions(options, target, initial) {
35
35
  optimization: !!optimizationOptions.styles.minify,
36
36
  inlineFonts: !!optimizationOptions.fonts.inline,
37
37
  sourcemap: !!sourcemapOptions.styles && (sourcemapOptions.hidden ? 'external' : true),
38
+ sourcesContent: sourcemapOptions.sourcesContent,
38
39
  preserveSymlinks,
39
40
  target,
40
41
  externalDependencies,
@@ -16,6 +16,7 @@ export interface BundleStylesheetOptions {
16
16
  inlineFonts: boolean;
17
17
  preserveSymlinks?: boolean;
18
18
  sourcemap: boolean | 'external' | 'inline' | 'linked';
19
+ sourcesContent?: boolean;
19
20
  outputNames: {
20
21
  bundles: string;
21
22
  media: string;
@@ -47,6 +47,7 @@ function createStylesheetBundleOptions(options, cache, inlineComponentData) {
47
47
  minify: options.optimization,
48
48
  metafile: true,
49
49
  sourcemap: options.sourcemap,
50
+ sourcesContent: options.sourcesContent,
50
51
  outdir: options.workspaceRoot,
51
52
  write: false,
52
53
  platform: 'browser',
@@ -315,7 +315,7 @@ function transformSupportedBrowsersToTargets(supportedBrowsers) {
315
315
  }
316
316
  return transformed;
317
317
  }
318
- const SUPPORTED_NODE_VERSIONS = '^20.11.1 || >=22.0.0';
318
+ const SUPPORTED_NODE_VERSIONS = '^20.11.1 || >=22.11.0';
319
319
  /**
320
320
  * Transform supported Node.js versions to esbuild target.
321
321
  * @see https://esbuild.github.io/api/#target
@@ -22,11 +22,12 @@ function createAngularSsrInternalMiddleware(server, indexHtmlTransformer) {
22
22
  // which must be processed by the runtime linker, even if they are not used.
23
23
  await (0, load_esm_1.loadEsmModule)('@angular/compiler');
24
24
  const { writeResponseToNodeResponse, createWebRequestFromNodeRequest } = await (0, load_esm_1.loadEsmModule)('@angular/ssr/node');
25
- // The following is necessary because accessing the module after invalidation may result in an empty module,
26
- // which can trigger a `TypeError: ɵgetOrCreateAngularServerApp is not a function` error.
27
- // TODO: look into why.
28
- await server.ssrLoadModule('/main.server.mjs');
29
25
  const { ɵgetOrCreateAngularServerApp } = (await server.ssrLoadModule('/main.server.mjs'));
26
+ // `ɵgetOrCreateAngularServerApp` can be undefined right after an error.
27
+ // See: https://github.com/angular/angular-cli/issues/29907
28
+ if (!ɵgetOrCreateAngularServerApp) {
29
+ return next();
30
+ }
30
31
  const angularServerApp = ɵgetOrCreateAngularServerApp({
31
32
  allowStaticRouteRender: true,
32
33
  });
@@ -10,7 +10,7 @@ Object.defineProperty(exports, "__esModule", { value: true });
10
10
  exports.normalizeCacheOptions = normalizeCacheOptions;
11
11
  const node_path_1 = require("node:path");
12
12
  /** Version placeholder is replaced during the build process with actual package version */
13
- const VERSION = '20.0.0-next.2';
13
+ const VERSION = '20.0.0-next.3';
14
14
  function hasCacheMetadata(value) {
15
15
  return (!!value &&
16
16
  typeof value === 'object' &&
@@ -13,10 +13,12 @@ function normalizeSourceMaps(sourceMap) {
13
13
  const styles = typeof sourceMap === 'object' ? sourceMap.styles : sourceMap;
14
14
  const hidden = (typeof sourceMap === 'object' && sourceMap.hidden) || false;
15
15
  const vendor = (typeof sourceMap === 'object' && sourceMap.vendor) || false;
16
+ const sourcesContent = typeof sourceMap === 'object' ? sourceMap.sourcesContent : sourceMap;
16
17
  return {
17
18
  vendor,
18
19
  hidden,
19
20
  scripts,
20
21
  styles,
22
+ sourcesContent,
21
23
  };
22
24
  }
@@ -34,7 +34,7 @@ async function launchServer() {
34
34
  // handle request
35
35
  if ((0, utils_1.isSsrNodeRequestHandler)(reqHandler)) {
36
36
  await reqHandler(req, res, (e) => {
37
- throw e;
37
+ throw e ?? new Error(`Unable to handle request: '${req.url}'.`);
38
38
  });
39
39
  }
40
40
  else {
@@ -54,7 +54,7 @@ async function prerenderPages(workspaceRoot, baseHref, appShellOptions, prerende
54
54
  // Get routes to prerender
55
55
  const { errors: extractionErrors, serializedRouteTree: serializableRouteTreeNode, appShellRoute, } = await getAllRoutes(workspaceRoot, baseHref, outputFilesForWorker, assetsReversed, appShellOptions, prerenderOptions, sourcemap, outputMode).catch((err) => {
56
56
  return {
57
- errors: [`An error occurred while extracting routes.\n\n${err.stack ?? err.message ?? err}`],
57
+ errors: [`An error occurred while extracting routes.\n\n${err.message ?? err.stack ?? err}`],
58
58
  serializedRouteTree: [],
59
59
  appShellRoute: undefined,
60
60
  };
@@ -150,7 +150,7 @@ async function renderPages(baseHref, sourcemap, serializableRouteTreeNode, maxTh
150
150
  }
151
151
  })
152
152
  .catch((err) => {
153
- errors.push(`An error occurred while prerendering route '${route}'.\n\n${err.stack ?? err.message ?? err.code ?? err}`);
153
+ errors.push(`An error occurred while prerendering route '${route}'.\n\n${err.message ?? err.stack ?? err.code ?? err}`);
154
154
  void renderWorker.destroy();
155
155
  });
156
156
  renderingPromises.push(renderResult);
@@ -222,7 +222,7 @@ async function getAllRoutes(workspaceRoot, baseHref, outputFilesForWorker, asset
222
222
  (0, error_1.assertIsError)(err);
223
223
  return {
224
224
  errors: [
225
- `An error occurred while extracting routes.\n\n${err.stack ?? err.message ?? err.code ?? err}`,
225
+ `An error occurred while extracting routes.\n\n${err.message ?? err.stack ?? err.code ?? err}`,
226
226
  ],
227
227
  serializedRouteTree: [],
228
228
  };