@angular/build 19.0.0-rc.3 → 19.0.1

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-rc.3",
3
+ "version": "19.0.1",
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-rc.3",
26
+ "@angular-devkit/architect": "0.1900.1",
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",
@@ -52,12 +52,12 @@
52
52
  "lmdb": "3.1.5"
53
53
  },
54
54
  "peerDependencies": {
55
- "@angular/compiler": "^19.0.0-next.9",
56
- "@angular/compiler-cli": "^19.0.0-next.9",
57
- "@angular/localize": "^19.0.0-next.9",
58
- "@angular/platform-server": "^19.0.0-next.9",
59
- "@angular/service-worker": "^19.0.0-next.9",
60
- "@angular/ssr": "^19.0.0-rc.3",
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.0.1",
61
61
  "less": "^4.2.0",
62
62
  "postcss": "^8.4.0",
63
63
  "tailwindcss": "^2.0.0 || ^3.0.0",
@@ -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 ?? '')
@@ -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-rc.3';
13
+ const VERSION = '19.0.1';
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,9 +16,10 @@ 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
24
  const { routeTree, appShellRoute, errors } = await extractRoutesAndCreateRouteTree(serverURL, undefined /** manifest */, true /** invokeGetPrerenderParams */, outputMode === schema_1.OutputMode.Server /** includePrerenderFallbackRoutes */);
24
25
  return {
@@ -27,11 +28,4 @@ async function extractRoutes() {
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;