@angular/build 20.2.0-next.0 → 20.2.0-next.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": "@angular/build",
3
- "version": "20.2.0-next.0",
3
+ "version": "20.2.0-next.2",
4
4
  "description": "Official build system for Angular",
5
5
  "keywords": [
6
6
  "Angular CLI",
@@ -23,15 +23,15 @@
23
23
  "builders": "builders.json",
24
24
  "dependencies": {
25
25
  "@ampproject/remapping": "2.3.0",
26
- "@angular-devkit/architect": "0.2002.0-next.0",
26
+ "@angular-devkit/architect": "0.2002.0-next.2",
27
27
  "@babel/core": "7.28.0",
28
28
  "@babel/helper-annotate-as-pure": "7.27.3",
29
29
  "@babel/helper-split-export-declaration": "7.24.7",
30
- "@inquirer/confirm": "5.1.13",
30
+ "@inquirer/confirm": "5.1.14",
31
31
  "@vitejs/plugin-basic-ssl": "2.1.0",
32
32
  "beasties": "0.3.5",
33
33
  "browserslist": "^4.23.0",
34
- "esbuild": "0.25.6",
34
+ "esbuild": "0.25.8",
35
35
  "https-proxy-agent": "7.0.6",
36
36
  "istanbul-lib-instrument": "6.0.3",
37
37
  "jsonc-parser": "3.3.1",
@@ -39,14 +39,14 @@
39
39
  "magic-string": "0.30.17",
40
40
  "mrmime": "2.0.1",
41
41
  "parse5-html-rewriting-stream": "8.0.0",
42
- "picomatch": "4.0.2",
42
+ "picomatch": "4.0.3",
43
43
  "piscina": "5.1.3",
44
- "rollup": "4.45.1",
44
+ "rolldown": "1.0.0-beta.29",
45
45
  "sass": "1.89.2",
46
46
  "semver": "7.7.2",
47
47
  "source-map-support": "0.5.21",
48
48
  "tinyglobby": "0.2.14",
49
- "vite": "7.0.4",
49
+ "vite": "7.0.6",
50
50
  "watchpack": "2.4.4"
51
51
  },
52
52
  "optionalDependencies": {
@@ -60,14 +60,14 @@
60
60
  "@angular/platform-browser": "^20.0.0 || ^20.2.0-next.0",
61
61
  "@angular/platform-server": "^20.0.0 || ^20.2.0-next.0",
62
62
  "@angular/service-worker": "^20.0.0 || ^20.2.0-next.0",
63
- "@angular/ssr": "^20.2.0-next.0",
63
+ "@angular/ssr": "^20.2.0-next.2",
64
64
  "karma": "^6.4.0",
65
65
  "less": "^4.2.0",
66
66
  "ng-packagr": "^20.0.0 || ^20.2.0-next.0",
67
67
  "postcss": "^8.4.0",
68
68
  "tailwindcss": "^2.0.0 || ^3.0.0 || ^4.0.0",
69
69
  "tslib": "^2.3.0",
70
- "typescript": ">=5.8 <5.9",
70
+ "typescript": ">=5.8 <6.0",
71
71
  "vitest": "^3.1.1"
72
72
  },
73
73
  "peerDependenciesMeta": {
@@ -12,7 +12,7 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
12
12
  Object.defineProperty(exports, "__esModule", { value: true });
13
13
  exports.optimizeChunks = optimizeChunks;
14
14
  const node_assert_1 = __importDefault(require("node:assert"));
15
- const rollup_1 = require("rollup");
15
+ const rolldown_1 = require("rolldown");
16
16
  const bundler_context_1 = require("../../tools/esbuild/bundler-context");
17
17
  const utils_1 = require("../../tools/esbuild/utils");
18
18
  const error_1 = require("../../utils/error");
@@ -54,7 +54,7 @@ async function optimizeChunks(original, sourcemap) {
54
54
  let bundle;
55
55
  let optimizedOutput;
56
56
  try {
57
- bundle = await (0, rollup_1.rollup)({
57
+ bundle = await (0, rolldown_1.rolldown)({
58
58
  input: mainFile,
59
59
  plugins: [
60
60
  {
@@ -81,7 +81,7 @@ async function optimizeChunks(original, sourcemap) {
81
81
  ],
82
82
  });
83
83
  const result = await bundle.generate({
84
- compact: true,
84
+ minify: { mangle: false, compress: false, removeWhitespace: true },
85
85
  sourcemap,
86
86
  chunkFileNames: (chunkInfo) => `${chunkInfo.name.replace(/-[a-zA-Z0-9]{8}$/, '')}-[hash].js`,
87
87
  });
@@ -256,6 +256,13 @@ function findBrowserProvider(projectResolver) {
256
256
  catch { }
257
257
  }
258
258
  }
259
+ function normalizeBrowserName(browserName) {
260
+ // Normalize browser names to match Vitest's expectations for headless but also supports karma's names
261
+ // e.g., 'ChromeHeadless' -> 'chrome', 'FirefoxHeadless'
262
+ // and 'Chrome' -> 'chrome', 'Firefox' -> 'firefox'.
263
+ const normalized = browserName.toLowerCase();
264
+ return normalized.replace(/headless$/, '');
265
+ }
259
266
  function setupBrowserConfiguration(browsers, debug, projectSourceRoot) {
260
267
  if (browsers === undefined) {
261
268
  return {};
@@ -288,8 +295,9 @@ function setupBrowserConfiguration(browsers, debug, projectSourceRoot) {
288
295
  const browser = {
289
296
  enabled: true,
290
297
  provider,
298
+ headless: browsers.some((name) => name.toLowerCase().includes('headless')),
291
299
  instances: browsers.map((browserName) => ({
292
- browser: browserName,
300
+ browser: normalizeBrowserName(browserName),
293
301
  })),
294
302
  };
295
303
  return { browser };
@@ -4,7 +4,8 @@
4
4
  export type Schema = {
5
5
  /**
6
6
  * A list of browsers to use for test execution. If undefined, jsdom on Node.js will be used
7
- * instead of a browser.
7
+ * instead of a browser. For Vitest and Karma, browser names ending with 'Headless' (e.g.,
8
+ * 'ChromeHeadless') will enable headless mode for that browser.
8
9
  */
9
10
  browsers?: string[];
10
11
  /**
@@ -19,7 +19,7 @@
19
19
  "enum": ["karma", "vitest"]
20
20
  },
21
21
  "browsers": {
22
- "description": "A list of browsers to use for test execution. If undefined, jsdom on Node.js will be used instead of a browser.",
22
+ "description": "A list of browsers to use for test execution. If undefined, jsdom on Node.js will be used instead of a browser. For Vitest and Karma, browser names ending with 'Headless' (e.g., 'ChromeHeadless') will enable headless mode for that browser.",
23
23
  "type": "array",
24
24
  "items": {
25
25
  "type": "string"
@@ -9,8 +9,12 @@
9
9
  Object.defineProperty(exports, "__esModule", { value: true });
10
10
  exports.createAngularAssetsMiddleware = createAngularAssetsMiddleware;
11
11
  const mrmime_1 = require("mrmime");
12
+ const node_crypto_1 = require("node:crypto");
13
+ const node_fs_1 = require("node:fs");
12
14
  const node_path_1 = require("node:path");
13
15
  const utils_1 = require("../utils");
16
+ const CSS_PREPROCESSOR_REGEXP = /\.(?:s[ac]ss|less|css)$/;
17
+ const JS_TS_REGEXP = /\.[cm]?[tj]sx?$/;
14
18
  function createAngularAssetsMiddleware(server, assets, outputFiles, componentStyles, encapsulateStyle) {
15
19
  return function angularAssetsMiddleware(req, res, next) {
16
20
  if (req.url === undefined || res.writableEnded) {
@@ -24,14 +28,27 @@ function createAngularAssetsMiddleware(server, assets, outputFiles, componentSty
24
28
  // Rewrite all build assets to a vite raw fs URL
25
29
  const asset = assets.get(pathname);
26
30
  if (asset) {
27
- // Workaround to disable Vite transformer middleware.
28
- // See: https://github.com/vitejs/vite/blob/746a1daab0395f98f0afbdee8f364cb6cf2f3b3f/packages/vite/src/node/server/middlewares/transform.ts#L201 and
29
- // https://github.com/vitejs/vite/blob/746a1daab0395f98f0afbdee8f364cb6cf2f3b3f/packages/vite/src/node/server/transformRequest.ts#L204-L206
30
- req.headers.accept = 'text/html';
31
- // The encoding needs to match what happens in the vite static middleware.
32
- // ref: https://github.com/vitejs/vite/blob/d4f13bd81468961c8c926438e815ab6b1c82735e/packages/vite/src/node/server/middlewares/static.ts#L163
33
- req.url = `${server.config.base}@fs/${encodeURI(asset.source)}`;
34
- next();
31
+ // This is a workaround to serve CSS, JS and TS files without Vite transformations.
32
+ if (JS_TS_REGEXP.test(extension) || CSS_PREPROCESSOR_REGEXP.test(extension)) {
33
+ const contents = (0, node_fs_1.readFileSync)(asset.source);
34
+ const etag = `W/${(0, node_crypto_1.createHash)('sha256').update(contents).digest('hex')}`;
35
+ if (checkAndHandleEtag(req, res, etag)) {
36
+ return;
37
+ }
38
+ const mimeType = (0, mrmime_1.lookup)(extension);
39
+ if (mimeType) {
40
+ res.setHeader('Content-Type', mimeType);
41
+ }
42
+ res.setHeader('ETag', etag);
43
+ res.setHeader('Cache-Control', 'no-cache');
44
+ res.end(contents);
45
+ }
46
+ else {
47
+ // The encoding needs to match what happens in the vite static middleware.
48
+ // ref: https://github.com/vitejs/vite/blob/d4f13bd81468961c8c926438e815ab6b1c82735e/packages/vite/src/node/server/middlewares/static.ts#L163
49
+ req.url = `${server.config.base}@fs/${encodeURI(asset.source)}`;
50
+ next();
51
+ }
35
52
  return;
36
53
  }
37
54
  // HTML fallbacking
@@ -78,11 +95,8 @@ function createAngularAssetsMiddleware(server, assets, outputFiles, componentSty
78
95
  else {
79
96
  componentStyle.used.add(componentId);
80
97
  }
81
- // Report if there are no changes to avoid reprocessing
82
98
  const etag = `W/"${outputFile.contents.byteLength}-${outputFile.hash}-${componentId}"`;
83
- if (req.headers['if-none-match'] === etag) {
84
- res.statusCode = 304;
85
- res.end();
99
+ if (checkAndHandleEtag(req, res, etag)) {
86
100
  return;
87
101
  }
88
102
  // Shim the stylesheet if a component ID is provided
@@ -105,11 +119,8 @@ function createAngularAssetsMiddleware(server, assets, outputFiles, componentSty
105
119
  return;
106
120
  }
107
121
  }
108
- // Avoid resending the content if it has not changed since last request
109
122
  const etag = `W/"${outputFile.contents.byteLength}-${outputFile.hash}"`;
110
- if (req.headers['if-none-match'] === etag) {
111
- res.statusCode = 304;
112
- res.end();
123
+ if (checkAndHandleEtag(req, res, etag)) {
113
124
  return;
114
125
  }
115
126
  const mimeType = (0, mrmime_1.lookup)(extension);
@@ -152,3 +163,11 @@ function createAngularAssetsMiddleware(server, assets, outputFiles, componentSty
152
163
  next();
153
164
  };
154
165
  }
166
+ function checkAndHandleEtag(req, res, etag) {
167
+ if (req.headers['if-none-match'] === etag) {
168
+ res.statusCode = 304;
169
+ res.end();
170
+ return true;
171
+ }
172
+ return false;
173
+ }
@@ -27,6 +27,7 @@ async function createAngularSsrTransformPlugin(workspaceRoot) {
27
27
  remappedMap.sourceRoot = normalizePath(workspaceRoot) + '/';
28
28
  return {
29
29
  code,
30
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
30
31
  map: remappedMap,
31
32
  };
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.2.0-next.0';
13
+ const VERSION = '20.2.0-next.2';
14
14
  function hasCacheMetadata(value) {
15
15
  return (!!value &&
16
16
  typeof value === 'object' &&