@angular-devkit/build-angular 21.0.0-next.4 → 21.0.0-next.6

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,16 +1,16 @@
1
1
  {
2
2
  "name": "@angular-devkit/build-angular",
3
- "version": "21.0.0-next.4",
3
+ "version": "21.0.0-next.6",
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.3.0",
10
- "@angular-devkit/architect": "0.2100.0-next.4",
11
- "@angular-devkit/build-webpack": "0.2100.0-next.4",
12
- "@angular-devkit/core": "21.0.0-next.4",
13
- "@angular/build": "21.0.0-next.4",
10
+ "@angular-devkit/architect": "0.2100.0-next.6",
11
+ "@angular-devkit/build-webpack": "0.2100.0-next.6",
12
+ "@angular-devkit/core": "21.0.0-next.6",
13
+ "@angular/build": "21.0.0-next.6",
14
14
  "@babel/core": "7.28.4",
15
15
  "@babel/generator": "7.28.3",
16
16
  "@babel/helper-annotate-as-pure": "7.27.3",
@@ -21,14 +21,14 @@
21
21
  "@babel/preset-env": "7.28.3",
22
22
  "@babel/runtime": "7.28.4",
23
23
  "@discoveryjs/json-ext": "0.6.3",
24
- "@ngtools/webpack": "21.0.0-next.4",
24
+ "@ngtools/webpack": "21.0.0-next.6",
25
25
  "ansi-colors": "4.1.3",
26
26
  "autoprefixer": "10.4.21",
27
27
  "babel-loader": "10.0.0",
28
28
  "browserslist": "^4.26.0",
29
29
  "copy-webpack-plugin": "13.0.1",
30
30
  "css-loader": "7.1.2",
31
- "esbuild-wasm": "0.25.9",
31
+ "esbuild-wasm": "0.25.10",
32
32
  "http-proxy-middleware": "3.0.5",
33
33
  "istanbul-lib-instrument": "6.0.3",
34
34
  "jsonc-parser": "3.3.1",
@@ -46,7 +46,7 @@
46
46
  "postcss-loader": "8.2.0",
47
47
  "resolve-url-loader": "5.0.0",
48
48
  "rxjs": "7.8.2",
49
- "sass": "1.92.1",
49
+ "sass": "1.93.2",
50
50
  "sass-loader": "16.0.5",
51
51
  "semver": "7.7.2",
52
52
  "source-map-loader": "5.0.0",
@@ -55,14 +55,14 @@
55
55
  "tinyglobby": "0.2.15",
56
56
  "tree-kill": "1.2.2",
57
57
  "tslib": "2.8.1",
58
- "webpack": "5.101.3",
59
- "webpack-dev-middleware": "7.4.3",
58
+ "webpack": "5.102.0",
59
+ "webpack-dev-middleware": "7.4.5",
60
60
  "webpack-dev-server": "5.2.2",
61
61
  "webpack-merge": "6.0.1",
62
62
  "webpack-subresource-integrity": "5.1.0"
63
63
  },
64
64
  "optionalDependencies": {
65
- "esbuild": "0.25.9"
65
+ "esbuild": "0.25.10"
66
66
  },
67
67
  "peerDependencies": {
68
68
  "@angular/core": "^21.0.0-next.0",
@@ -71,7 +71,7 @@
71
71
  "@angular/platform-browser": "^21.0.0-next.0",
72
72
  "@angular/platform-server": "^21.0.0-next.0",
73
73
  "@angular/service-worker": "^21.0.0-next.0",
74
- "@angular/ssr": "^21.0.0-next.4",
74
+ "@angular/ssr": "^21.0.0-next.6",
75
75
  "@web/test-runner": "^0.20.0",
76
76
  "browser-sync": "^3.0.2",
77
77
  "jest": "^29.5.0",
@@ -137,7 +137,7 @@
137
137
  "type": "git",
138
138
  "url": "https://github.com/angular/angular-cli.git"
139
139
  },
140
- "packageManager": "pnpm@10.17.0",
140
+ "packageManager": "pnpm@10.17.1",
141
141
  "engines": {
142
142
  "node": "^20.19.0 || ^22.12.0 || >=24.0.0",
143
143
  "npm": "^6.11.0 || ^7.5.6 || >=8.0.0",
@@ -59,7 +59,11 @@ async function _renderUniversal(options, context, browserResult, serverResult, s
59
59
  const browserOptions = await context.validateOptions(rawBrowserOptions, browserBuilderName);
60
60
  // Locate zone.js to load in the render worker
61
61
  const root = context.workspaceRoot;
62
- const zonePackage = require.resolve('zone.js', { paths: [root] });
62
+ let zonePackage;
63
+ try {
64
+ zonePackage = require.resolve('zone.js', { paths: [root] });
65
+ }
66
+ catch { }
63
67
  const projectName = context.target && context.target.project;
64
68
  if (!projectName) {
65
69
  throw new Error('The builder requires a target.');
@@ -101,8 +101,9 @@ function isBootstrapFn(value) {
101
101
  * @returns A promise resolving to the render function of the worker.
102
102
  */
103
103
  async function initialize() {
104
- // Setup Zone.js
105
- await Promise.resolve(`${zonePackage}`).then(s => __importStar(require(s)));
104
+ if (zonePackage) {
105
+ await Promise.resolve(`${zonePackage}`).then(s => __importStar(require(s)));
106
+ }
106
107
  // Return the render function for use
107
108
  return render;
108
109
  }
@@ -141,7 +141,7 @@ exports.default = (0, architect_1.createBuilder)(async (schema, context) => {
141
141
  // the environment for fake async to work correctly.
142
142
  // Third, we initialize `TestBed`. This is dependent on fake async being set up correctly beforehand.
143
143
  `--setupFilesAfterEnv="<rootDir>/jest-global.mjs"`,
144
- ...(options.polyfills ? [`--setupFilesAfterEnv="<rootDir>/polyfills.mjs"`] : []),
144
+ ...(options.polyfills?.length ? [`--setupFilesAfterEnv="<rootDir>/polyfills.mjs"`] : []),
145
145
  `--setupFilesAfterEnv="<rootDir>/init-test-bed.mjs"`,
146
146
  // Don't run any infrastructure files as tests, they are manually loaded where needed.
147
147
  `--testPathIgnorePatterns="<rootDir>/jest-global\\.mjs"`,
@@ -9,10 +9,16 @@
9
9
  // TODO(dgp1130): These imports likely don't resolve in stricter package environments like `pnpm`, since they are resolved relative to
10
10
  // `@angular-devkit/build-angular` rather than the user's workspace. Should look into virtual modules to support those use cases.
11
11
 
12
+ import { NgModule, provideZoneChangeDetection } from '@angular/core';
12
13
  import { getTestBed } from '@angular/core/testing';
13
14
  import { BrowserTestingModule, platformBrowserTesting } from '@angular/platform-browser/testing';
14
15
 
15
- getTestBed().initTestEnvironment(BrowserTestingModule, platformBrowserTesting(), {
16
+ @NgModule({
17
+ providers: [typeof window.Zone !== 'undefined' ? provideZoneChangeDetection() : []],
18
+ })
19
+ class TestModule {}
20
+
21
+ getTestBed().initTestEnvironment([BrowserTestingModule, TestModule], platformBrowserTesting(), {
16
22
  errorOnUnknownElements: true,
17
23
  errorOnUnknownProperties: true,
18
24
  });
@@ -129,13 +129,17 @@ async function initializeBrowser(options, context, webpackConfigurationTransform
129
129
  }, context, (wco) => [(0, configs_1.getCommonConfig)(wco), (0, configs_1.getStylesConfig)(wco)]);
130
130
  return [karma, (await webpackConfigurationTransformer?.(config)) ?? config];
131
131
  }
132
- function getBuiltInMainFile() {
132
+ function getBuiltInMainFile(includeZoneProvider = false) {
133
133
  const content = Buffer.from(`
134
+ import { provideZoneChangeDetection, ɵcompileNgModuleDefs as compileNgModuleDefs } from '@angular/core';
134
135
  import { getTestBed } from '@angular/core/testing';
135
136
  import { BrowserTestingModule, platformBrowserTesting } from '@angular/platform-browser/testing';
136
137
 
138
+ export class TestModule {}
139
+ compileNgModuleDefs(TestModule, {providers: [${includeZoneProvider ? 'provideZoneChangeDetection()' : ''}]});
140
+
137
141
  // Initialize the Angular testing environment.
138
- getTestBed().initTestEnvironment(BrowserTestingModule, platformBrowserTesting(), {
142
+ getTestBed().initTestEnvironment([BrowserTestingModule, TestModule], platformBrowserTesting(), {
139
143
  errorOnUnknownElements: true,
140
144
  errorOnUnknownProperties: true
141
145
  });
@@ -69,6 +69,11 @@ async function getRoutes(indexFile, outputPath, serverBundlePath, options, works
69
69
  routes.add(route);
70
70
  }
71
71
  }
72
+ let zonePackage;
73
+ try {
74
+ zonePackage = require.resolve('zone.js/node', { paths: [workspaceRoot] });
75
+ }
76
+ catch { }
72
77
  if (discoverRoutes) {
73
78
  const renderWorker = new piscina_1.default({
74
79
  filename: require.resolve('./routes-extractor-worker'),
@@ -77,7 +82,7 @@ async function getRoutes(indexFile, outputPath, serverBundlePath, options, works
77
82
  indexFile,
78
83
  outputPath,
79
84
  serverBundlePath,
80
- zonePackage: require.resolve('zone.js', { paths: [workspaceRoot] }),
85
+ zonePackage,
81
86
  },
82
87
  recordTiming: false,
83
88
  });
@@ -145,7 +150,11 @@ async function _renderUniversal(options, context, browserResult, serverResult, b
145
150
  // Users can specify a different base html file e.g. "src/home.html"
146
151
  const indexFile = (0, webpack_browser_config_1.getIndexOutputFile)(browserOptions.index);
147
152
  const { styles: normalizedStylesOptimization } = (0, utils_1.normalizeOptimization)(browserOptions.optimization);
148
- const zonePackage = require.resolve('zone.js', { paths: [context.workspaceRoot] });
153
+ let zonePackage;
154
+ try {
155
+ zonePackage = require.resolve('zone.js/node', { paths: [context.workspaceRoot] });
156
+ }
157
+ catch { }
149
158
  const { baseOutputPath = '' } = serverResult;
150
159
  const worker = new piscina_1.default({
151
160
  filename: path.join(__dirname, 'render-worker.js'),
@@ -126,8 +126,10 @@ function isBootstrapFn(value) {
126
126
  * @returns A promise resolving to the render function of the worker.
127
127
  */
128
128
  async function initialize() {
129
- // Setup Zone.js
130
- await Promise.resolve(`${zonePackage}`).then(s => __importStar(require(s)));
129
+ if (zonePackage) {
130
+ // Setup Zone.js
131
+ await Promise.resolve(`${zonePackage}`).then(s => __importStar(require(s)));
132
+ }
131
133
  // Return the render function for use
132
134
  return render;
133
135
  }
@@ -6,7 +6,7 @@
6
6
  * found in the LICENSE file at https://angular.dev/license
7
7
  */
8
8
  export interface RoutesExtractorWorkerData {
9
- zonePackage: string;
9
+ zonePackage: string | undefined;
10
10
  indexFile: string;
11
11
  outputPath: string;
12
12
  serverBundlePath: string;
@@ -70,8 +70,10 @@ async function extract() {
70
70
  * @returns A promise resolving to the extract function of the worker.
71
71
  */
72
72
  async function initialize() {
73
- // Setup Zone.js
74
- await Promise.resolve(`${zonePackage}`).then(s => __importStar(require(s)));
73
+ if (zonePackage) {
74
+ // Setup Zone.js
75
+ await Promise.resolve(`${zonePackage}`).then(s => __importStar(require(s)));
76
+ }
75
77
  return extract;
76
78
  }
77
79
  /**
@@ -206,22 +206,18 @@ async function checkTsConfigForPreserveWhitespacesSetting(context, tsConfigPath)
206
206
  function getPlatformServerExportsConfig(wco) {
207
207
  // Add `@angular/platform-server` exports.
208
208
  // This is needed so that DI tokens can be referenced and set at runtime outside of the bundle.
209
- // Only add `@angular/platform-server` exports when it is installed.
210
- // In some cases this builder is used when `@angular/platform-server` is not installed.
211
- // Example: when using `@nguniversal/common/clover` which does not need `@angular/platform-server`.
212
- return (0, helpers_1.isPackageInstalled)(wco.root, '@angular/platform-server')
213
- ? {
214
- module: {
215
- rules: [
216
- {
217
- loader: require.resolve('./platform-server-exports-loader'),
218
- include: [path.resolve(wco.root, wco.buildOptions.main)],
219
- options: {
220
- angularSSRInstalled: (0, helpers_1.isPackageInstalled)(wco.root, '@angular/ssr'),
221
- },
209
+ return {
210
+ module: {
211
+ rules: [
212
+ {
213
+ loader: require.resolve('./platform-server-exports-loader'),
214
+ include: [path.resolve(wco.root, wco.buildOptions.main)],
215
+ options: {
216
+ angularSSRInstalled: (0, helpers_1.isPackageInstalled)(wco.root, '@angular/ssr'),
217
+ isZoneJsInstalled: (0, helpers_1.isPackageInstalled)(wco.root, 'zone.js'),
222
218
  },
223
- ],
224
- },
225
- }
226
- : {};
219
+ },
220
+ ],
221
+ },
222
+ };
227
223
  }
@@ -12,4 +12,5 @@
12
12
  */
13
13
  export default function (this: import('webpack').LoaderContext<{
14
14
  angularSSRInstalled: boolean;
15
+ isZoneJsInstalled: boolean;
15
16
  }>, content: string, map: Parameters<import('webpack').LoaderDefinitionFunction>[1]): void;
@@ -14,7 +14,7 @@ exports.default = default_1;
14
14
  * @see https://github.com/webpack/webpack/issues/15936.
15
15
  */
16
16
  function default_1(content, map) {
17
- const { angularSSRInstalled } = this.getOptions();
17
+ const { angularSSRInstalled, isZoneJsInstalled } = this.getOptions();
18
18
  let source = `${content}
19
19
 
20
20
  // EXPORTS added by @angular-devkit/build-angular
@@ -25,6 +25,10 @@ function default_1(content, map) {
25
25
  export { ɵgetRoutesFromAngularRouterConfig } from '@angular/ssr';
26
26
  `;
27
27
  }
28
+ if (isZoneJsInstalled) {
29
+ source = `import 'zone.js/node';
30
+ ${source}`;
31
+ }
28
32
  this.callback(null, source, map);
29
33
  return;
30
34
  }
@@ -6,6 +6,7 @@
6
6
  * found in the LICENSE file at https://angular.dev/license
7
7
  */
8
8
 
9
+ import { NgModule } from '@angular/core';
9
10
  import { getTestBed } from '@angular/core/testing';
10
11
  import { BrowserTestingModule, platformBrowserTesting } from '@angular/platform-browser/testing';
11
12
  import {
@@ -63,8 +64,13 @@ export async function runJasmineTests(jasmineEnv) {
63
64
  // eslint-disable-next-line no-undef
64
65
  jasmine.DEFAULT_TIMEOUT_INTERVAL = config.defaultTimeoutInterval;
65
66
 
67
+ @NgModule({
68
+ providers: [typeof window.Zone !== 'undefined' ? provideZoneChangeDetection() : []],
69
+ })
70
+ class TestModule {}
71
+
66
72
  // Initialize `TestBed` automatically for users. This assumes we already evaluated `zone.js/testing`.
67
- getTestBed().initTestEnvironment(BrowserTestingModule, platformBrowserTesting(), {
73
+ getTestBed().initTestEnvironment([BrowserTestingModule, TestModule], platformBrowserTesting(), {
68
74
  errorOnUnknownElements: true,
69
75
  errorOnUnknownProperties: true,
70
76
  });
@@ -37,7 +37,7 @@ export interface ApplicationPresetOptions {
37
37
  inputSourceMap: unknown;
38
38
  };
39
39
  optimize?: {
40
- pureTopLevel: boolean;
40
+ topLevelSafeMode: boolean;
41
41
  wrapDecorators: boolean;
42
42
  };
43
43
  supportedBrowsers?: string[];
@@ -124,13 +124,7 @@ function default_1(api, options) {
124
124
  }
125
125
  if (options.optimize) {
126
126
  const { adjustStaticMembers, adjustTypeScriptEnums, elideAngularMetadata, markTopLevelPure, } = require('@angular/build/private');
127
- if (options.optimize.pureTopLevel) {
128
- plugins.push(markTopLevelPure);
129
- }
130
- plugins.push(elideAngularMetadata, adjustTypeScriptEnums, [
131
- adjustStaticMembers,
132
- { wrapDecorators: options.optimize.wrapDecorators },
133
- ]);
127
+ plugins.push([markTopLevelPure, { topLevelSafeMode: options.optimize.topLevelSafeMode }], elideAngularMetadata, adjustTypeScriptEnums, [adjustStaticMembers, { wrapDecorators: options.optimize.wrapDecorators }]);
134
128
  }
135
129
  if (options.instrumentCode) {
136
130
  plugins.push(require('../plugins/add-code-coverage').default);
@@ -99,7 +99,7 @@ exports.default = (0, babel_loader_1.custom)(() => {
99
99
  customOptions.optimize = {
100
100
  // Angular packages provide additional tested side effects guarantees and can use
101
101
  // otherwise unsafe optimizations. (@angular/platform-server/init) however has side-effects.
102
- pureTopLevel: AngularPackage && sideEffectFree,
102
+ topLevelSafeMode: !(AngularPackage && sideEffectFree),
103
103
  // JavaScript modules that are marked as side effect free are considered to have
104
104
  // no decorators that contain non-local effects.
105
105
  wrapDecorators: sideEffectFree,
@@ -91,7 +91,8 @@ async function getStylesConfig(wco) {
91
91
  if (postcssConfig) {
92
92
  const postCssPluginRequire = (0, node_module_1.createRequire)(path.dirname(postcssConfig.configPath) + '/');
93
93
  for (const [pluginName, pluginOptions] of postcssConfig.config.plugins) {
94
- const plugin = postCssPluginRequire(pluginName);
94
+ const pluginMod = postCssPluginRequire(pluginName);
95
+ const plugin = pluginMod.__esModule ? pluginMod['default'] : pluginMod;
95
96
  if (typeof plugin !== 'function' || plugin.postcss !== true) {
96
97
  throw new Error(`Attempted to load invalid Postcss plugin: "${pluginName}"`);
97
98
  }
@@ -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 = '21.0.0-next.4';
13
+ const VERSION = '21.0.0-next.6';
14
14
  function hasCacheMetadata(value) {
15
15
  return (!!value &&
16
16
  typeof value === 'object' &&