@angular/build 19.0.0-rc.1 → 19.0.0-rc.3

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.1",
3
+ "version": "19.0.0-rc.3",
4
4
  "description": "Official build system for Angular",
5
5
  "keywords": [
6
6
  "Angular CLI",
@@ -23,12 +23,12 @@
23
23
  "builders": "builders.json",
24
24
  "dependencies": {
25
25
  "@ampproject/remapping": "2.3.0",
26
- "@angular-devkit/architect": "0.1900.0-rc.1",
26
+ "@angular-devkit/architect": "0.1900.0-rc.3",
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.0.1",
31
+ "@inquirer/confirm": "5.0.2",
32
32
  "@vitejs/plugin-basic-ssl": "1.1.0",
33
33
  "beasties": "0.1.0",
34
34
  "browserslist": "^4.23.0",
@@ -42,14 +42,14 @@
42
42
  "parse5-html-rewriting-stream": "7.0.0",
43
43
  "picomatch": "4.0.2",
44
44
  "piscina": "4.7.0",
45
- "rollup": "4.24.4",
46
- "sass": "1.80.6",
45
+ "rollup": "4.26.0",
46
+ "sass": "1.80.7",
47
47
  "semver": "7.6.3",
48
- "vite": "5.4.10",
48
+ "vite": "5.4.11",
49
49
  "watchpack": "2.4.2"
50
50
  },
51
51
  "optionalDependencies": {
52
- "lmdb": "3.1.4"
52
+ "lmdb": "3.1.5"
53
53
  },
54
54
  "peerDependencies": {
55
55
  "@angular/compiler": "^19.0.0-next.9",
@@ -57,7 +57,7 @@
57
57
  "@angular/localize": "^19.0.0-next.9",
58
58
  "@angular/platform-server": "^19.0.0-next.9",
59
59
  "@angular/service-worker": "^19.0.0-next.9",
60
- "@angular/ssr": "^19.0.0-rc.1",
60
+ "@angular/ssr": "^19.0.0-rc.3",
61
61
  "less": "^4.2.0",
62
62
  "postcss": "^8.4.0",
63
63
  "tailwindcss": "^2.0.0 || ^3.0.0",
@@ -86,21 +86,9 @@ async function executePostBundleSteps(options, outputFiles, assetFiles, initialF
86
86
  }
87
87
  const serializableRouteTreeNodeForManifest = [];
88
88
  for (const metadata of serializableRouteTreeNode) {
89
- switch (metadata.renderMode) {
90
- case models_1.RouteRenderMode.Prerender:
91
- case /* Legacy building mode */ undefined: {
92
- if (!metadata.redirectTo) {
93
- serializableRouteTreeNodeForManifest.push(metadata);
94
- if (!metadata.route.includes('*')) {
95
- prerenderedRoutes[metadata.route] = { headers: metadata.headers };
96
- }
97
- }
98
- break;
99
- }
100
- case models_1.RouteRenderMode.Server:
101
- case models_1.RouteRenderMode.Client:
102
- serializableRouteTreeNodeForManifest.push(metadata);
103
- break;
89
+ serializableRouteTreeNodeForManifest.push(metadata);
90
+ if (metadata.renderMode === models_1.RouteRenderMode.Prerender && !metadata.route.includes('*')) {
91
+ prerenderedRoutes[metadata.route] = { headers: metadata.headers };
104
92
  }
105
93
  }
106
94
  if (outputMode === schema_1.OutputMode.Server) {
@@ -236,7 +236,7 @@ async function normalizeOptions(context, projectName, options, extensions) {
236
236
  }
237
237
  }
238
238
  // Initial options to keep
239
- const { allowedCommonJsDependencies, aot, baseHref, crossOrigin, externalDependencies, extractLicenses, inlineStyleLanguage = 'css', outExtension, serviceWorker, poll, polyfills, statsJson, outputMode, stylePreprocessorOptions, subresourceIntegrity, verbose, watch, progress = true, externalPackages, namedChunks, budgets, deployUrl, clearScreen, define, partialSSRBuild = false, externalRuntimeStyles, instrumentForCoverage, security, } = options;
239
+ const { allowedCommonJsDependencies, aot = true, baseHref, crossOrigin, externalDependencies, extractLicenses, inlineStyleLanguage = 'css', outExtension, serviceWorker, poll, polyfills, statsJson, outputMode, stylePreprocessorOptions, subresourceIntegrity, verbose, watch, progress = true, externalPackages, namedChunks, budgets, deployUrl, clearScreen, define, partialSSRBuild = false, externalRuntimeStyles, instrumentForCoverage, security, } = options;
240
240
  // Return all the normalized options
241
241
  return {
242
242
  advancedOptimizations: !!aot && optimizationOptions.scripts,
@@ -293,7 +293,7 @@ async function normalizeOptions(context, projectName, options, extensions) {
293
293
  clearScreen,
294
294
  define,
295
295
  partialSSRBuild: environment_options_1.usePartialSsrBuild || partialSSRBuild,
296
- externalRuntimeStyles,
296
+ externalRuntimeStyles: aot && externalRuntimeStyles,
297
297
  instrumentForCoverage,
298
298
  security,
299
299
  templateUpdates: !!options.templateUpdates,
@@ -119,7 +119,6 @@ function createCompilerPlugin(pluginOptions, stylesheetBundler) {
119
119
  // dependencies or web worker processing.
120
120
  let modifiedFiles;
121
121
  if (pluginOptions.sourceFileCache?.modifiedFiles.size &&
122
- referencedFileTracker &&
123
122
  !pluginOptions.noopTypeScriptCompilation) {
124
123
  // TODO: Differentiate between changed input files and stale output files
125
124
  modifiedFiles = referencedFileTracker.update(pluginOptions.sourceFileCache.modifiedFiles);
@@ -129,6 +128,8 @@ function createCompilerPlugin(pluginOptions, stylesheetBundler) {
129
128
  if (!pluginOptions.externalRuntimeStyles) {
130
129
  stylesheetBundler.invalidate(modifiedFiles);
131
130
  }
131
+ // Remove any stale additional results based on modified files
132
+ modifiedFiles.forEach((file) => additionalResults.delete(file));
132
133
  }
133
134
  if (!pluginOptions.noopTypeScriptCompilation &&
134
135
  compilation.update &&
@@ -142,6 +143,7 @@ function createCompilerPlugin(pluginOptions, stylesheetBundler) {
142
143
  sourceFileCache: pluginOptions.sourceFileCache,
143
144
  async transformStylesheet(data, containingFile, stylesheetFile, order, className) {
144
145
  let stylesheetResult;
146
+ let resultSource = stylesheetFile ?? containingFile;
145
147
  // Stylesheet file only exists for external stylesheets
146
148
  if (stylesheetFile) {
147
149
  stylesheetResult = await stylesheetBundler.bundleFile(stylesheetFile);
@@ -161,6 +163,11 @@ function createCompilerPlugin(pluginOptions, stylesheetBundler) {
161
163
  .update(className ?? '')
162
164
  .digest('hex')
163
165
  : undefined);
166
+ // Adjust result source for inline styles.
167
+ // There may be multiple inline styles with the same containing file and to ensure that the results
168
+ // do not overwrite each other the result source identifier needs to be unique for each. The class
169
+ // name and order fields can be used for this. The structure is arbitrary as long as it is unique.
170
+ resultSource += `?class=${className}&order=${order}`;
164
171
  }
165
172
  (result.warnings ??= []).push(...stylesheetResult.warnings);
166
173
  if (stylesheetResult.errors) {
@@ -168,7 +175,7 @@ function createCompilerPlugin(pluginOptions, stylesheetBundler) {
168
175
  return '';
169
176
  }
170
177
  const { contents, outputFiles, metafile, referencedFiles } = stylesheetResult;
171
- additionalResults.set(stylesheetFile ?? containingFile, {
178
+ additionalResults.set(resultSource, {
172
179
  outputFiles,
173
180
  metafile,
174
181
  });
@@ -362,12 +369,20 @@ function createCompilerPlugin(pluginOptions, stylesheetBundler) {
362
369
  };
363
370
  });
364
371
  build.onLoad({ filter: /\.[cm]?js$/ }, (0, load_result_cache_1.createCachedLoad)(pluginOptions.loadResultCache, async (args) => {
372
+ let request = args.path;
373
+ if (pluginOptions.fileReplacements) {
374
+ const replacement = pluginOptions.fileReplacements[path.normalize(args.path)];
375
+ if (replacement) {
376
+ request = path.normalize(replacement);
377
+ }
378
+ }
365
379
  return (0, profiling_1.profileAsync)('NG_EMIT_JS*', async () => {
366
- const sideEffects = await hasSideEffects(args.path);
367
- const contents = await javascriptTransformer.transformFile(args.path, pluginOptions.jit, sideEffects);
380
+ const sideEffects = await hasSideEffects(request);
381
+ const contents = await javascriptTransformer.transformFile(request, pluginOptions.jit, sideEffects);
368
382
  return {
369
383
  contents,
370
384
  loader: 'js',
385
+ watchFiles: request !== args.path ? [request] : undefined,
371
386
  };
372
387
  }, true);
373
388
  }));
@@ -65,7 +65,7 @@ class UrlRebasingImporter {
65
65
  continue;
66
66
  }
67
67
  // Sass variable usage either starts with a `$` or contains a namespace and a `.$`
68
- const valueNormalized = value[0] === '$' || /^\w+\.\$/.test(value) ? `#{${value}}` : value;
68
+ const valueNormalized = value[0] === '$' || /^\w[\w_-]*\.\$/.test(value) ? `#{${value}}` : value;
69
69
  const rebasedPath = (0, node_path_1.relative)(this.entryDirectory, stylesheetDirectory);
70
70
  // Normalize path separators and escape characters
71
71
  // https://developer.mozilla.org/en-US/docs/Web/CSS/url#syntax
@@ -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.1';
13
+ const VERSION = '19.0.0-rc.3';
14
14
  function hasCacheMetadata(value) {
15
15
  return (!!value &&
16
16
  typeof value === 'object' &&
@@ -15,6 +15,7 @@ export type SerializableRouteTreeNode = ReturnType<Awaited<ReturnType<typeof ɵe
15
15
  export type WritableSerializableRouteTreeNode = Writeable<SerializableRouteTreeNode>;
16
16
  export interface RoutersExtractorWorkerResult {
17
17
  serializedRouteTree: SerializableRouteTreeNode;
18
+ appShellRoute?: string;
18
19
  errors: string[];
19
20
  }
20
21
  /**
@@ -15,8 +15,7 @@ exports.RouteRenderMode = void 0;
15
15
  * It maps `RenderMode` enum values to their corresponding numeric identifiers.
16
16
  */
17
17
  exports.RouteRenderMode = {
18
- AppShell: 0,
19
- Server: 1,
20
- Client: 2,
21
- Prerender: 3,
18
+ Server: 0,
19
+ Client: 1,
20
+ Prerender: 2,
22
21
  };
@@ -51,12 +51,11 @@ async function prerenderPages(workspaceRoot, baseHref, appShellOptions, prerende
51
51
  assetsReversed[addLeadingSlash(destination.replace(/\\/g, node_path_1.posix.sep))] = source;
52
52
  }
53
53
  // Get routes to prerender
54
- const { errors: extractionErrors, serializedRouteTree: serializableRouteTreeNode } = await getAllRoutes(workspaceRoot, baseHref, outputFilesForWorker, assetsReversed, appShellOptions, prerenderOptions, sourcemap, outputMode).catch((err) => {
54
+ const { errors: extractionErrors, serializedRouteTree: serializableRouteTreeNode, appShellRoute, } = await getAllRoutes(workspaceRoot, baseHref, outputFilesForWorker, assetsReversed, appShellOptions, prerenderOptions, sourcemap, outputMode).catch((err) => {
55
55
  return {
56
- errors: [
57
- `An error occurred while extracting routes.\n\n${err.stack ?? err.message ?? err}`,
58
- ],
56
+ errors: [`An error occurred while extracting routes.\n\n${err.stack ?? err.message ?? err}`],
59
57
  serializedRouteTree: [],
58
+ appShellRoute: undefined,
60
59
  };
61
60
  });
62
61
  errors.push(...extractionErrors);
@@ -73,7 +72,6 @@ async function prerenderPages(workspaceRoot, baseHref, appShellOptions, prerende
73
72
  switch (metadata.renderMode) {
74
73
  case undefined: /* Legacy building mode */
75
74
  case models_1.RouteRenderMode.Prerender:
76
- case models_1.RouteRenderMode.AppShell:
77
75
  serializableRouteTreeNodeForPrerender.push(metadata);
78
76
  break;
79
77
  case models_1.RouteRenderMode.Server:
@@ -92,7 +90,7 @@ async function prerenderPages(workspaceRoot, baseHref, appShellOptions, prerende
92
90
  };
93
91
  }
94
92
  // Render routes
95
- const { errors: renderingErrors, output } = await renderPages(baseHref, sourcemap, serializableRouteTreeNodeForPrerender, maxThreads, workspaceRoot, outputFilesForWorker, assetsReversed, appShellOptions, outputMode);
93
+ const { errors: renderingErrors, output } = await renderPages(baseHref, sourcemap, serializableRouteTreeNodeForPrerender, maxThreads, workspaceRoot, outputFilesForWorker, assetsReversed, appShellOptions, outputMode, appShellRoute ?? appShellOptions?.route);
96
94
  errors.push(...renderingErrors);
97
95
  return {
98
96
  errors,
@@ -101,7 +99,7 @@ async function prerenderPages(workspaceRoot, baseHref, appShellOptions, prerende
101
99
  serializableRouteTreeNode,
102
100
  };
103
101
  }
104
- async function renderPages(baseHref, sourcemap, serializableRouteTreeNode, maxThreads, workspaceRoot, outputFilesForWorker, assetFilesForWorker, appShellOptions, outputMode) {
102
+ async function renderPages(baseHref, sourcemap, serializableRouteTreeNode, maxThreads, workspaceRoot, outputFilesForWorker, assetFilesForWorker, appShellOptions, outputMode, appShellRoute) {
105
103
  const output = {};
106
104
  const errors = [];
107
105
  const workerExecArgv = [utils_1.IMPORT_EXEC_ARGV];
@@ -122,7 +120,7 @@ async function renderPages(baseHref, sourcemap, serializableRouteTreeNode, maxTh
122
120
  });
123
121
  try {
124
122
  const renderingPromises = [];
125
- const appShellRoute = appShellOptions && addLeadingSlash(appShellOptions.route);
123
+ const appShellRouteWithLeadingSlash = appShellRoute && addLeadingSlash(appShellRoute);
126
124
  const baseHrefWithLeadingSlash = addLeadingSlash(baseHref);
127
125
  for (const { route, redirectTo, renderMode } of serializableRouteTreeNode) {
128
126
  // Remove the base href from the file output path.
@@ -134,14 +132,14 @@ async function renderPages(baseHref, sourcemap, serializableRouteTreeNode, maxTh
134
132
  output[outPath] = { content: generateRedirectStaticPage(redirectTo), appShellRoute: false };
135
133
  continue;
136
134
  }
137
- const isAppShellRoute = renderMode === models_1.RouteRenderMode.AppShell ||
138
- // Legacy handling
139
- (renderMode === undefined && appShellRoute === routeWithoutBaseHref);
140
- const render = renderWorker.run({ url: route, isAppShellRoute });
135
+ const render = renderWorker.run({ url: route });
141
136
  const renderResult = render
142
137
  .then((content) => {
143
138
  if (content !== null) {
144
- output[outPath] = { content, appShellRoute: isAppShellRoute };
139
+ output[outPath] = {
140
+ content,
141
+ appShellRoute: appShellRouteWithLeadingSlash === routeWithoutBaseHref,
142
+ };
145
143
  }
146
144
  })
147
145
  .catch((err) => {
@@ -163,10 +161,12 @@ async function renderPages(baseHref, sourcemap, serializableRouteTreeNode, maxTh
163
161
  async function getAllRoutes(workspaceRoot, baseHref, outputFilesForWorker, assetFilesForWorker, appShellOptions, prerenderOptions, sourcemap, outputMode) {
164
162
  const { routesFile, discoverRoutes } = prerenderOptions ?? {};
165
163
  const routes = [];
164
+ let appShellRoute;
166
165
  if (appShellOptions) {
166
+ appShellRoute = (0, url_1.urlJoin)(baseHref, appShellOptions.route);
167
167
  routes.push({
168
- renderMode: models_1.RouteRenderMode.AppShell,
169
- route: (0, url_1.urlJoin)(baseHref, appShellOptions.route),
168
+ renderMode: models_1.RouteRenderMode.Prerender,
169
+ route: appShellRoute,
170
170
  });
171
171
  }
172
172
  if (routesFile) {
@@ -179,7 +179,7 @@ async function getAllRoutes(workspaceRoot, baseHref, outputFilesForWorker, asset
179
179
  }
180
180
  }
181
181
  if (!discoverRoutes) {
182
- return { errors: [], serializedRouteTree: routes };
182
+ return { errors: [], appShellRoute, serializedRouteTree: routes };
183
183
  }
184
184
  const workerExecArgv = [utils_1.IMPORT_EXEC_ARGV];
185
185
  if (sourcemap) {
@@ -198,9 +198,9 @@ async function getAllRoutes(workspaceRoot, baseHref, outputFilesForWorker, asset
198
198
  execArgv: workerExecArgv,
199
199
  });
200
200
  try {
201
- const { serializedRouteTree, errors } = await renderWorker.run({});
201
+ const { serializedRouteTree, appShellRoute, errors } = await renderWorker.run({});
202
202
  if (!routes.length) {
203
- return { errors, serializedRouteTree };
203
+ return { errors, appShellRoute, serializedRouteTree };
204
204
  }
205
205
  // Merge the routing trees
206
206
  const uniqueRoutes = new Map();
@@ -20,9 +20,10 @@ let serverURL = launch_server_1.DEFAULT_URL;
20
20
  /** Renders an application based on a provided options. */
21
21
  async function extractRoutes() {
22
22
  const { ɵextractRoutesAndCreateRouteTree: extractRoutesAndCreateRouteTree } = await (0, load_esm_from_memory_1.loadEsmModuleFromMemory)('./main.server.mjs');
23
- const { routeTree, errors } = await extractRoutesAndCreateRouteTree(serverURL, undefined /** manifest */, true /** invokeGetPrerenderParams */, outputMode === schema_1.OutputMode.Server /** includePrerenderFallbackRoutes */);
23
+ const { routeTree, appShellRoute, errors } = await extractRoutesAndCreateRouteTree(serverURL, undefined /** manifest */, true /** invokeGetPrerenderParams */, outputMode === schema_1.OutputMode.Server /** includePrerenderFallbackRoutes */);
24
24
  return {
25
25
  errors,
26
+ appShellRoute,
26
27
  serializedRouteTree: routeTree.toObject(),
27
28
  };
28
29
  }