@angular/build 19.1.0-next.2 → 19.1.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 (58) hide show
  1. package/LICENSE +1 -1
  2. package/builders.json +5 -0
  3. package/index.d.ts +8 -0
  4. package/index.js +24 -0
  5. package/package.json +20 -16
  6. package/private/index.d.ts +8 -0
  7. package/private/index.js +24 -0
  8. package/src/builders/application/build-action.d.ts +1 -0
  9. package/src/builders/application/build-action.js +93 -11
  10. package/src/builders/application/execute-build.js +5 -2
  11. package/src/builders/application/index.d.ts +5 -12
  12. package/src/builders/application/index.js +35 -21
  13. package/src/builders/application/options.d.ts +6 -0
  14. package/src/builders/application/options.js +1 -0
  15. package/src/builders/application/results.d.ts +4 -1
  16. package/src/builders/application/setup-bundling.d.ts +2 -1
  17. package/src/builders/application/setup-bundling.js +2 -2
  18. package/src/builders/dev-server/index.d.ts +4 -2
  19. package/src/builders/dev-server/index.js +2 -1
  20. package/src/builders/dev-server/vite-server.d.ts +5 -1
  21. package/src/builders/dev-server/vite-server.js +101 -77
  22. package/src/builders/extract-i18n/index.d.ts +4 -2
  23. package/src/builders/extract-i18n/index.js +2 -1
  24. package/src/builders/ng-packagr/builder.d.ts +19 -0
  25. package/src/builders/ng-packagr/builder.js +103 -0
  26. package/src/builders/ng-packagr/index.d.ts +14 -0
  27. package/src/builders/ng-packagr/index.js +15 -0
  28. package/src/builders/ng-packagr/schema.d.ts +21 -0
  29. package/src/builders/ng-packagr/schema.js +4 -0
  30. package/src/builders/ng-packagr/schema.json +27 -0
  31. package/src/index.d.ts +2 -1
  32. package/src/index.js +3 -1
  33. package/src/private.d.ts +4 -7
  34. package/src/private.js +4 -1
  35. package/src/tools/babel/plugins/pure-toplevel-functions.js +14 -3
  36. package/src/tools/esbuild/angular/compiler-plugin.d.ts +2 -4
  37. package/src/tools/esbuild/angular/compiler-plugin.js +21 -10
  38. package/src/tools/esbuild/angular-localize-init-warning-plugin.d.ts +16 -0
  39. package/src/tools/esbuild/angular-localize-init-warning-plugin.js +49 -0
  40. package/src/tools/esbuild/application-code-bundle.d.ts +2 -1
  41. package/src/tools/esbuild/application-code-bundle.js +37 -26
  42. package/src/tools/esbuild/bundler-execution-result.d.ts +10 -3
  43. package/src/tools/esbuild/bundler-execution-result.js +13 -10
  44. package/src/tools/esbuild/compiler-plugin-options.js +0 -1
  45. package/src/tools/esbuild/javascript-transformer.js +8 -4
  46. package/src/tools/vite/middlewares/assets-middleware.d.ts +2 -2
  47. package/src/tools/vite/middlewares/assets-middleware.js +4 -4
  48. package/src/tools/vite/plugins/angular-memory-plugin.js +10 -5
  49. package/src/tools/vite/plugins/setup-middlewares-plugin.d.ts +2 -2
  50. package/src/tools/vite/utils.d.ts +5 -1
  51. package/src/tools/vite/utils.js +2 -1
  52. package/src/utils/bundle-calculator.d.ts +1 -0
  53. package/src/utils/bundle-calculator.js +5 -4
  54. package/src/utils/environment-options.js +1 -1
  55. package/src/utils/i18n-options.js +3 -3
  56. package/src/utils/normalize-cache.js +1 -1
  57. package/src/utils/server-rendering/fetch-patch.js +2 -2
  58. package/tsconfig-build.json +0 -6
package/LICENSE CHANGED
@@ -1,6 +1,6 @@
1
1
  The MIT License
2
2
 
3
- Copyright (c) 2010-2024 Google LLC. https://angular.dev/license
3
+ Copyright (c) 2010-2025 Google LLC. https://angular.dev/license
4
4
 
5
5
  Permission is hereby granted, free of charge, to any person obtaining a copy
6
6
  of this software and associated documentation files (the "Software"), to deal
package/builders.json CHANGED
@@ -14,6 +14,11 @@
14
14
  "implementation": "./src/builders/extract-i18n/index",
15
15
  "schema": "./src/builders/extract-i18n/schema.json",
16
16
  "description": "Extract i18n messages from an application."
17
+ },
18
+ "ng-packagr": {
19
+ "implementation": "./src/builders/ng-packagr/index",
20
+ "schema": "./src/builders/ng-packagr/schema.json",
21
+ "description": "Build a library with ng-packagr."
17
22
  }
18
23
  }
19
24
  }
package/index.d.ts ADDED
@@ -0,0 +1,8 @@
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.dev/license
7
+ */
8
+ export * from './src/index';
package/index.js ADDED
@@ -0,0 +1,24 @@
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.dev/license
8
+ */
9
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
10
+ if (k2 === undefined) k2 = k;
11
+ var desc = Object.getOwnPropertyDescriptor(m, k);
12
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
13
+ desc = { enumerable: true, get: function() { return m[k]; } };
14
+ }
15
+ Object.defineProperty(o, k2, desc);
16
+ }) : (function(o, m, k, k2) {
17
+ if (k2 === undefined) k2 = k;
18
+ o[k2] = m[k];
19
+ }));
20
+ var __exportStar = (this && this.__exportStar) || function(m, exports) {
21
+ for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
22
+ };
23
+ Object.defineProperty(exports, "__esModule", { value: true });
24
+ __exportStar(require("./src/index"), exports);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@angular/build",
3
- "version": "19.1.0-next.2",
3
+ "version": "19.1.0",
4
4
  "description": "Official build system for Angular",
5
5
  "keywords": [
6
6
  "Angular CLI",
@@ -23,42 +23,43 @@
23
23
  "builders": "builders.json",
24
24
  "dependencies": {
25
25
  "@ampproject/remapping": "2.3.0",
26
- "@angular-devkit/architect": "0.1901.0-next.2",
26
+ "@angular-devkit/architect": "0.1901.0",
27
27
  "@babel/core": "7.26.0",
28
28
  "@babel/helper-annotate-as-pure": "7.25.9",
29
29
  "@babel/helper-split-export-declaration": "7.24.7",
30
30
  "@babel/plugin-syntax-import-attributes": "7.26.0",
31
- "@inquirer/confirm": "5.1.0",
31
+ "@inquirer/confirm": "5.1.1",
32
32
  "@vitejs/plugin-basic-ssl": "1.2.0",
33
33
  "beasties": "0.2.0",
34
34
  "browserslist": "^4.23.0",
35
- "esbuild": "0.24.0",
36
- "fast-glob": "3.3.2",
35
+ "esbuild": "0.24.2",
36
+ "fast-glob": "3.3.3",
37
37
  "https-proxy-agent": "7.0.6",
38
38
  "istanbul-lib-instrument": "6.0.3",
39
39
  "listr2": "8.2.5",
40
- "magic-string": "0.30.15",
40
+ "magic-string": "0.30.17",
41
41
  "mrmime": "2.0.0",
42
42
  "parse5-html-rewriting-stream": "7.0.0",
43
43
  "picomatch": "4.0.2",
44
44
  "piscina": "4.8.0",
45
- "rollup": "4.28.1",
46
- "sass": "1.83.0",
45
+ "rollup": "4.30.1",
46
+ "sass": "1.83.1",
47
47
  "semver": "7.6.3",
48
- "vite": "6.0.3",
48
+ "vite": "6.0.7",
49
49
  "watchpack": "2.4.2"
50
50
  },
51
51
  "optionalDependencies": {
52
- "lmdb": "3.2.0"
52
+ "lmdb": "3.2.2"
53
53
  },
54
54
  "peerDependencies": {
55
- "@angular/compiler": "^19.0.0 || ^19.1.0-next.0",
56
- "@angular/compiler-cli": "^19.0.0 || ^19.1.0-next.0",
57
- "@angular/localize": "^19.0.0 || ^19.1.0-next.0",
58
- "@angular/platform-server": "^19.0.0 || ^19.1.0-next.0",
59
- "@angular/service-worker": "^19.0.0 || ^19.1.0-next.0",
60
- "@angular/ssr": "^19.1.0-next.2",
55
+ "@angular/compiler": "^19.0.0",
56
+ "@angular/compiler-cli": "^19.0.0",
57
+ "@angular/localize": "^19.0.0",
58
+ "@angular/platform-server": "^19.0.0",
59
+ "@angular/service-worker": "^19.0.0",
60
+ "@angular/ssr": "^19.1.0",
61
61
  "less": "^4.2.0",
62
+ "ng-packagr": "^19.0.0",
62
63
  "postcss": "^8.4.0",
63
64
  "tailwindcss": "^2.0.0 || ^3.0.0",
64
65
  "typescript": ">=5.5 <5.8"
@@ -79,6 +80,9 @@
79
80
  "less": {
80
81
  "optional": true
81
82
  },
83
+ "ng-packagr": {
84
+ "optional": true
85
+ },
82
86
  "postcss": {
83
87
  "optional": true
84
88
  },
@@ -0,0 +1,8 @@
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.dev/license
7
+ */
8
+ export * from '../src/private';
@@ -0,0 +1,24 @@
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.dev/license
8
+ */
9
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
10
+ if (k2 === undefined) k2 = k;
11
+ var desc = Object.getOwnPropertyDescriptor(m, k);
12
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
13
+ desc = { enumerable: true, get: function() { return m[k]; } };
14
+ }
15
+ Object.defineProperty(o, k2, desc);
16
+ }) : (function(o, m, k, k2) {
17
+ if (k2 === undefined) k2 = k;
18
+ o[k2] = m[k];
19
+ }));
20
+ var __exportStar = (this && this.__exportStar) || function(m, exports) {
21
+ for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
22
+ };
23
+ Object.defineProperty(exports, "__esModule", { value: true });
24
+ __exportStar(require("../src/private"), exports);
@@ -25,4 +25,5 @@ export declare function runEsBuildBuildAction(action: (rebuildState?: RebuildSta
25
25
  clearScreen?: boolean;
26
26
  colors?: boolean;
27
27
  jsonLogs?: boolean;
28
+ incrementalResults?: boolean;
28
29
  }): AsyncIterable<Result>;
@@ -65,7 +65,7 @@ const packageWatchFiles = [
65
65
  '.pnp.data.json',
66
66
  ];
67
67
  async function* runEsBuildBuildAction(action, options) {
68
- const { watch, poll, clearScreen, logger, cacheOptions, outputOptions, verbose, projectRoot, workspaceRoot, progress, preserveSymlinks, colors, jsonLogs, } = options;
68
+ const { watch, poll, clearScreen, logger, cacheOptions, outputOptions, verbose, projectRoot, workspaceRoot, progress, preserveSymlinks, colors, jsonLogs, incrementalResults, } = options;
69
69
  const withProgress = progress ? utils_1.withSpinner : utils_1.withNoProgress;
70
70
  // Initial build
71
71
  let result;
@@ -122,7 +122,7 @@ async function* runEsBuildBuildAction(action, options) {
122
122
  // Output the first build results after setting up the watcher to ensure that any code executed
123
123
  // higher in the iterator call stack will trigger the watcher. This is particularly relevant for
124
124
  // unit tests which execute the builder and modify the file system programmatically.
125
- yield await emitOutputResult(result, outputOptions);
125
+ yield* emitOutputResults(result, outputOptions);
126
126
  // Finish if watch mode is not enabled
127
127
  if (!watcher) {
128
128
  return;
@@ -143,7 +143,8 @@ async function* runEsBuildBuildAction(action, options) {
143
143
  }
144
144
  // Clear removed files from current watch files
145
145
  changes.removed.forEach((removedPath) => currentWatchFiles.delete(removedPath));
146
- result = await withProgress('Changes detected. Rebuilding...', () => action(result.createRebuildState(changes)));
146
+ const rebuildState = result.createRebuildState(changes);
147
+ result = await withProgress('Changes detected. Rebuilding...', () => action(rebuildState));
147
148
  // Log all diagnostic (error/warning/logs) messages
148
149
  await (0, utils_1.logMessages)(logger, result, colors, jsonLogs);
149
150
  // Update watched locations provided by the new build result.
@@ -163,7 +164,9 @@ async function* runEsBuildBuildAction(action, options) {
163
164
  if (staleWatchFiles?.size) {
164
165
  watcher.remove([...staleWatchFiles]);
165
166
  }
166
- yield await emitOutputResult(result, outputOptions);
167
+ for (const outputResult of emitOutputResults(result, outputOptions, changes, incrementalResults ? rebuildState : undefined)) {
168
+ yield outputResult;
169
+ }
167
170
  }
168
171
  }
169
172
  finally {
@@ -172,9 +175,9 @@ async function* runEsBuildBuildAction(action, options) {
172
175
  (0, sass_language_1.shutdownSassWorkerPool)();
173
176
  }
174
177
  }
175
- async function emitOutputResult({ outputFiles, assetFiles, errors, warnings, externalMetadata, htmlIndexPath, htmlBaseHref, templateUpdates, }, outputOptions) {
178
+ function* emitOutputResults({ outputFiles, assetFiles, errors, warnings, externalMetadata, htmlIndexPath, htmlBaseHref, templateUpdates, }, outputOptions, changes, rebuildState) {
176
179
  if (errors.length > 0) {
177
- return {
180
+ yield {
178
181
  kind: results_1.ResultKind.Failure,
179
182
  errors: errors,
180
183
  warnings: warnings,
@@ -182,19 +185,98 @@ async function emitOutputResult({ outputFiles, assetFiles, errors, warnings, ext
182
185
  outputOptions,
183
186
  },
184
187
  };
188
+ return;
185
189
  }
186
- // Template updates only exist if no other changes have occurred
187
- if (templateUpdates?.size) {
190
+ // Template updates only exist if no other JS changes have occurred
191
+ const hasTemplateUpdates = !!templateUpdates?.size;
192
+ if (hasTemplateUpdates) {
188
193
  const updateResult = {
189
194
  kind: results_1.ResultKind.ComponentUpdate,
190
- updates: Array.from(templateUpdates).map(([id, content]) => ({
195
+ updates: Array.from(templateUpdates, ([id, content]) => ({
191
196
  type: 'template',
192
197
  id,
193
198
  content,
194
199
  })),
195
200
  };
196
- return updateResult;
201
+ yield updateResult;
202
+ }
203
+ // Use an incremental result if previous output information is available
204
+ if (rebuildState && changes) {
205
+ const { previousAssetsInfo, previousOutputInfo } = rebuildState;
206
+ const incrementalResult = {
207
+ kind: results_1.ResultKind.Incremental,
208
+ warnings: warnings,
209
+ added: [],
210
+ removed: [],
211
+ modified: [],
212
+ files: {},
213
+ detail: {
214
+ externalMetadata,
215
+ htmlIndexPath,
216
+ htmlBaseHref,
217
+ outputOptions,
218
+ },
219
+ };
220
+ // Initially assume all previous output files have been removed
221
+ const removedOutputFiles = new Map(previousOutputInfo);
222
+ for (const file of outputFiles) {
223
+ removedOutputFiles.delete(file.path);
224
+ // Temporarily ignore JS files until Angular compiler plugin refactor to allow
225
+ // bypassing application code bundling for template affecting only changes.
226
+ // TODO: Remove once refactor is complete.
227
+ if (hasTemplateUpdates && /\.js(?:\.map)?$/.test(file.path)) {
228
+ continue;
229
+ }
230
+ const previousHash = previousOutputInfo.get(file.path)?.hash;
231
+ let needFile = false;
232
+ if (previousHash === undefined) {
233
+ needFile = true;
234
+ incrementalResult.added.push(file.path);
235
+ }
236
+ else if (previousHash !== file.hash) {
237
+ needFile = true;
238
+ incrementalResult.modified.push(file.path);
239
+ }
240
+ if (needFile) {
241
+ incrementalResult.files[file.path] = {
242
+ type: file.type,
243
+ contents: file.contents,
244
+ origin: 'memory',
245
+ hash: file.hash,
246
+ };
247
+ }
248
+ }
249
+ // Initially assume all previous assets files have been removed
250
+ const removedAssetFiles = new Map(previousAssetsInfo);
251
+ for (const { source, destination } of assetFiles) {
252
+ removedAssetFiles.delete(source);
253
+ if (!previousAssetsInfo.has(source)) {
254
+ incrementalResult.added.push(destination);
255
+ }
256
+ else if (changes.modified.has(source)) {
257
+ incrementalResult.modified.push(destination);
258
+ }
259
+ else {
260
+ continue;
261
+ }
262
+ incrementalResult.files[destination] = {
263
+ type: bundler_context_1.BuildOutputFileType.Browser,
264
+ inputPath: source,
265
+ origin: 'disk',
266
+ };
267
+ }
268
+ // Include the removed output and asset files
269
+ incrementalResult.removed.push(...Array.from(removedOutputFiles, ([file, { type }]) => ({
270
+ path: file,
271
+ type,
272
+ })), ...Array.from(removedAssetFiles.values(), (file) => ({
273
+ path: file,
274
+ type: bundler_context_1.BuildOutputFileType.Browser,
275
+ })));
276
+ yield incrementalResult;
277
+ return;
197
278
  }
279
+ // Otherwise, use a full result
198
280
  const result = {
199
281
  kind: results_1.ResultKind.Full,
200
282
  warnings: warnings,
@@ -221,5 +303,5 @@ async function emitOutputResult({ outputFiles, assetFiles, errors, warnings, ext
221
303
  hash: file.hash,
222
304
  };
223
305
  }
224
- return result;
306
+ yield result;
225
307
  }
@@ -41,6 +41,7 @@ var __importStar = (this && this.__importStar) || (function () {
41
41
  })();
42
42
  Object.defineProperty(exports, "__esModule", { value: true });
43
43
  exports.executeBuild = executeBuild;
44
+ const compilation_1 = require("../../tools/angular/compilation");
44
45
  const source_file_cache_1 = require("../../tools/esbuild/angular/source-file-cache");
45
46
  const budget_stats_1 = require("../../tools/esbuild/budget-stats");
46
47
  const bundler_context_1 = require("../../tools/esbuild/bundler-context");
@@ -102,7 +103,9 @@ async function executeBuild(options, context, rebuildState) {
102
103
  if (options.templateUpdates) {
103
104
  templateUpdates = new Map();
104
105
  }
105
- bundlerContexts = (0, setup_bundling_1.setupBundlerContexts)(options, target, codeBundleCache, componentStyleBundler, templateUpdates);
106
+ bundlerContexts = (0, setup_bundling_1.setupBundlerContexts)(options, target, codeBundleCache, componentStyleBundler,
107
+ // Create new reusable compilation for the appropriate mode based on the `jit` plugin option
108
+ await (0, compilation_1.createAngularCompilation)(!!options.jit, !options.serverEntryPoint), templateUpdates);
106
109
  // Bundle everything on initial build
107
110
  bundlingResult = await bundler_context_1.BundlerContext.bundleAll([
108
111
  ...bundlerContexts.typescriptContexts,
@@ -145,7 +148,7 @@ async function executeBuild(options, context, rebuildState) {
145
148
  }
146
149
  const { metafile, initialFiles, outputFiles } = bundlingResult;
147
150
  executionResult.outputFiles.push(...outputFiles);
148
- const changedFiles = rebuildState && executionResult.findChangedFiles(rebuildState.previousOutputHashes);
151
+ const changedFiles = rebuildState && executionResult.findChangedFiles(rebuildState.previousOutputInfo);
149
152
  // Analyze files for bundle budget failures if present
150
153
  let budgetFailures;
151
154
  if (options.budgets) {
@@ -5,8 +5,8 @@
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.dev/license
7
7
  */
8
- import { BuilderContext, BuilderOutput } from '@angular-devkit/architect';
9
- import { BuildOutputFile } from '../../tools/esbuild/bundler-context';
8
+ import { Builder, BuilderContext, BuilderOutput } from '@angular-devkit/architect';
9
+ import { json } from '@angular-devkit/core';
10
10
  import { ApplicationBuilderExtensions, ApplicationBuilderInternalOptions } from './options';
11
11
  import { Result } from './results';
12
12
  import { Schema as ApplicationBuilderOptions } from './schema';
@@ -14,13 +14,6 @@ export type { ApplicationBuilderOptions };
14
14
  export declare function buildApplicationInternal(options: ApplicationBuilderInternalOptions, context: BuilderContext & {
15
15
  signal?: AbortSignal;
16
16
  }, extensions?: ApplicationBuilderExtensions): AsyncIterable<Result>;
17
- export interface ApplicationBuilderOutput extends BuilderOutput {
18
- outputFiles?: BuildOutputFile[];
19
- assetFiles?: {
20
- source: string;
21
- destination: string;
22
- }[];
23
- }
24
17
  /**
25
18
  * Builds an application using the `application` builder with the provided
26
19
  * options.
@@ -35,6 +28,6 @@ export interface ApplicationBuilderOutput extends BuilderOutput {
35
28
  * @param extensions An object contain extension points for the build.
36
29
  * @returns The build output results of the build.
37
30
  */
38
- export declare function buildApplication(options: ApplicationBuilderOptions, context: BuilderContext, extensions?: ApplicationBuilderExtensions): AsyncIterable<ApplicationBuilderOutput>;
39
- declare const _default: import("../../../../../angular_devkit/architect/src/internal").Builder<ApplicationBuilderOptions & import("../../../../../angular_devkit/core/src").JsonObject>;
40
- export default _default;
31
+ export declare function buildApplication(options: ApplicationBuilderOptions, context: BuilderContext, extensions?: ApplicationBuilderExtensions): AsyncIterable<BuilderOutput>;
32
+ declare const builder: Builder<ApplicationBuilderOptions & json.JsonObject>;
33
+ export default builder;
@@ -96,6 +96,7 @@ context, extensions) {
96
96
  clearScreen: normalizedOptions.clearScreen,
97
97
  colors: normalizedOptions.colors,
98
98
  jsonLogs: normalizedOptions.jsonLogs,
99
+ incrementalResults: normalizedOptions.incrementalResults,
99
100
  logger,
100
101
  signal,
101
102
  });
@@ -116,7 +117,8 @@ context, extensions) {
116
117
  */
117
118
  async function* buildApplication(options, context, extensions) {
118
119
  let initial = true;
119
- for await (const result of buildApplicationInternal(options, context, extensions)) {
120
+ const internalOptions = { ...options, incrementalResults: true };
121
+ for await (const result of buildApplicationInternal(internalOptions, context, extensions)) {
120
122
  const outputOptions = result.detail?.['outputOptions'];
121
123
  if (initial) {
122
124
  initial = false;
@@ -134,7 +136,7 @@ async function* buildApplication(options, context, extensions) {
134
136
  continue;
135
137
  }
136
138
  (0, node_assert_1.default)(outputOptions, 'Application output options are required for builder usage.');
137
- (0, node_assert_1.default)(result.kind === results_1.ResultKind.Full, 'Application build did not provide a full output.');
139
+ (0, node_assert_1.default)(result.kind === results_1.ResultKind.Full || result.kind === results_1.ResultKind.Incremental, 'Application build did not provide a file result output.');
138
140
  // TODO: Restructure output logging to better handle stdout JSON piping
139
141
  if (!environment_options_1.useJSONBuildLogs) {
140
142
  context.logger.info(`Output location: ${outputOptions.base}\n`);
@@ -147,24 +149,7 @@ async function* buildApplication(options, context, extensions) {
147
149
  file.type === bundler_context_1.BuildOutputFileType.ServerRoot)) {
148
150
  return;
149
151
  }
150
- let typeDirectory;
151
- switch (file.type) {
152
- case bundler_context_1.BuildOutputFileType.Browser:
153
- case bundler_context_1.BuildOutputFileType.Media:
154
- typeDirectory = outputOptions.browser;
155
- break;
156
- case bundler_context_1.BuildOutputFileType.ServerApplication:
157
- case bundler_context_1.BuildOutputFileType.ServerRoot:
158
- typeDirectory = outputOptions.server;
159
- break;
160
- case bundler_context_1.BuildOutputFileType.Root:
161
- typeDirectory = '';
162
- break;
163
- default:
164
- throw new Error(`Unhandled write for file "${filePath}" with type "${bundler_context_1.BuildOutputFileType[file.type]}".`);
165
- }
166
- // NOTE: 'base' is a fully resolved path at this point
167
- const fullFilePath = node_path_1.default.join(outputOptions.base, typeDirectory, filePath);
152
+ const fullFilePath = generateFullPath(filePath, file.type, outputOptions);
168
153
  // Ensure output subdirectories exist
169
154
  const fileBasePath = node_path_1.default.dirname(fullFilePath);
170
155
  if (fileBasePath && !directoryExists.has(fileBasePath)) {
@@ -180,7 +165,36 @@ async function* buildApplication(options, context, extensions) {
180
165
  await promises_1.default.copyFile(file.inputPath, fullFilePath, promises_1.default.constants.COPYFILE_FICLONE);
181
166
  }
182
167
  });
168
+ // Delete any removed files if incremental
169
+ if (result.kind === results_1.ResultKind.Incremental && result.removed?.length) {
170
+ await Promise.all(result.removed.map((file) => {
171
+ const fullFilePath = generateFullPath(file.path, file.type, outputOptions);
172
+ return promises_1.default.rm(fullFilePath, { force: true, maxRetries: 3 });
173
+ }));
174
+ }
183
175
  yield { success: true };
184
176
  }
185
177
  }
186
- exports.default = (0, architect_1.createBuilder)(buildApplication);
178
+ function generateFullPath(filePath, type, outputOptions) {
179
+ let typeDirectory;
180
+ switch (type) {
181
+ case bundler_context_1.BuildOutputFileType.Browser:
182
+ case bundler_context_1.BuildOutputFileType.Media:
183
+ typeDirectory = outputOptions.browser;
184
+ break;
185
+ case bundler_context_1.BuildOutputFileType.ServerApplication:
186
+ case bundler_context_1.BuildOutputFileType.ServerRoot:
187
+ typeDirectory = outputOptions.server;
188
+ break;
189
+ case bundler_context_1.BuildOutputFileType.Root:
190
+ typeDirectory = '';
191
+ break;
192
+ default:
193
+ throw new Error(`Unhandled write for file "${filePath}" with type "${bundler_context_1.BuildOutputFileType[type]}".`);
194
+ }
195
+ // NOTE: 'base' is a fully resolved path at this point
196
+ const fullFilePath = node_path_1.default.join(outputOptions.base, typeDirectory, filePath);
197
+ return fullFilePath;
198
+ }
199
+ const builder = (0, architect_1.createBuilder)(buildApplication);
200
+ exports.default = builder;
@@ -74,6 +74,11 @@ interface InternalOptions {
74
74
  * template updates.
75
75
  */
76
76
  templateUpdates?: boolean;
77
+ /**
78
+ * Enables emitting incremental build results when in watch mode. A full build result will only be emitted
79
+ * for the initial build. This option also requires watch to be enabled to have an effect.
80
+ */
81
+ incrementalResults?: boolean;
77
82
  /**
78
83
  * Enables instrumentation to collect code coverage data for specific files.
79
84
  *
@@ -193,6 +198,7 @@ export declare function normalizeOptions(context: BuilderContext, projectName: s
193
198
  instrumentForCoverage: ((filename: string) => boolean) | undefined;
194
199
  security: import("./schema").Security | undefined;
195
200
  templateUpdates: boolean;
201
+ incrementalResults: boolean;
196
202
  }>;
197
203
  export declare function getLocaleBaseHref(baseHref: string | undefined, i18n: NormalizedApplicationBuildOptions['i18nOptions'], locale: string): string | undefined;
198
204
  export {};
@@ -298,6 +298,7 @@ async function normalizeOptions(context, projectName, options, extensions) {
298
298
  instrumentForCoverage,
299
299
  security,
300
300
  templateUpdates: !!options.templateUpdates,
301
+ incrementalResults: !!options.incrementalResults,
301
302
  };
302
303
  }
303
304
  async function getTailwindConfig(searchDirectories, workspaceRoot, context) {
@@ -30,7 +30,10 @@ export interface FullResult extends BaseResult {
30
30
  export interface IncrementalResult extends BaseResult {
31
31
  kind: ResultKind.Incremental;
32
32
  added: string[];
33
- removed: string[];
33
+ removed: {
34
+ path: string;
35
+ type: BuildOutputFileType;
36
+ }[];
34
37
  modified: string[];
35
38
  files: Record<string, ResultFile>;
36
39
  }
@@ -5,6 +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.dev/license
7
7
  */
8
+ import { AngularCompilation } from '../../tools/angular/compilation';
8
9
  import { ComponentStylesheetBundler } from '../../tools/esbuild/angular/component-stylesheets';
9
10
  import { SourceFileCache } from '../../tools/esbuild/angular/source-file-cache';
10
11
  import { BundlerContext } from '../../tools/esbuild/bundler-context';
@@ -17,7 +18,7 @@ import { NormalizedApplicationBuildOptions } from './options';
17
18
  * @param codeBundleCache An instance of the TypeScript source file cache.
18
19
  * @returns An array of BundlerContext objects.
19
20
  */
20
- export declare function setupBundlerContexts(options: NormalizedApplicationBuildOptions, target: string[], codeBundleCache: SourceFileCache, stylesheetBundler: ComponentStylesheetBundler, templateUpdates: Map<string, string> | undefined): {
21
+ export declare function setupBundlerContexts(options: NormalizedApplicationBuildOptions, target: string[], codeBundleCache: SourceFileCache, stylesheetBundler: ComponentStylesheetBundler, angularCompilation: AngularCompilation, templateUpdates: Map<string, string> | undefined): {
21
22
  typescriptContexts: BundlerContext[];
22
23
  otherContexts: BundlerContext[];
23
24
  };
@@ -23,12 +23,12 @@ const utils_1 = require("../../tools/esbuild/utils");
23
23
  * @param codeBundleCache An instance of the TypeScript source file cache.
24
24
  * @returns An array of BundlerContext objects.
25
25
  */
26
- function setupBundlerContexts(options, target, codeBundleCache, stylesheetBundler, templateUpdates) {
26
+ function setupBundlerContexts(options, target, codeBundleCache, stylesheetBundler, angularCompilation, templateUpdates) {
27
27
  const { outputMode, serverEntryPoint, appShellOptions, prerenderOptions, ssrOptions, workspaceRoot, watch = false, } = options;
28
28
  const typescriptContexts = [];
29
29
  const otherContexts = [];
30
30
  // Browser application code
31
- typescriptContexts.push(new bundler_context_1.BundlerContext(workspaceRoot, watch, (0, application_code_bundle_1.createBrowserCodeBundleOptions)(options, target, codeBundleCache, stylesheetBundler, templateUpdates)));
31
+ typescriptContexts.push(new bundler_context_1.BundlerContext(workspaceRoot, watch, (0, application_code_bundle_1.createBrowserCodeBundleOptions)(options, target, codeBundleCache, stylesheetBundler, angularCompilation, templateUpdates)));
32
32
  // Browser polyfills code
33
33
  const browserPolyfillBundleOptions = (0, application_code_bundle_1.createBrowserPolyfillBundleOptions)(options, target, codeBundleCache, stylesheetBundler);
34
34
  if (browserPolyfillBundleOptions) {
@@ -5,10 +5,12 @@
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.dev/license
7
7
  */
8
+ import { Builder } from '@angular-devkit/architect';
9
+ import { json } from '@angular-devkit/core';
8
10
  import { execute } from './builder';
9
11
  import type { DevServerBuilderOutput } from './output';
10
12
  import type { Schema as DevServerBuilderOptions } from './schema';
11
13
  export { type DevServerBuilderOptions, type DevServerBuilderOutput, execute as executeDevServerBuilder, };
12
- declare const _default: import("../../../../../angular_devkit/architect/src/internal").Builder<DevServerBuilderOptions & import("../../../../../angular_devkit/core/src").JsonObject>;
13
- export default _default;
14
+ declare const builder: Builder<DevServerBuilderOptions & json.JsonObject>;
15
+ export default builder;
14
16
  export { execute as executeDevServer };
@@ -12,4 +12,5 @@ const architect_1 = require("@angular-devkit/architect");
12
12
  const builder_1 = require("./builder");
13
13
  Object.defineProperty(exports, "executeDevServerBuilder", { enumerable: true, get: function () { return builder_1.execute; } });
14
14
  Object.defineProperty(exports, "executeDevServer", { enumerable: true, get: function () { return builder_1.execute; } });
15
- exports.default = (0, architect_1.createBuilder)(builder_1.execute);
15
+ const builder = (0, architect_1.createBuilder)(builder_1.execute);
16
+ exports.default = builder;
@@ -23,6 +23,10 @@ interface OutputFileRecord {
23
23
  servable: boolean;
24
24
  type: BuildOutputFileType;
25
25
  }
26
+ interface OutputAssetRecord {
27
+ source: string;
28
+ updated: boolean;
29
+ }
26
30
  interface DevServerExternalResultMetadata extends Omit<ExternalResultMetadata, 'explicit'> {
27
31
  explicitBrowser: string[];
28
32
  explicitServer: string[];
@@ -34,5 +38,5 @@ export declare function serveWithVite(serverOptions: NormalizedDevServerOptions,
34
38
  middleware?: Connect.NextHandleFunction[];
35
39
  buildPlugins?: Plugin[];
36
40
  }): AsyncIterableIterator<DevServerBuilderOutput>;
37
- export declare function setupServer(serverOptions: NormalizedDevServerOptions, outputFiles: Map<string, OutputFileRecord>, assets: Map<string, string>, preserveSymlinks: boolean | undefined, externalMetadata: DevServerExternalResultMetadata, ssrMode: ServerSsrMode, prebundleTransformer: JavaScriptTransformer, target: string[], zoneless: boolean, componentStyles: Map<string, ComponentStyleRecord>, templateUpdates: Map<string, string>, prebundleLoaderExtensions: EsbuildLoaderOption | undefined, extensionMiddleware?: Connect.NextHandleFunction[], indexHtmlTransformer?: (content: string) => Promise<string>, thirdPartySourcemaps?: boolean): Promise<InlineConfig>;
41
+ export declare function setupServer(serverOptions: NormalizedDevServerOptions, outputFiles: Map<string, OutputFileRecord>, assets: Map<string, OutputAssetRecord>, preserveSymlinks: boolean | undefined, externalMetadata: DevServerExternalResultMetadata, ssrMode: ServerSsrMode, prebundleTransformer: JavaScriptTransformer, target: string[], zoneless: boolean, componentStyles: Map<string, ComponentStyleRecord>, templateUpdates: Map<string, string>, prebundleLoaderExtensions: EsbuildLoaderOption | undefined, define: ApplicationBuilderInternalOptions['define'], extensionMiddleware?: Connect.NextHandleFunction[], indexHtmlTransformer?: (content: string) => Promise<string>, thirdPartySourcemaps?: boolean): Promise<InlineConfig>;
38
42
  export {};