@angular/build 19.0.0 → 19.0.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": "19.0.0",
3
+ "version": "19.0.2",
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.1900.0",
26
+ "@angular-devkit/architect": "0.1900.2",
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",
@@ -57,7 +57,7 @@
57
57
  "@angular/localize": "^19.0.0",
58
58
  "@angular/platform-server": "^19.0.0",
59
59
  "@angular/service-worker": "^19.0.0",
60
- "@angular/ssr": "^19.0.0",
60
+ "@angular/ssr": "^19.0.2",
61
61
  "less": "^4.2.0",
62
62
  "postcss": "^8.4.0",
63
63
  "tailwindcss": "^2.0.0 || ^3.0.0",
package/src/private.d.ts CHANGED
@@ -11,6 +11,8 @@
11
11
  * All exports are not supported for external use, do not provide SemVer guarantees, and
12
12
  * their existence may change in any future version.
13
13
  */
14
+ import { CompilerPluginOptions } from './tools/esbuild/angular/compiler-plugin';
15
+ import { BundleStylesheetOptions } from './tools/esbuild/stylesheets/bundle-options';
14
16
  export { buildApplicationInternal } from './builders/application';
15
17
  export type { ApplicationBuilderInternalOptions } from './builders/application/options';
16
18
  export { type Result, type ResultFile, ResultKind } from './builders/application/results';
@@ -23,7 +25,9 @@ export { SassWorkerImplementation } from './tools/sass/sass-service';
23
25
  export { SourceFileCache } from './tools/esbuild/angular/source-file-cache';
24
26
  export { createJitResourceTransformer } from './tools/angular/transformers/jit-resource-transformer';
25
27
  export { JavaScriptTransformer } from './tools/esbuild/javascript-transformer';
26
- export { createCompilerPlugin } from './tools/esbuild/angular/compiler-plugin';
28
+ export declare function createCompilerPlugin(pluginOptions: CompilerPluginOptions, styleOptions: BundleStylesheetOptions & {
29
+ inlineStyleLanguage: string;
30
+ }): import('esbuild').Plugin;
27
31
  export * from './utils/bundle-calculator';
28
32
  export { checkPort } from './utils/check-port';
29
33
  export { deleteOutputDir } from './utils/delete-output-dir';
package/src/private.js CHANGED
@@ -21,13 +21,16 @@ var __exportStar = (this && this.__exportStar) || function(m, exports) {
21
21
  for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
22
22
  };
23
23
  Object.defineProperty(exports, "__esModule", { value: true });
24
- exports.assertCompatibleAngularVersion = exports.getSupportedBrowsers = exports.generateBuildStatsTable = exports.augmentAppWithServiceWorker = exports.purgeStaleBuildCache = exports.createTranslationLoader = exports.loadProxyConfiguration = exports.InlineCriticalCssProcessor = exports.IndexHtmlGenerator = exports.loadTranslations = exports.createI18nOptions = exports.deleteOutputDir = exports.checkPort = exports.createCompilerPlugin = exports.JavaScriptTransformer = exports.createJitResourceTransformer = exports.SourceFileCache = exports.SassWorkerImplementation = exports.transformSupportedBrowsersToTargets = exports.emitFilesToDisk = exports.serveWithVite = exports.ResultKind = exports.buildApplicationInternal = void 0;
24
+ exports.assertCompatibleAngularVersion = exports.getSupportedBrowsers = exports.generateBuildStatsTable = exports.augmentAppWithServiceWorker = exports.purgeStaleBuildCache = exports.createTranslationLoader = exports.loadProxyConfiguration = exports.InlineCriticalCssProcessor = exports.IndexHtmlGenerator = exports.loadTranslations = exports.createI18nOptions = exports.deleteOutputDir = exports.checkPort = exports.JavaScriptTransformer = exports.createJitResourceTransformer = exports.SourceFileCache = exports.SassWorkerImplementation = exports.transformSupportedBrowsersToTargets = exports.emitFilesToDisk = exports.serveWithVite = exports.ResultKind = exports.buildApplicationInternal = void 0;
25
+ exports.createCompilerPlugin = createCompilerPlugin;
25
26
  /**
26
27
  * @fileoverview
27
28
  * Private exports intended only for use with the @angular-devkit/build-angular package.
28
29
  * All exports are not supported for external use, do not provide SemVer guarantees, and
29
30
  * their existence may change in any future version.
30
31
  */
32
+ const compiler_plugin_1 = require("./tools/esbuild/angular/compiler-plugin");
33
+ const component_stylesheets_1 = require("./tools/esbuild/angular/component-stylesheets");
31
34
  // Builders
32
35
  var application_1 = require("./builders/application");
33
36
  Object.defineProperty(exports, "buildApplicationInternal", { enumerable: true, get: function () { return application_1.buildApplicationInternal; } });
@@ -49,8 +52,9 @@ var jit_resource_transformer_1 = require("./tools/angular/transformers/jit-resou
49
52
  Object.defineProperty(exports, "createJitResourceTransformer", { enumerable: true, get: function () { return jit_resource_transformer_1.createJitResourceTransformer; } });
50
53
  var javascript_transformer_1 = require("./tools/esbuild/javascript-transformer");
51
54
  Object.defineProperty(exports, "JavaScriptTransformer", { enumerable: true, get: function () { return javascript_transformer_1.JavaScriptTransformer; } });
52
- var compiler_plugin_1 = require("./tools/esbuild/angular/compiler-plugin");
53
- Object.defineProperty(exports, "createCompilerPlugin", { enumerable: true, get: function () { return compiler_plugin_1.createCompilerPlugin; } });
55
+ function createCompilerPlugin(pluginOptions, styleOptions) {
56
+ return (0, compiler_plugin_1.createCompilerPlugin)(pluginOptions, new component_stylesheets_1.ComponentStylesheetBundler(styleOptions, styleOptions.inlineStyleLanguage, pluginOptions.incremental));
57
+ }
54
58
  // Utilities
55
59
  __exportStar(require("./utils/bundle-calculator"), exports);
56
60
  var check_port_1 = require("./utils/check-port");
@@ -51,6 +51,17 @@ class AotCompilation extends angular_compilation_1.AngularCompilation {
51
51
  if (compilerOptions.externalRuntimeStyles) {
52
52
  hostOptions.externalStylesheets ??= new Map();
53
53
  }
54
+ // Collect stale source files for HMR analysis of inline component resources
55
+ let staleSourceFiles;
56
+ if (compilerOptions['_enableHmr'] && hostOptions.modifiedFiles && this.#state) {
57
+ for (const modifiedFile of hostOptions.modifiedFiles) {
58
+ const sourceFile = this.#state.typeScriptProgram.getSourceFile(modifiedFile);
59
+ if (sourceFile) {
60
+ staleSourceFiles ??= new Map();
61
+ staleSourceFiles.set(modifiedFile, sourceFile);
62
+ }
63
+ }
64
+ }
54
65
  // Create Angular compiler host
55
66
  const host = (0, angular_host_1.createAngularCompilerHost)(typescript_1.default, compilerOptions, hostOptions);
56
67
  // Create the Angular specific program that contains the Angular compiler
@@ -67,12 +78,8 @@ class AotCompilation extends angular_compilation_1.AngularCompilation {
67
78
  const typeScriptProgram = typescript_1.default.createEmitAndSemanticDiagnosticsBuilderProgram(angularTypeScriptProgram, host, oldProgram, configurationDiagnostics);
68
79
  await (0, profiling_1.profileAsync)('NG_ANALYZE_PROGRAM', () => angularCompiler.analyzeAsync());
69
80
  let templateUpdates;
70
- if (compilerOptions['_enableHmr'] &&
71
- hostOptions.modifiedFiles &&
72
- hasOnlyTemplates(hostOptions.modifiedFiles)) {
73
- const componentNodes = [...hostOptions.modifiedFiles].flatMap((file) => [
74
- ...angularCompiler.getComponentsWithTemplateFile(file),
75
- ]);
81
+ if (compilerOptions['_enableHmr'] && hostOptions.modifiedFiles && this.#state) {
82
+ const componentNodes = collectHmrCandidates(hostOptions.modifiedFiles, angularProgram, staleSourceFiles);
76
83
  for (const node of componentNodes) {
77
84
  if (!typescript_1.default.isClassDeclaration(node)) {
78
85
  continue;
@@ -296,13 +303,35 @@ function findAffectedFiles(builder, { ignoreForDiagnostics }, includeTTC) {
296
303
  }
297
304
  return affectedFiles;
298
305
  }
299
- function hasOnlyTemplates(modifiedFiles) {
306
+ function collectHmrCandidates(modifiedFiles, { compiler }, staleSourceFiles) {
307
+ const candidates = new Set();
300
308
  for (const file of modifiedFiles) {
301
- const lowerFile = file.toLowerCase();
302
- if (lowerFile.endsWith('.html') || lowerFile.endsWith('.svg')) {
309
+ const templateFileNodes = compiler.getComponentsWithTemplateFile(file);
310
+ if (templateFileNodes.size) {
311
+ templateFileNodes.forEach((node) => candidates.add(node));
312
+ continue;
313
+ }
314
+ const styleFileNodes = compiler.getComponentsWithStyleFile(file);
315
+ if (styleFileNodes.size) {
316
+ styleFileNodes.forEach((node) => candidates.add(node));
303
317
  continue;
304
318
  }
305
- return false;
319
+ const staleSource = staleSourceFiles?.get(file);
320
+ if (staleSource === undefined) {
321
+ // Unknown file requires a rebuild so clear out the candidates and stop collecting
322
+ candidates.clear();
323
+ break;
324
+ }
325
+ const updatedSource = compiler.getCurrentProgram().getSourceFile(file);
326
+ if (updatedSource === undefined) {
327
+ // No longer existing program file requires a rebuild so clear out the candidates and stop collecting
328
+ candidates.clear();
329
+ break;
330
+ }
331
+ // Compare the stale and updated file for changes
332
+ // TODO: Implement -- for now assume a rebuild is needed
333
+ candidates.clear();
334
+ break;
306
335
  }
307
- return true;
336
+ return candidates;
308
337
  }
@@ -157,7 +157,7 @@ function createCompilerPlugin(pluginOptions, stylesheetBundler) {
157
157
  // invalid the output and force a full page reload for HMR cases. The containing file and order
158
158
  // of the style within the containing file is used.
159
159
  pluginOptions.externalRuntimeStyles
160
- ? (0, node_crypto_1.createHash)('sha-256')
160
+ ? (0, node_crypto_1.createHash)('sha256')
161
161
  .update(containingFile)
162
162
  .update((order ?? 0).toString())
163
163
  .update(className ?? '')
@@ -171,7 +171,6 @@ function createServerMainCodeBundleOptions(options, target, sourceFileCache, sty
171
171
  return (loadResultCache) => {
172
172
  const pluginOptions = (0, compiler_plugin_options_1.createCompilerPluginOptions)(options, sourceFileCache, loadResultCache);
173
173
  const mainServerNamespace = 'angular:main-server';
174
- const mainServerInjectPolyfillsNamespace = 'angular:main-server-inject-polyfills';
175
174
  const mainServerInjectManifestNamespace = 'angular:main-server-inject-manifest';
176
175
  const zoneless = (0, utils_1.isZonelessApp)(polyfills);
177
176
  const entryPoints = {
@@ -187,7 +186,9 @@ function createServerMainCodeBundleOptions(options, target, sourceFileCache, sty
187
186
  const buildOptions = {
188
187
  ...getEsBuildServerCommonOptions(options),
189
188
  target,
190
- inject: [mainServerInjectPolyfillsNamespace, mainServerInjectManifestNamespace],
189
+ banner: {
190
+ js: `import './polyfills.server.mjs';`,
191
+ },
191
192
  entryPoints,
192
193
  supported: (0, utils_1.getFeatureSupport)(target, zoneless),
193
194
  plugins: [
@@ -217,16 +218,9 @@ function createServerMainCodeBundleOptions(options, target, sourceFileCache, sty
217
218
  buildOptions.external.push('xhr2');
218
219
  }
219
220
  buildOptions.plugins.push((0, server_bundle_metadata_plugin_1.createServerBundleMetadata)(), (0, virtual_module_plugin_1.createVirtualModulePlugin)({
220
- namespace: mainServerInjectPolyfillsNamespace,
221
- cache: loadResultCache,
222
- loadContent: () => ({
223
- contents: `import './polyfills.server.mjs';`,
224
- loader: 'js',
225
- resolveDir: workspaceRoot,
226
- }),
227
- }), (0, virtual_module_plugin_1.createVirtualModulePlugin)({
228
221
  namespace: mainServerInjectManifestNamespace,
229
222
  cache: loadResultCache,
223
+ entryPointOnly: false,
230
224
  loadContent: async () => {
231
225
  const contents = [
232
226
  // Configure `@angular/ssr` manifest.
@@ -246,15 +240,17 @@ function createServerMainCodeBundleOptions(options, target, sourceFileCache, sty
246
240
  loadContent: async () => {
247
241
  const mainServerEntryPointJsImport = entryFileToWorkspaceRelative(workspaceRoot, mainServerEntryPoint);
248
242
  const contents = [
243
+ // Inject manifest
244
+ `import '${mainServerInjectManifestNamespace}';`,
245
+ // Add @angular/ssr exports
246
+ `export {
247
+ ɵdestroyAngularServerApp,
248
+ ɵextractRoutesAndCreateRouteTree,
249
+ ɵgetOrCreateAngularServerApp,
250
+ } from '@angular/ssr';`,
249
251
  // Re-export all symbols including default export from 'main.server.ts'
250
252
  `export { default } from '${mainServerEntryPointJsImport}';`,
251
253
  `export * from '${mainServerEntryPointJsImport}';`,
252
- // Add @angular/ssr exports
253
- `export {
254
- ɵdestroyAngularServerApp,
255
- ɵextractRoutesAndCreateRouteTree,
256
- ɵgetOrCreateAngularServerApp,
257
- } from '@angular/ssr';`,
258
254
  ];
259
255
  return {
260
256
  contents: contents.join('\n'),
@@ -277,17 +273,21 @@ function createSsrEntryCodeBundleOptions(options, target, sourceFileCache, style
277
273
  const pluginOptions = (0, compiler_plugin_options_1.createCompilerPluginOptions)(options, sourceFileCache, loadResultCache);
278
274
  const ssrEntryNamespace = 'angular:ssr-entry';
279
275
  const ssrInjectManifestNamespace = 'angular:ssr-entry-inject-manifest';
280
- const ssrInjectRequireNamespace = 'angular:ssr-entry-inject-require';
281
276
  const isNodePlatform = options.ssrOptions?.platform !== schema_1.ExperimentalPlatform.Neutral;
282
- const inject = [ssrInjectManifestNamespace];
283
- if (isNodePlatform) {
284
- inject.unshift(ssrInjectRequireNamespace);
285
- }
286
277
  const buildOptions = {
287
278
  ...getEsBuildServerCommonOptions(options),
288
279
  target,
280
+ banner: isNodePlatform
281
+ ? {
282
+ js: [
283
+ // Note: Needed as esbuild does not provide require shims / proxy from ESModules.
284
+ // See: https://github.com/evanw/esbuild/issues/1921.
285
+ `import { createRequire } from 'node:module';`,
286
+ `globalThis['require'] ??= createRequire(import.meta.url);`,
287
+ ].join('\n'),
288
+ }
289
+ : undefined,
289
290
  entryPoints: {
290
- // TODO: consider renaming to index
291
291
  'server': ssrEntryNamespace,
292
292
  },
293
293
  supported: (0, utils_1.getFeatureSupport)(target, true),
@@ -299,7 +299,6 @@ function createSsrEntryCodeBundleOptions(options, target, sourceFileCache, style
299
299
  // Component stylesheet bundler
300
300
  stylesheetBundler),
301
301
  ],
302
- inject,
303
302
  };
304
303
  buildOptions.plugins ??= [];
305
304
  if (externalPackages) {
@@ -317,24 +316,9 @@ function createSsrEntryCodeBundleOptions(options, target, sourceFileCache, style
317
316
  buildOptions.external.push('xhr2');
318
317
  }
319
318
  buildOptions.plugins.push((0, server_bundle_metadata_plugin_1.createServerBundleMetadata)({ ssrEntryBundle: true }), (0, virtual_module_plugin_1.createVirtualModulePlugin)({
320
- namespace: ssrInjectRequireNamespace,
321
- cache: loadResultCache,
322
- loadContent: () => {
323
- const contents = [
324
- // Note: Needed as esbuild does not provide require shims / proxy from ESModules.
325
- // See: https://github.com/evanw/esbuild/issues/1921.
326
- `import { createRequire } from 'node:module';`,
327
- `globalThis['require'] ??= createRequire(import.meta.url);`,
328
- ];
329
- return {
330
- contents: contents.join('\n'),
331
- loader: 'js',
332
- resolveDir: workspaceRoot,
333
- };
334
- },
335
- }), (0, virtual_module_plugin_1.createVirtualModulePlugin)({
336
319
  namespace: ssrInjectManifestNamespace,
337
320
  cache: loadResultCache,
321
+ entryPointOnly: false,
338
322
  loadContent: () => {
339
323
  const contents = [
340
324
  // Configure `@angular/ssr` app engine manifest.
@@ -354,6 +338,8 @@ function createSsrEntryCodeBundleOptions(options, target, sourceFileCache, style
354
338
  loadContent: () => {
355
339
  const serverEntryPointJsImport = entryFileToWorkspaceRelative(workspaceRoot, serverEntryPoint);
356
340
  const contents = [
341
+ // Configure `@angular/ssr` app engine manifest.
342
+ `import '${ssrInjectManifestNamespace}';`,
357
343
  // Re-export all symbols including default export
358
344
  `import * as server from '${serverEntryPointJsImport}';`,
359
345
  `export * from '${serverEntryPointJsImport}';`,
@@ -185,7 +185,7 @@ function generateInitHelper(streaming, wasmContents) {
185
185
  let resultContents;
186
186
  if (streaming) {
187
187
  const fetchOptions = {
188
- integrity: 'sha256-' + (0, node_crypto_1.createHash)('sha-256').update(wasmContents).digest('base64'),
188
+ integrity: 'sha256-' + (0, node_crypto_1.createHash)('sha256').update(wasmContents).digest('base64'),
189
189
  };
190
190
  const fetchContents = `fetch(new URL(wasmPath, import.meta.url), ${JSON.stringify(fetchOptions)})`;
191
191
  resultContents = `await WebAssembly.instantiateStreaming(${fetchContents}, imports)`;
@@ -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 = '19.0.0';
13
+ const VERSION = '19.0.2';
14
14
  function hasCacheMetadata(value) {
15
15
  return (!!value &&
16
16
  typeof value === 'object' &&
@@ -101,10 +101,8 @@ function generateAngularServerAppManifest(additionalHtmlOutputFiles, outputFiles
101
101
  const extension = (0, node_path_1.extname)(file.path);
102
102
  if (extension === '.html' || (inlineCriticalCss && extension === '.css')) {
103
103
  const jsChunkFilePath = `assets-chunks/${file.path.replace(/[./]/g, '_')}.mjs`;
104
- const escapedContent = escapeUnsafeChars(file.text);
105
- serverAssetsChunks.push((0, utils_1.createOutputFile)(jsChunkFilePath, `export default \`${escapedContent}\`;`, bundler_context_1.BuildOutputFileType.ServerApplication));
106
- const contentLength = Buffer.byteLength(escapedContent);
107
- serverAssetsContent.push(`['${file.path}', {size: ${contentLength}, hash: '${file.hash}', text: () => import('./${jsChunkFilePath}').then(m => m.default)}]`);
104
+ serverAssetsChunks.push((0, utils_1.createOutputFile)(jsChunkFilePath, `export default \`${escapeUnsafeChars(file.text)}\`;`, bundler_context_1.BuildOutputFileType.ServerApplication));
105
+ serverAssetsContent.push(`['${file.path}', {size: ${file.size}, hash: '${file.hash}', text: () => import('./${jsChunkFilePath}').then(m => m.default)}]`);
108
106
  }
109
107
  }
110
108
  const manifestContent = `
@@ -13,5 +13,4 @@ export interface ExtractRoutesWorkerData extends ESMInMemoryFileLoaderWorkerData
13
13
  }
14
14
  /** Renders an application based on a provided options. */
15
15
  declare function extractRoutes(): Promise<RoutersExtractorWorkerResult>;
16
- declare const _default: Promise<typeof extractRoutes>;
17
- export default _default;
16
+ export default extractRoutes;
@@ -16,22 +16,16 @@ const load_esm_from_memory_1 = require("./load-esm-from-memory");
16
16
  * This is passed as workerData when setting up the worker via the `piscina` package.
17
17
  */
18
18
  const { outputMode, hasSsrEntry } = worker_threads_1.workerData;
19
- let serverURL = launch_server_1.DEFAULT_URL;
20
19
  /** Renders an application based on a provided options. */
21
20
  async function extractRoutes() {
21
+ const serverURL = outputMode !== undefined && hasSsrEntry ? await (0, launch_server_1.launchServer)() : launch_server_1.DEFAULT_URL;
22
+ (0, fetch_patch_1.patchFetchToLoadInMemoryAssets)(serverURL);
22
23
  const { ɵextractRoutesAndCreateRouteTree: extractRoutesAndCreateRouteTree } = await (0, load_esm_from_memory_1.loadEsmModuleFromMemory)('./main.server.mjs');
23
- const { routeTree, appShellRoute, errors } = await extractRoutesAndCreateRouteTree(serverURL, undefined /** manifest */, true /** invokeGetPrerenderParams */, outputMode === schema_1.OutputMode.Server /** includePrerenderFallbackRoutes */);
24
+ const { routeTree, appShellRoute, errors } = await extractRoutesAndCreateRouteTree(serverURL, undefined /** manifest */, outputMode !== undefined /** invokeGetPrerenderParams */, outputMode === schema_1.OutputMode.Server /** includePrerenderFallbackRoutes */);
24
25
  return {
25
26
  errors,
26
27
  appShellRoute,
27
28
  serializedRouteTree: routeTree.toObject(),
28
29
  };
29
30
  }
30
- async function initialize() {
31
- if (outputMode !== undefined && hasSsrEntry) {
32
- serverURL = await (0, launch_server_1.launchServer)();
33
- }
34
- (0, fetch_patch_1.patchFetchToLoadInMemoryAssets)(serverURL);
35
- return extractRoutes;
36
- }
37
- exports.default = initialize();
31
+ exports.default = extractRoutes;