@angular/build 19.0.0-next.2 → 19.0.0-next.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.
Files changed (36) hide show
  1. package/package.json +10 -10
  2. package/src/builders/application/execute-post-bundle.js +29 -18
  3. package/src/builders/application/i18n.js +2 -11
  4. package/src/builders/application/options.d.ts +11 -0
  5. package/src/builders/application/options.js +23 -1
  6. package/src/builders/application/setup-bundling.js +7 -7
  7. package/src/builders/dev-server/internal.d.ts +0 -1
  8. package/src/builders/dev-server/internal.js +1 -3
  9. package/src/builders/dev-server/vite-server.d.ts +2 -1
  10. package/src/builders/dev-server/vite-server.js +13 -2
  11. package/src/tools/esbuild/angular/file-reference-tracker.d.ts +1 -1
  12. package/src/tools/esbuild/application-code-bundle.d.ts +1 -6
  13. package/src/tools/esbuild/application-code-bundle.js +105 -70
  14. package/src/tools/esbuild/bundler-context.js +14 -10
  15. package/src/tools/esbuild/cache.d.ts +1 -1
  16. package/src/tools/esbuild/utils.d.ts +9 -0
  17. package/src/tools/esbuild/utils.js +14 -0
  18. package/src/tools/sass/sass-service.js +9 -4
  19. package/src/tools/vite/angular-memory-plugin.js +2 -2
  20. package/src/tools/vite/middlewares/ssr-middleware.d.ts +1 -4
  21. package/src/tools/vite/middlewares/ssr-middleware.js +25 -38
  22. package/src/utils/normalize-cache.js +1 -1
  23. package/src/utils/server-rendering/fetch-patch.js +4 -5
  24. package/src/utils/server-rendering/load-esm-from-memory.d.ts +12 -2
  25. package/src/utils/server-rendering/manifest.d.ts +44 -0
  26. package/src/utils/server-rendering/manifest.js +88 -0
  27. package/src/utils/server-rendering/prerender.d.ts +22 -2
  28. package/src/utils/server-rendering/prerender.js +51 -40
  29. package/src/utils/server-rendering/render-worker.d.ts +7 -8
  30. package/src/utils/server-rendering/render-worker.js +10 -13
  31. package/src/utils/server-rendering/routes-extractor-worker.d.ts +2 -6
  32. package/src/utils/server-rendering/routes-extractor-worker.js +3 -34
  33. package/src/utils/server-rendering/main-bundle-exports.d.ts +0 -27
  34. package/src/utils/server-rendering/main-bundle-exports.js +0 -9
  35. package/src/utils/server-rendering/render-page.d.ts +0 -26
  36. package/src/utils/server-rendering/render-page.js +0 -114
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@angular/build",
3
- "version": "19.0.0-next.2",
3
+ "version": "19.0.0-next.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-next.2",
26
+ "@angular-devkit/architect": "0.1900.0-next.3",
27
27
  "@babel/core": "7.25.2",
28
28
  "@babel/helper-annotate-as-pure": "7.24.7",
29
29
  "@babel/helper-split-export-declaration": "7.24.7",
30
- "@babel/plugin-syntax-import-attributes": "7.24.7",
31
- "@inquirer/confirm": "3.1.22",
30
+ "@babel/plugin-syntax-import-attributes": "7.25.6",
31
+ "@inquirer/confirm": "3.2.0",
32
32
  "@vitejs/plugin-basic-ssl": "1.1.0",
33
33
  "browserslist": "^4.23.0",
34
34
  "critters": "0.0.24",
@@ -36,16 +36,16 @@
36
36
  "fast-glob": "3.3.2",
37
37
  "https-proxy-agent": "7.0.5",
38
38
  "listr2": "8.2.4",
39
- "lmdb": "3.0.14",
39
+ "lmdb": "3.1.0",
40
40
  "magic-string": "0.30.11",
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.6.1",
45
- "rollup": "4.21.1",
46
- "sass": "1.77.8",
45
+ "rollup": "4.21.2",
46
+ "sass": "1.78.0",
47
47
  "semver": "7.6.3",
48
- "vite": "5.4.2",
48
+ "vite": "5.4.3",
49
49
  "watchpack": "2.4.2"
50
50
  },
51
51
  "peerDependencies": {
@@ -53,11 +53,11 @@
53
53
  "@angular/localize": "^19.0.0-next.0",
54
54
  "@angular/platform-server": "^19.0.0-next.0",
55
55
  "@angular/service-worker": "^19.0.0-next.0",
56
- "@angular/ssr": "^19.0.0-next.2",
56
+ "@angular/ssr": "^19.0.0-next.3",
57
57
  "less": "^4.2.0",
58
58
  "postcss": "^8.4.0",
59
59
  "tailwindcss": "^2.0.0 || ^3.0.0",
60
- "typescript": ">=5.4 <5.6"
60
+ "typescript": ">=5.5 <5.7"
61
61
  },
62
62
  "peerDependenciesMeta": {
63
63
  "@angular/localize": {
@@ -16,8 +16,10 @@ const bundler_context_1 = require("../../tools/esbuild/bundler-context");
16
16
  const index_html_generator_1 = require("../../tools/esbuild/index-html-generator");
17
17
  const utils_1 = require("../../tools/esbuild/utils");
18
18
  const environment_options_1 = require("../../utils/environment-options");
19
+ const manifest_1 = require("../../utils/server-rendering/manifest");
19
20
  const prerender_1 = require("../../utils/server-rendering/prerender");
20
21
  const service_worker_1 = require("../../utils/service-worker");
22
+ const options_1 = require("./options");
21
23
  /**
22
24
  * Run additional builds steps including SSG, AppShell, Index HTML file and Service worker generation.
23
25
  * @param options The normalized application builder options used to create the build.
@@ -32,15 +34,11 @@ async function executePostBundleSteps(options, outputFiles, assetFiles, initialF
32
34
  const allErrors = [];
33
35
  const allWarnings = [];
34
36
  const prerenderedRoutes = [];
35
- const { serviceWorker, indexHtmlOptions, optimizationOptions, sourcemapOptions, prerenderOptions, appShellOptions, workspaceRoot, verbose, } = options;
36
- /**
37
- * Index HTML content without CSS inlining to be used for server rendering (AppShell, SSG and SSR).
38
- *
39
- * NOTE: we don't perform critical CSS inlining as this will be done during server rendering.
40
- */
41
- let ssrIndexContent;
42
- // When using prerender/app-shell the index HTML file can be regenerated.
43
- // Thus, we use a Map so that we do not generate 2 files with the same filename.
37
+ const { baseHref = '/', serviceWorker, indexHtmlOptions, optimizationOptions, sourcemapOptions, ssrOptions, prerenderOptions, appShellOptions, workspaceRoot, verbose, } = options;
38
+ // Index HTML content without CSS inlining to be used for server rendering (AppShell, SSG and SSR).
39
+ // NOTE: Critical CSS inlining is deliberately omitted here, as it will be handled during server rendering.
40
+ // Additionally, when using prerendering or AppShell, the index HTML file may be regenerated.
41
+ // To prevent generating duplicate files with the same filename, a `Map` is used to store and manage the files.
44
42
  const additionalHtmlOutputFiles = new Map();
45
43
  // Generate index HTML file
46
44
  // If localization is enabled, index generation is handled in the inlining process.
@@ -50,21 +48,34 @@ async function executePostBundleSteps(options, outputFiles, assetFiles, initialF
50
48
  allWarnings.push(...warnings);
51
49
  additionalHtmlOutputFiles.set(indexHtmlOptions.output, (0, utils_1.createOutputFile)(indexHtmlOptions.output, csrContent, bundler_context_1.BuildOutputFileType.Browser));
52
50
  if (ssrContent) {
53
- const serverIndexHtmlFilename = 'index.server.html';
54
- additionalHtmlOutputFiles.set(serverIndexHtmlFilename, (0, utils_1.createOutputFile)(serverIndexHtmlFilename, ssrContent, bundler_context_1.BuildOutputFileType.Server));
55
- ssrIndexContent = ssrContent;
51
+ additionalHtmlOutputFiles.set(options_1.INDEX_HTML_SERVER, (0, utils_1.createOutputFile)(options_1.INDEX_HTML_SERVER, ssrContent, bundler_context_1.BuildOutputFileType.Server));
56
52
  }
57
53
  }
54
+ // Create server manifest
55
+ if (prerenderOptions || appShellOptions || ssrOptions) {
56
+ additionalOutputFiles.push((0, utils_1.createOutputFile)(manifest_1.SERVER_APP_MANIFEST_FILENAME, (0, manifest_1.generateAngularServerAppManifest)(additionalHtmlOutputFiles, outputFiles, optimizationOptions.styles.inlineCritical ?? false, undefined), bundler_context_1.BuildOutputFileType.Server));
57
+ }
58
58
  // Pre-render (SSG) and App-shell
59
59
  // If localization is enabled, prerendering is handled in the inlining process.
60
- if (prerenderOptions || appShellOptions) {
61
- (0, node_assert_1.default)(ssrIndexContent, 'The "index" option is required when using the "ssg" or "appShell" options.');
62
- const { output, warnings, errors, prerenderedRoutes: generatedRoutes, } = await (0, prerender_1.prerenderPages)(workspaceRoot, appShellOptions, prerenderOptions, outputFiles, assetFiles, ssrIndexContent, sourcemapOptions.scripts, optimizationOptions.styles.inlineCritical, environment_options_1.maxWorkers, verbose);
60
+ if ((prerenderOptions || appShellOptions) && !allErrors.length) {
61
+ (0, node_assert_1.default)(indexHtmlOptions, 'The "index" option is required when using the "ssg" or "appShell" options.');
62
+ const { output, warnings, errors, prerenderedRoutes: generatedRoutes, serializableRouteTreeNode, } = await (0, prerender_1.prerenderPages)(workspaceRoot, baseHref, appShellOptions, prerenderOptions, [...outputFiles, ...additionalOutputFiles], assetFiles, sourcemapOptions.scripts, environment_options_1.maxWorkers, verbose);
63
63
  allErrors.push(...errors);
64
64
  allWarnings.push(...warnings);
65
65
  prerenderedRoutes.push(...Array.from(generatedRoutes));
66
- for (const [path, content] of Object.entries(output)) {
67
- additionalHtmlOutputFiles.set(path, (0, utils_1.createOutputFile)(path, content, bundler_context_1.BuildOutputFileType.Browser));
66
+ const indexHasBeenPrerendered = generatedRoutes.has(indexHtmlOptions.output);
67
+ for (const [path, { content, appShellRoute }] of Object.entries(output)) {
68
+ // Update the index contents with the app shell under these conditions:
69
+ // - Replace 'index.html' with the app shell only if it hasn't been prerendered yet.
70
+ // - Always replace 'index.csr.html' with the app shell.
71
+ const filePath = appShellRoute && !indexHasBeenPrerendered ? indexHtmlOptions.output : path;
72
+ additionalHtmlOutputFiles.set(filePath, (0, utils_1.createOutputFile)(filePath, content, bundler_context_1.BuildOutputFileType.Browser));
73
+ }
74
+ if (ssrOptions) {
75
+ // Regenerate the manifest to append route tree. This is only needed if SSR is enabled.
76
+ const manifest = additionalOutputFiles.find((f) => f.path === manifest_1.SERVER_APP_MANIFEST_FILENAME);
77
+ (0, node_assert_1.default)(manifest, `${manifest_1.SERVER_APP_MANIFEST_FILENAME} was not found in output files.`);
78
+ manifest.contents = new TextEncoder().encode((0, manifest_1.generateAngularServerAppManifest)(additionalHtmlOutputFiles, outputFiles, optimizationOptions.styles.inlineCritical ?? false, serializableRouteTreeNode));
68
79
  }
69
80
  }
70
81
  additionalOutputFiles.push(...additionalHtmlOutputFiles.values());
@@ -72,7 +83,7 @@ async function executePostBundleSteps(options, outputFiles, assetFiles, initialF
72
83
  // If localization is enabled, service worker is handled in the inlining process.
73
84
  if (serviceWorker) {
74
85
  try {
75
- const serviceWorkerResult = await (0, service_worker_1.augmentAppWithServiceWorkerEsbuild)(workspaceRoot, serviceWorker, options.baseHref || '/', options.indexHtmlOptions?.output,
86
+ const serviceWorkerResult = await (0, service_worker_1.augmentAppWithServiceWorkerEsbuild)(workspaceRoot, serviceWorker, baseHref, options.indexHtmlOptions?.output,
76
87
  // Ensure additional files recently added are used
77
88
  [...outputFiles, ...additionalOutputFiles], assetFiles);
78
89
  additionalOutputFiles.push((0, utils_1.createOutputFile)('ngsw.json', serviceWorkerResult.manifest, bundler_context_1.BuildOutputFileType.Browser));
@@ -15,8 +15,8 @@ const i18n_inliner_1 = require("../../tools/esbuild/i18n-inliner");
15
15
  const environment_options_1 = require("../../utils/environment-options");
16
16
  const i18n_options_1 = require("../../utils/i18n-options");
17
17
  const load_translations_1 = require("../../utils/load-translations");
18
- const url_1 = require("../../utils/url");
19
18
  const execute_post_bundle_1 = require("./execute-post-bundle");
19
+ const options_1 = require("./options");
20
20
  /**
21
21
  * Inlines all active locales as specified by the application build options into all
22
22
  * application JavaScript files created during the build.
@@ -46,7 +46,7 @@ async function inlineI18n(options, executionResult, initialFiles) {
46
46
  const localeOutputFiles = localeInlineResult.outputFiles;
47
47
  inlineResult.errors.push(...localeInlineResult.errors);
48
48
  inlineResult.warnings.push(...localeInlineResult.warnings);
49
- const baseHref = getLocaleBaseHref(options.baseHref, options.i18nOptions, locale) ?? options.baseHref;
49
+ const baseHref = (0, options_1.getLocaleBaseHref)(options.baseHref, options.i18nOptions, locale) ?? options.baseHref;
50
50
  const { errors, warnings, additionalAssets, additionalOutputFiles, prerenderedRoutes: generatedRoutes, } = await (0, execute_post_bundle_1.executePostBundleSteps)({
51
51
  ...options,
52
52
  baseHref,
@@ -90,15 +90,6 @@ async function inlineI18n(options, executionResult, initialFiles) {
90
90
  }
91
91
  return inlineResult;
92
92
  }
93
- function getLocaleBaseHref(baseHref, i18n, locale) {
94
- if (i18n.flatOutput) {
95
- return undefined;
96
- }
97
- if (i18n.locales[locale] && i18n.locales[locale].baseHref !== '') {
98
- return (0, url_1.urlJoin)(baseHref || '', i18n.locales[locale].baseHref ?? `/${locale}/`);
99
- }
100
- return undefined;
101
- }
102
93
  /**
103
94
  * Loads all active translations using the translation loaders from the `@angular/localize` package.
104
95
  * @param context The architect builder context for the current build.
@@ -10,6 +10,16 @@ import type { Plugin } from 'esbuild';
10
10
  import { I18nOptions } from '../../utils/i18n-options';
11
11
  import { IndexHtmlTransform } from '../../utils/index-file/index-html-generator';
12
12
  import { Schema as ApplicationBuilderOptions, I18NTranslation, OutputPathClass } from './schema';
13
+ /**
14
+ * The filename for the client-side rendered HTML template.
15
+ * This template is used for client-side rendering (CSR) in a web application.
16
+ */
17
+ export declare const INDEX_HTML_CSR = "index.csr.html";
18
+ /**
19
+ * The filename for the server-side rendered HTML template.
20
+ * This template is used for server-side rendering (SSR) in a web application.
21
+ */
22
+ export declare const INDEX_HTML_SERVER = "index.server.html";
13
23
  export type NormalizedOutputOptions = Required<OutputPathClass> & {
14
24
  clean: boolean;
15
25
  ignoreServer: boolean;
@@ -148,4 +158,5 @@ export declare function normalizeOptions(context: BuilderContext, projectName: s
148
158
  [key: string]: string;
149
159
  } | undefined;
150
160
  }>;
161
+ export declare function getLocaleBaseHref(baseHref: string | undefined, i18n: NormalizedApplicationBuildOptions['i18nOptions'], locale: string): string | undefined;
151
162
  export {};
@@ -10,7 +10,9 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
10
10
  return (mod && mod.__esModule) ? mod : { "default": mod };
11
11
  };
12
12
  Object.defineProperty(exports, "__esModule", { value: true });
13
+ exports.INDEX_HTML_SERVER = exports.INDEX_HTML_CSR = void 0;
13
14
  exports.normalizeOptions = normalizeOptions;
15
+ exports.getLocaleBaseHref = getLocaleBaseHref;
14
16
  const node_fs_1 = require("node:fs");
15
17
  const promises_1 = require("node:fs/promises");
16
18
  const node_module_1 = require("node:module");
@@ -21,7 +23,18 @@ const environment_options_1 = require("../../utils/environment-options");
21
23
  const i18n_options_1 = require("../../utils/i18n-options");
22
24
  const normalize_cache_1 = require("../../utils/normalize-cache");
23
25
  const postcss_configuration_1 = require("../../utils/postcss-configuration");
26
+ const url_1 = require("../../utils/url");
24
27
  const schema_1 = require("./schema");
28
+ /**
29
+ * The filename for the client-side rendered HTML template.
30
+ * This template is used for client-side rendering (CSR) in a web application.
31
+ */
32
+ exports.INDEX_HTML_CSR = 'index.csr.html';
33
+ /**
34
+ * The filename for the server-side rendered HTML template.
35
+ * This template is used for server-side rendering (SSR) in a web application.
36
+ */
37
+ exports.INDEX_HTML_SERVER = 'index.server.html';
25
38
  /**
26
39
  * Normalize the user provided options by creating full paths for all path based options
27
40
  * and converting multi-form options into a single form that can be directly used
@@ -164,7 +177,7 @@ async function normalizeOptions(context, projectName, options, extensions) {
164
177
  * For instance, accessing `foo.com/` would lead to `foo.com/index.html` being served instead of hitting the server.
165
178
  */
166
179
  const indexBaseName = node_path_1.default.basename(options.index);
167
- indexOutput = ssrOptions && indexBaseName === 'index.html' ? 'index.csr.html' : indexBaseName;
180
+ indexOutput = ssrOptions && indexBaseName === 'index.html' ? exports.INDEX_HTML_CSR : indexBaseName;
168
181
  }
169
182
  else {
170
183
  indexOutput = options.index.output || 'index.html';
@@ -369,3 +382,12 @@ function normalizeGlobalEntries(rawEntries, defaultName) {
369
382
  }
370
383
  return [...bundles.values()];
371
384
  }
385
+ function getLocaleBaseHref(baseHref, i18n, locale) {
386
+ if (i18n.flatOutput) {
387
+ return undefined;
388
+ }
389
+ if (i18n.locales[locale] && i18n.locales[locale].baseHref !== '') {
390
+ return (0, url_1.urlJoin)(baseHref || '', i18n.locales[locale].baseHref ?? `/${locale}/`);
391
+ }
392
+ return undefined;
393
+ }
@@ -22,22 +22,22 @@ const utils_1 = require("../../tools/esbuild/utils");
22
22
  * @returns An array of BundlerContext objects.
23
23
  */
24
24
  function setupBundlerContexts(options, browsers, codeBundleCache) {
25
- const { appShellOptions, prerenderOptions, serverEntryPoint, ssrOptions, workspaceRoot } = options;
25
+ const { appShellOptions, prerenderOptions, serverEntryPoint, ssrOptions, workspaceRoot, watch = false, } = options;
26
26
  const target = (0, utils_1.transformSupportedBrowsersToTargets)(browsers);
27
27
  const bundlerContexts = [];
28
28
  // Browser application code
29
- bundlerContexts.push(new bundler_context_1.BundlerContext(workspaceRoot, !!options.watch, (0, application_code_bundle_1.createBrowserCodeBundleOptions)(options, target, codeBundleCache)));
29
+ bundlerContexts.push(new bundler_context_1.BundlerContext(workspaceRoot, watch, (0, application_code_bundle_1.createBrowserCodeBundleOptions)(options, target, codeBundleCache)));
30
30
  // Browser polyfills code
31
31
  const browserPolyfillBundleOptions = (0, application_code_bundle_1.createBrowserPolyfillBundleOptions)(options, target, codeBundleCache);
32
32
  if (browserPolyfillBundleOptions) {
33
- bundlerContexts.push(new bundler_context_1.BundlerContext(workspaceRoot, !!options.watch, browserPolyfillBundleOptions));
33
+ bundlerContexts.push(new bundler_context_1.BundlerContext(workspaceRoot, watch, browserPolyfillBundleOptions));
34
34
  }
35
35
  // Global Stylesheets
36
36
  if (options.globalStyles.length > 0) {
37
37
  for (const initial of [true, false]) {
38
38
  const bundleOptions = (0, global_styles_1.createGlobalStylesBundleOptions)(options, target, initial);
39
39
  if (bundleOptions) {
40
- bundlerContexts.push(new bundler_context_1.BundlerContext(workspaceRoot, !!options.watch, bundleOptions, () => initial));
40
+ bundlerContexts.push(new bundler_context_1.BundlerContext(workspaceRoot, watch, bundleOptions, () => initial));
41
41
  }
42
42
  }
43
43
  }
@@ -46,7 +46,7 @@ function setupBundlerContexts(options, browsers, codeBundleCache) {
46
46
  for (const initial of [true, false]) {
47
47
  const bundleOptions = (0, global_scripts_1.createGlobalScriptsBundleOptions)(options, target, initial);
48
48
  if (bundleOptions) {
49
- bundlerContexts.push(new bundler_context_1.BundlerContext(workspaceRoot, !!options.watch, bundleOptions, () => initial));
49
+ bundlerContexts.push(new bundler_context_1.BundlerContext(workspaceRoot, watch, bundleOptions, () => initial));
50
50
  }
51
51
  }
52
52
  }
@@ -54,11 +54,11 @@ function setupBundlerContexts(options, browsers, codeBundleCache) {
54
54
  if (serverEntryPoint && (prerenderOptions || appShellOptions || ssrOptions)) {
55
55
  const nodeTargets = [...target, ...(0, utils_1.getSupportedNodeTargets)()];
56
56
  // Server application code
57
- bundlerContexts.push(new bundler_context_1.BundlerContext(workspaceRoot, !!options.watch, (0, application_code_bundle_1.createServerCodeBundleOptions)(options, nodeTargets, codeBundleCache)));
57
+ bundlerContexts.push(new bundler_context_1.BundlerContext(workspaceRoot, watch, (0, application_code_bundle_1.createServerMainCodeBundleOptions)(options, nodeTargets, codeBundleCache)));
58
58
  // Server polyfills code
59
59
  const serverPolyfillBundleOptions = (0, application_code_bundle_1.createServerPolyfillBundleOptions)(options, nodeTargets, codeBundleCache);
60
60
  if (serverPolyfillBundleOptions) {
61
- bundlerContexts.push(new bundler_context_1.BundlerContext(workspaceRoot, !!options.watch, serverPolyfillBundleOptions));
61
+ bundlerContexts.push(new bundler_context_1.BundlerContext(workspaceRoot, watch, serverPolyfillBundleOptions));
62
62
  }
63
63
  }
64
64
  return bundlerContexts;
@@ -9,7 +9,6 @@ export { type BuildOutputFile, BuildOutputFileType } from '@angular/build';
9
9
  export { createRxjsEsmResolutionPlugin } from '../../tools/esbuild/rxjs-esm-resolution-plugin';
10
10
  export { JavaScriptTransformer } from '../../tools/esbuild/javascript-transformer';
11
11
  export { getFeatureSupport, isZonelessApp } from '../../tools/esbuild/utils';
12
- export { renderPage } from '../../utils/server-rendering/render-page';
13
12
  export { type IndexHtmlTransform } from '../../utils/index-file/index-html-generator';
14
13
  export { purgeStaleBuildCache } from '../../utils/purge-cache';
15
14
  export { getSupportedBrowsers } from '../../utils/supported-browsers';
@@ -7,7 +7,7 @@
7
7
  * found in the LICENSE file at https://angular.dev/license
8
8
  */
9
9
  Object.defineProperty(exports, "__esModule", { value: true });
10
- exports.buildApplicationInternal = exports.transformSupportedBrowsersToTargets = exports.getSupportedBrowsers = exports.purgeStaleBuildCache = exports.renderPage = exports.isZonelessApp = exports.getFeatureSupport = exports.JavaScriptTransformer = exports.createRxjsEsmResolutionPlugin = exports.BuildOutputFileType = void 0;
10
+ exports.buildApplicationInternal = exports.transformSupportedBrowsersToTargets = exports.getSupportedBrowsers = exports.purgeStaleBuildCache = exports.isZonelessApp = exports.getFeatureSupport = exports.JavaScriptTransformer = exports.createRxjsEsmResolutionPlugin = exports.BuildOutputFileType = void 0;
11
11
  var build_1 = require("@angular/build");
12
12
  Object.defineProperty(exports, "BuildOutputFileType", { enumerable: true, get: function () { return build_1.BuildOutputFileType; } });
13
13
  var rxjs_esm_resolution_plugin_1 = require("../../tools/esbuild/rxjs-esm-resolution-plugin");
@@ -17,8 +17,6 @@ Object.defineProperty(exports, "JavaScriptTransformer", { enumerable: true, get:
17
17
  var utils_1 = require("../../tools/esbuild/utils");
18
18
  Object.defineProperty(exports, "getFeatureSupport", { enumerable: true, get: function () { return utils_1.getFeatureSupport; } });
19
19
  Object.defineProperty(exports, "isZonelessApp", { enumerable: true, get: function () { return utils_1.isZonelessApp; } });
20
- var render_page_1 = require("../../utils/server-rendering/render-page");
21
- Object.defineProperty(exports, "renderPage", { enumerable: true, get: function () { return render_page_1.renderPage; } });
22
20
  var purge_cache_1 = require("../../utils/purge-cache");
23
21
  Object.defineProperty(exports, "purgeStaleBuildCache", { enumerable: true, get: function () { return purge_cache_1.purgeStaleBuildCache; } });
24
22
  var supported_browsers_1 = require("../../utils/supported-browsers");
@@ -9,7 +9,7 @@ import type { BuilderContext } from '@angular-devkit/architect';
9
9
  import type { Plugin } from 'esbuild';
10
10
  import type { Connect, DepOptimizationConfig, InlineConfig } from 'vite';
11
11
  import { Result } from '../application/results';
12
- import { type ApplicationBuilderInternalOptions, type ExternalResultMetadata, JavaScriptTransformer } from './internal';
12
+ import { type ApplicationBuilderInternalOptions, BuildOutputFileType, type ExternalResultMetadata, JavaScriptTransformer } from './internal';
13
13
  import type { NormalizedDevServerOptions } from './options';
14
14
  import type { DevServerBuilderOutput } from './output';
15
15
  interface OutputFileRecord {
@@ -18,6 +18,7 @@ interface OutputFileRecord {
18
18
  hash?: string;
19
19
  updated: boolean;
20
20
  servable: boolean;
21
+ type: BuildOutputFileType;
21
22
  }
22
23
  export type BuilderAction = (options: ApplicationBuilderInternalOptions, context: BuilderContext, plugins?: Plugin[]) => AsyncIterable<Result>;
23
24
  export declare function serveWithVite(serverOptions: NormalizedDevServerOptions, builderName: string, builderAction: BuilderAction, context: BuilderContext, transformers?: {
@@ -204,12 +204,14 @@ async function* serveWithVite(serverOptions, builderName, builderAction, context
204
204
  server.config.server.fs.allow = [
205
205
  ...new Set([...server.config.server.fs.allow, ...assetFiles.values()]),
206
206
  ];
207
- handleUpdate(normalizePath, generatedFiles, server, serverOptions, context.logger);
208
207
  if (requiresServerRestart) {
209
208
  // Restart the server to force SSR dep re-optimization when a dependency has been added.
210
209
  // This is a workaround for: https://github.com/vitejs/vite/issues/14896
211
210
  await server.restart();
212
211
  }
212
+ else {
213
+ await handleUpdate(normalizePath, generatedFiles, server, serverOptions, context.logger);
214
+ }
213
215
  }
214
216
  else {
215
217
  const projectName = context.target?.project;
@@ -271,12 +273,14 @@ async function* serveWithVite(serverOptions, builderName, builderAction, context
271
273
  }
272
274
  await new Promise((resolve) => (deferred = resolve));
273
275
  }
274
- function handleUpdate(normalizePath, generatedFiles, server, serverOptions, logger) {
276
+ async function handleUpdate(normalizePath, generatedFiles, server, serverOptions, logger) {
275
277
  const updatedFiles = [];
278
+ let isServerFileUpdated = false;
276
279
  // Invalidate any updated files
277
280
  for (const [file, record] of generatedFiles) {
278
281
  if (record.updated) {
279
282
  updatedFiles.push(file);
283
+ isServerFileUpdated ||= record.type === internal_1.BuildOutputFileType.Server;
280
284
  const updatedModules = server.moduleGraph.getModulesByFile(normalizePath((0, node_path_1.join)(server.config.root, file)));
281
285
  updatedModules?.forEach((m) => server?.moduleGraph.invalidateModule(m));
282
286
  }
@@ -284,6 +288,11 @@ function handleUpdate(normalizePath, generatedFiles, server, serverOptions, logg
284
288
  if (!updatedFiles.length) {
285
289
  return;
286
290
  }
291
+ // clean server apps cache
292
+ if (isServerFileUpdated) {
293
+ const { ɵdestroyAngularServerApp } = (await server.ssrLoadModule('/main.server.mjs'));
294
+ ɵdestroyAngularServerApp();
295
+ }
287
296
  if (serverOptions.liveReload || serverOptions.hmr) {
288
297
  if (updatedFiles.every((f) => f.endsWith('.css'))) {
289
298
  const timestamp = Date.now();
@@ -334,6 +343,7 @@ function analyzeResultFiles(normalizePath, htmlIndexPath, resultFiles, generated
334
343
  contents: file.contents,
335
344
  servable,
336
345
  size: file.contents.byteLength,
346
+ type: file.type,
337
347
  updated: false,
338
348
  });
339
349
  continue;
@@ -352,6 +362,7 @@ function analyzeResultFiles(normalizePath, htmlIndexPath, resultFiles, generated
352
362
  size: file.contents.byteLength,
353
363
  hash: file.hash,
354
364
  updated: true,
365
+ type: file.type,
355
366
  servable,
356
367
  });
357
368
  }
@@ -7,7 +7,7 @@
7
7
  */
8
8
  export declare class FileReferenceTracker {
9
9
  #private;
10
- get referencedFiles(): IterableIterator<string>;
10
+ get referencedFiles(): MapIterator<string>;
11
11
  add(containingFile: string, referencedFiles: Iterable<string>): void;
12
12
  /**
13
13
  *
@@ -11,10 +11,5 @@ import { SourceFileCache } from './angular/source-file-cache';
11
11
  import { BundlerOptionsFactory } from './bundler-context';
12
12
  export declare function createBrowserCodeBundleOptions(options: NormalizedApplicationBuildOptions, target: string[], sourceFileCache?: SourceFileCache): BuildOptions;
13
13
  export declare function createBrowserPolyfillBundleOptions(options: NormalizedApplicationBuildOptions, target: string[], sourceFileCache?: SourceFileCache): BuildOptions | BundlerOptionsFactory | undefined;
14
- /**
15
- * Create an esbuild 'build' options object for the server bundle.
16
- * @param options The builder's user-provider normalized options.
17
- * @returns An esbuild BuildOptions object.
18
- */
19
- export declare function createServerCodeBundleOptions(options: NormalizedApplicationBuildOptions, target: string[], sourceFileCache: SourceFileCache): BuildOptions;
20
14
  export declare function createServerPolyfillBundleOptions(options: NormalizedApplicationBuildOptions, target: string[], sourceFileCache?: SourceFileCache): BundlerOptionsFactory | undefined;
15
+ export declare function createServerMainCodeBundleOptions(options: NormalizedApplicationBuildOptions, target: string[], sourceFileCache: SourceFileCache): BuildOptions;