@angular/build 19.0.0-next.1 → 19.0.0-next.11

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 (129) hide show
  1. package/LICENSE +5 -5
  2. package/package.json +26 -22
  3. package/src/builders/application/build-action.js +9 -9
  4. package/src/builders/application/chunk-optimizer.js +1 -4
  5. package/src/builders/application/execute-build.js +19 -2
  6. package/src/builders/application/execute-post-bundle.d.ts +2 -2
  7. package/src/builders/application/execute-post-bundle.js +58 -20
  8. package/src/builders/application/i18n.d.ts +2 -2
  9. package/src/builders/application/i18n.js +6 -16
  10. package/src/builders/application/index.js +8 -5
  11. package/src/builders/application/options.d.ts +38 -1
  12. package/src/builders/application/options.js +62 -4
  13. package/src/builders/application/results.d.ts +5 -3
  14. package/src/builders/application/schema.d.ts +72 -0
  15. package/src/builders/application/schema.js +29 -1
  16. package/src/builders/application/schema.json +38 -0
  17. package/src/builders/application/setup-bundling.js +12 -9
  18. package/src/builders/dev-server/internal.d.ts +0 -1
  19. package/src/builders/dev-server/internal.js +1 -3
  20. package/src/builders/dev-server/vite-server.d.ts +8 -2
  21. package/src/builders/dev-server/vite-server.js +132 -58
  22. package/src/builders/extract-i18n/application-extraction.js +3 -3
  23. package/src/tools/angular/angular-host.d.ts +2 -1
  24. package/src/tools/angular/angular-host.js +17 -1
  25. package/src/tools/angular/compilation/angular-compilation.d.ts +1 -0
  26. package/src/tools/angular/compilation/aot-compilation.d.ts +1 -0
  27. package/src/tools/angular/compilation/aot-compilation.js +9 -1
  28. package/src/tools/angular/compilation/parallel-compilation.d.ts +2 -1
  29. package/src/tools/angular/compilation/parallel-compilation.js +4 -12
  30. package/src/tools/angular/compilation/parallel-worker.d.ts +1 -0
  31. package/src/tools/angular/compilation/parallel-worker.js +5 -2
  32. package/src/tools/babel/plugins/add-code-coverage.d.ts +14 -0
  33. package/src/tools/babel/plugins/add-code-coverage.js +44 -0
  34. package/src/tools/babel/plugins/types.d.ts +20 -0
  35. package/src/tools/esbuild/angular/compiler-plugin.d.ts +2 -0
  36. package/src/tools/esbuild/angular/compiler-plugin.js +69 -10
  37. package/src/tools/esbuild/angular/component-stylesheets.d.ts +10 -4
  38. package/src/tools/esbuild/angular/component-stylesheets.js +49 -12
  39. package/src/tools/esbuild/angular/file-reference-tracker.d.ts +1 -1
  40. package/src/tools/esbuild/angular/jit-plugin-callbacks.d.ts +1 -1
  41. package/src/tools/esbuild/angular/jit-plugin-callbacks.js +2 -2
  42. package/src/tools/esbuild/application-code-bundle.d.ts +2 -6
  43. package/src/tools/esbuild/application-code-bundle.js +233 -71
  44. package/src/tools/esbuild/budget-stats.js +1 -1
  45. package/src/tools/esbuild/bundler-context.d.ts +4 -3
  46. package/src/tools/esbuild/bundler-context.js +24 -19
  47. package/src/tools/esbuild/bundler-execution-result.d.ts +5 -2
  48. package/src/tools/esbuild/bundler-execution-result.js +7 -3
  49. package/src/tools/esbuild/cache.d.ts +6 -1
  50. package/src/tools/esbuild/cache.js +7 -0
  51. package/src/tools/esbuild/compiler-plugin-options.js +6 -1
  52. package/src/tools/esbuild/global-scripts.js +1 -1
  53. package/src/tools/esbuild/global-styles.js +3 -0
  54. package/src/tools/esbuild/i18n-inliner.js +4 -4
  55. package/src/tools/esbuild/javascript-transformer-worker.d.ts +1 -0
  56. package/src/tools/esbuild/javascript-transformer-worker.js +5 -1
  57. package/src/tools/esbuild/javascript-transformer.d.ts +2 -2
  58. package/src/tools/esbuild/javascript-transformer.js +7 -12
  59. package/src/tools/esbuild/server-bundle-metadata-plugin.d.ts +22 -0
  60. package/src/tools/esbuild/server-bundle-metadata-plugin.js +36 -0
  61. package/src/tools/esbuild/stylesheets/bundle-options.d.ts +2 -0
  62. package/src/tools/esbuild/stylesheets/bundle-options.js +2 -1
  63. package/src/tools/esbuild/stylesheets/sass-language.js +4 -0
  64. package/src/tools/esbuild/stylesheets/stylesheet-plugin-factory.d.ts +9 -0
  65. package/src/tools/esbuild/utils.d.ts +9 -0
  66. package/src/tools/esbuild/utils.js +33 -4
  67. package/src/tools/sass/sass-service.js +11 -13
  68. package/src/tools/sass/worker.d.ts +13 -32
  69. package/src/tools/sass/worker.js +20 -0
  70. package/src/tools/vite/middlewares/assets-middleware.d.ts +1 -1
  71. package/src/tools/vite/middlewares/assets-middleware.js +43 -4
  72. package/src/tools/vite/middlewares/component-middleware.d.ts +9 -0
  73. package/src/tools/vite/middlewares/component-middleware.js +33 -0
  74. package/src/tools/vite/middlewares/headers-middleware.d.ts +19 -0
  75. package/src/tools/vite/middlewares/headers-middleware.js +34 -0
  76. package/src/tools/vite/middlewares/html-fallback-middleware.d.ts +1 -1
  77. package/src/tools/vite/middlewares/html-fallback-middleware.js +23 -7
  78. package/src/tools/vite/middlewares/index-html-middleware.js +1 -2
  79. package/src/tools/vite/middlewares/index.d.ts +3 -1
  80. package/src/tools/vite/middlewares/index.js +7 -2
  81. package/src/tools/vite/middlewares/ssr-middleware.d.ts +2 -4
  82. package/src/tools/vite/middlewares/ssr-middleware.js +75 -43
  83. package/src/tools/vite/plugins/angular-memory-plugin.d.ts +16 -0
  84. package/src/tools/vite/{angular-memory-plugin.js → plugins/angular-memory-plugin.js} +19 -40
  85. package/src/tools/vite/{i18n-locale-plugin.d.ts → plugins/i18n-locale-plugin.d.ts} +0 -4
  86. package/src/tools/vite/{i18n-locale-plugin.js → plugins/i18n-locale-plugin.js} +2 -3
  87. package/src/tools/vite/plugins/index.d.ts +12 -0
  88. package/src/tools/vite/plugins/index.js +21 -0
  89. package/src/tools/vite/plugins/setup-middlewares-plugin.d.ts +42 -0
  90. package/src/tools/vite/plugins/setup-middlewares-plugin.js +63 -0
  91. package/src/{utils/server-rendering/main-bundle-exports.js → tools/vite/plugins/ssr-transform-plugin.d.ts} +2 -2
  92. package/src/tools/vite/plugins/ssr-transform-plugin.js +38 -0
  93. package/src/tools/vite/utils.d.ts +0 -3
  94. package/src/tools/vite/utils.js +0 -12
  95. package/src/typings.d.ts +26 -0
  96. package/src/utils/environment-options.d.ts +2 -0
  97. package/src/utils/environment-options.js +5 -1
  98. package/src/utils/index-file/index-html-generator.js +5 -0
  99. package/src/utils/index-file/inline-critical-css.js +43 -33
  100. package/src/utils/index-file/ngcm-attribute.d.ts +15 -0
  101. package/src/utils/index-file/ngcm-attribute.js +37 -0
  102. package/src/utils/index-file/valid-self-closing-tags.js +28 -0
  103. package/src/utils/normalize-cache.js +1 -1
  104. package/src/utils/server-rendering/fetch-patch.d.ts +1 -1
  105. package/src/utils/server-rendering/fetch-patch.js +5 -6
  106. package/src/utils/server-rendering/launch-server.d.ts +14 -0
  107. package/src/utils/server-rendering/launch-server.js +63 -0
  108. package/src/utils/server-rendering/load-esm-from-memory.d.ts +18 -2
  109. package/src/utils/server-rendering/manifest.d.ts +50 -0
  110. package/src/utils/server-rendering/manifest.js +126 -0
  111. package/src/utils/server-rendering/models.d.ts +27 -0
  112. package/src/utils/server-rendering/models.js +22 -0
  113. package/src/utils/server-rendering/prerender.d.ts +26 -10
  114. package/src/utils/server-rendering/prerender.js +122 -75
  115. package/src/utils/server-rendering/render-worker.d.ts +9 -8
  116. package/src/utils/server-rendering/render-worker.js +19 -14
  117. package/src/utils/server-rendering/routes-extractor-worker.d.ts +6 -10
  118. package/src/utils/server-rendering/routes-extractor-worker.js +16 -33
  119. package/src/utils/server-rendering/utils.d.ts +11 -0
  120. package/src/utils/server-rendering/utils.js +17 -0
  121. package/src/utils/supported-browsers.js +1 -0
  122. package/src/utils/worker-pool.d.ts +12 -0
  123. package/src/utils/worker-pool.js +43 -0
  124. package/src/tools/vite/angular-memory-plugin.d.ts +0 -21
  125. package/src/utils/server-rendering/main-bundle-exports.d.ts +0 -27
  126. package/src/utils/server-rendering/render-page.d.ts +0 -26
  127. package/src/utils/server-rendering/render-page.js +0 -114
  128. /package/src/tools/vite/{id-prefix-plugin.d.ts → plugins/id-prefix-plugin.d.ts} +0 -0
  129. /package/src/tools/vite/{id-prefix-plugin.js → plugins/id-prefix-plugin.js} +0 -0
@@ -12,18 +12,22 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
12
12
  Object.defineProperty(exports, "__esModule", { value: true });
13
13
  exports.createBrowserCodeBundleOptions = createBrowserCodeBundleOptions;
14
14
  exports.createBrowserPolyfillBundleOptions = createBrowserPolyfillBundleOptions;
15
- exports.createServerCodeBundleOptions = createServerCodeBundleOptions;
16
15
  exports.createServerPolyfillBundleOptions = createServerPolyfillBundleOptions;
16
+ exports.createServerMainCodeBundleOptions = createServerMainCodeBundleOptions;
17
+ exports.createSsrEntryCodeBundleOptions = createSsrEntryCodeBundleOptions;
17
18
  const node_assert_1 = __importDefault(require("node:assert"));
18
19
  const node_crypto_1 = require("node:crypto");
19
20
  const node_path_1 = require("node:path");
21
+ const schema_1 = require("../../builders/application/schema");
20
22
  const environment_options_1 = require("../../utils/environment-options");
23
+ const manifest_1 = require("../../utils/server-rendering/manifest");
21
24
  const compiler_plugin_1 = require("./angular/compiler-plugin");
22
25
  const compiler_plugin_options_1 = require("./compiler-plugin-options");
23
26
  const external_packages_plugin_1 = require("./external-packages-plugin");
24
27
  const i18n_locale_plugin_1 = require("./i18n-locale-plugin");
25
28
  const loader_import_attribute_plugin_1 = require("./loader-import-attribute-plugin");
26
29
  const rxjs_esm_resolution_plugin_1 = require("./rxjs-esm-resolution-plugin");
30
+ const server_bundle_metadata_plugin_1 = require("./server-bundle-metadata-plugin");
27
31
  const sourcemap_ignorelist_plugin_1 = require("./sourcemap-ignorelist-plugin");
28
32
  const utils_1 = require("./utils");
29
33
  const virtual_module_plugin_1 = require("./virtual-module-plugin");
@@ -110,29 +114,29 @@ function createBrowserPolyfillBundleOptions(options, target, sourceFileCache) {
110
114
  // cannot be used with fully incremental bundling yet.
111
115
  return hasTypeScriptEntries ? buildOptions : () => buildOptions;
112
116
  }
113
- /**
114
- * Create an esbuild 'build' options object for the server bundle.
115
- * @param options The builder's user-provider normalized options.
116
- * @returns An esbuild BuildOptions object.
117
- */
118
- function createServerCodeBundleOptions(options, target, sourceFileCache) {
119
- const { serverEntryPoint, workspaceRoot, ssrOptions, watch, externalPackages, prerenderOptions, polyfills, } = options;
120
- (0, node_assert_1.default)(serverEntryPoint, 'createServerCodeBundleOptions should not be called without a defined serverEntryPoint.');
121
- const { pluginOptions, styleOptions } = (0, compiler_plugin_options_1.createCompilerPluginOptions)(options, target, sourceFileCache);
122
- const mainServerNamespace = 'angular:server-render-utils';
123
- const entryPoints = {
124
- 'render-utils.server': mainServerNamespace,
125
- 'main.server': serverEntryPoint,
126
- };
127
- const ssrEntryPoint = ssrOptions?.entry;
128
- if (ssrEntryPoint) {
129
- entryPoints['server'] = ssrEntryPoint;
117
+ function createServerPolyfillBundleOptions(options, target, sourceFileCache) {
118
+ const serverPolyfills = [];
119
+ const polyfillsFromConfig = new Set(options.polyfills);
120
+ const isNodePlatform = options.ssrOptions?.platform !== schema_1.ExperimentalPlatform.Neutral;
121
+ if (!(0, utils_1.isZonelessApp)(options.polyfills)) {
122
+ serverPolyfills.push(isNodePlatform ? 'zone.js/node' : 'zone.js');
123
+ }
124
+ if (polyfillsFromConfig.has('@angular/localize') ||
125
+ polyfillsFromConfig.has('@angular/localize/init')) {
126
+ serverPolyfills.push('@angular/localize/init');
127
+ }
128
+ serverPolyfills.push('@angular/platform-server/init');
129
+ const namespace = 'angular:polyfills-server';
130
+ const polyfillBundleOptions = getEsBuildCommonPolyfillsOptions({
131
+ ...options,
132
+ polyfills: serverPolyfills,
133
+ }, namespace, false, sourceFileCache);
134
+ if (!polyfillBundleOptions) {
135
+ return;
130
136
  }
131
- const zoneless = (0, utils_1.isZonelessApp)(polyfills);
132
137
  const buildOptions = {
133
- ...getEsBuildCommonOptions(options),
134
- platform: 'node',
135
- splitting: true,
138
+ ...polyfillBundleOptions,
139
+ platform: isNodePlatform ? 'node' : 'neutral',
136
140
  outExtension: { '.js': '.mjs' },
137
141
  // Note: `es2015` is needed for RxJS v6. If not specified, `module` would
138
142
  // match and the ES5 distribution would be bundled and ends up breaking at
@@ -140,14 +144,50 @@ function createServerCodeBundleOptions(options, target, sourceFileCache) {
140
144
  // More details: https://github.com/angular/angular-cli/issues/25405.
141
145
  mainFields: ['es2020', 'es2015', 'module', 'main'],
142
146
  entryNames: '[name]',
147
+ banner: isNodePlatform
148
+ ? {
149
+ js: [
150
+ // Note: Needed as esbuild does not provide require shims / proxy from ESModules.
151
+ // See: https://github.com/evanw/esbuild/issues/1921.
152
+ `import { createRequire } from 'node:module';`,
153
+ `globalThis['require'] ??= createRequire(import.meta.url);`,
154
+ ].join('\n'),
155
+ }
156
+ : undefined,
143
157
  target,
144
- banner: {
145
- js: `import './polyfills.server.mjs';`,
158
+ entryPoints: {
159
+ 'polyfills.server': namespace,
146
160
  },
161
+ };
162
+ buildOptions.plugins ??= [];
163
+ buildOptions.plugins.push((0, server_bundle_metadata_plugin_1.createServerBundleMetadata)());
164
+ return () => buildOptions;
165
+ }
166
+ function createServerMainCodeBundleOptions(options, target, sourceFileCache) {
167
+ const { serverEntryPoint: mainServerEntryPoint, workspaceRoot, outputMode, externalPackages, ssrOptions, polyfills, } = options;
168
+ (0, node_assert_1.default)(mainServerEntryPoint, 'createServerCodeBundleOptions should not be called without a defined serverEntryPoint.');
169
+ const { pluginOptions, styleOptions } = (0, compiler_plugin_options_1.createCompilerPluginOptions)(options, target, sourceFileCache);
170
+ const mainServerNamespace = 'angular:main-server';
171
+ const mainServerInjectPolyfillsNamespace = 'angular:main-server-inject-polyfills';
172
+ const mainServerInjectManifestNamespace = 'angular:main-server-inject-manifest';
173
+ const zoneless = (0, utils_1.isZonelessApp)(polyfills);
174
+ const entryPoints = {
175
+ 'main.server': mainServerNamespace,
176
+ };
177
+ const ssrEntryPoint = ssrOptions?.entry;
178
+ const isOldBehaviour = !outputMode;
179
+ if (ssrEntryPoint && isOldBehaviour) {
180
+ // Old behavior: 'server.ts' was bundled together with the SSR (Server-Side Rendering) code.
181
+ // This approach combined server-side logic and rendering into a single bundle.
182
+ entryPoints['server'] = ssrEntryPoint;
183
+ }
184
+ const buildOptions = {
185
+ ...getEsBuildServerCommonOptions(options),
186
+ target,
187
+ inject: [mainServerInjectPolyfillsNamespace, mainServerInjectManifestNamespace],
147
188
  entryPoints,
148
189
  supported: (0, utils_1.getFeatureSupport)(target, zoneless),
149
190
  plugins: [
150
- (0, loader_import_attribute_plugin_1.createLoaderImportAttributePlugin)(),
151
191
  (0, wasm_plugin_1.createWasmPlugin)({ allowAsync: zoneless, cache: sourceFileCache?.loadResultCache }),
152
192
  (0, sourcemap_ignorelist_plugin_1.createSourcemapIgnorelistPlugin)(),
153
193
  (0, compiler_plugin_1.createCompilerPlugin)(
@@ -164,20 +204,55 @@ function createServerCodeBundleOptions(options, target, sourceFileCache) {
164
204
  else {
165
205
  buildOptions.plugins.push((0, rxjs_esm_resolution_plugin_1.createRxjsEsmResolutionPlugin)());
166
206
  }
167
- buildOptions.plugins.push((0, virtual_module_plugin_1.createVirtualModulePlugin)({
207
+ // Mark manifest and polyfills file as external as these are generated by a different bundle step.
208
+ (buildOptions.external ??= []).push(...utils_1.SERVER_GENERATED_EXTERNALS);
209
+ const isNodePlatform = options.ssrOptions?.platform !== schema_1.ExperimentalPlatform.Neutral;
210
+ if (!isNodePlatform) {
211
+ // `@angular/platform-server` lazily depends on `xhr2` for XHR usage with the HTTP client.
212
+ // Since `xhr2` has Node.js dependencies, it cannot be used when targeting non-Node.js platforms.
213
+ // Note: The framework already issues a warning when using XHR with SSR.
214
+ buildOptions.external.push('xhr2');
215
+ }
216
+ buildOptions.plugins.push((0, server_bundle_metadata_plugin_1.createServerBundleMetadata)(), (0, virtual_module_plugin_1.createVirtualModulePlugin)({
217
+ namespace: mainServerInjectPolyfillsNamespace,
218
+ cache: sourceFileCache?.loadResultCache,
219
+ loadContent: () => ({
220
+ contents: `import './polyfills.server.mjs';`,
221
+ loader: 'js',
222
+ resolveDir: workspaceRoot,
223
+ }),
224
+ }), (0, virtual_module_plugin_1.createVirtualModulePlugin)({
225
+ namespace: mainServerInjectManifestNamespace,
226
+ cache: sourceFileCache?.loadResultCache,
227
+ loadContent: async () => {
228
+ const contents = [
229
+ // Configure `@angular/ssr` manifest.
230
+ `import manifest from './${manifest_1.SERVER_APP_MANIFEST_FILENAME}';`,
231
+ `import { ɵsetAngularAppManifest } from '@angular/ssr';`,
232
+ `ɵsetAngularAppManifest(manifest);`,
233
+ ];
234
+ return {
235
+ contents: contents.join('\n'),
236
+ loader: 'js',
237
+ resolveDir: workspaceRoot,
238
+ };
239
+ },
240
+ }), (0, virtual_module_plugin_1.createVirtualModulePlugin)({
168
241
  namespace: mainServerNamespace,
169
242
  cache: sourceFileCache?.loadResultCache,
170
243
  loadContent: async () => {
244
+ const mainServerEntryPointJsImport = entryFileToWorkspaceRelative(workspaceRoot, mainServerEntryPoint);
171
245
  const contents = [
172
- `export { ɵConsole } from '@angular/core';`,
173
- `export { renderApplication, renderModule, ɵSERVER_CONTEXT } from '@angular/platform-server';`,
246
+ // Re-export all symbols including default export from 'main.server.ts'
247
+ `export { default } from '${mainServerEntryPointJsImport}';`,
248
+ `export * from '${mainServerEntryPointJsImport}';`,
249
+ // Add @angular/ssr exports
250
+ `export {
251
+ ɵdestroyAngularServerApp,
252
+ ɵextractRoutesAndCreateRouteTree,
253
+ ɵgetOrCreateAngularServerApp,
254
+ } from '@angular/ssr';`,
174
255
  ];
175
- if (watch) {
176
- contents.push(`export { ɵresetCompiledComponents } from '@angular/core';`);
177
- }
178
- if (prerenderOptions?.discoverRoutes) {
179
- contents.push(`export { ɵgetRoutesFromAngularRouterConfig } from '@angular/ssr';`);
180
- }
181
256
  return {
182
257
  contents: contents.join('\n'),
183
258
  loader: 'js',
@@ -190,28 +265,117 @@ function createServerCodeBundleOptions(options, target, sourceFileCache) {
190
265
  }
191
266
  return buildOptions;
192
267
  }
193
- function createServerPolyfillBundleOptions(options, target, sourceFileCache) {
194
- const serverPolyfills = [];
195
- const polyfillsFromConfig = new Set(options.polyfills);
196
- if (!(0, utils_1.isZonelessApp)(options.polyfills)) {
197
- serverPolyfills.push('zone.js/node');
268
+ function createSsrEntryCodeBundleOptions(options, target, sourceFileCache) {
269
+ const { workspaceRoot, ssrOptions, externalPackages } = options;
270
+ const serverEntryPoint = ssrOptions?.entry;
271
+ (0, node_assert_1.default)(serverEntryPoint, 'createSsrEntryCodeBundleOptions should not be called without a defined serverEntryPoint.');
272
+ const { pluginOptions, styleOptions } = (0, compiler_plugin_options_1.createCompilerPluginOptions)(options, target, sourceFileCache);
273
+ const ssrEntryNamespace = 'angular:ssr-entry';
274
+ const ssrInjectManifestNamespace = 'angular:ssr-entry-inject-manifest';
275
+ const ssrInjectRequireNamespace = 'angular:ssr-entry-inject-require';
276
+ const isNodePlatform = options.ssrOptions?.platform !== schema_1.ExperimentalPlatform.Neutral;
277
+ const inject = [ssrInjectManifestNamespace];
278
+ if (isNodePlatform) {
279
+ inject.unshift(ssrInjectRequireNamespace);
198
280
  }
199
- if (polyfillsFromConfig.has('@angular/localize') ||
200
- polyfillsFromConfig.has('@angular/localize/init')) {
201
- serverPolyfills.push('@angular/localize/init');
281
+ const buildOptions = {
282
+ ...getEsBuildServerCommonOptions(options),
283
+ target,
284
+ entryPoints: {
285
+ // TODO: consider renaming to index
286
+ 'server': ssrEntryNamespace,
287
+ },
288
+ supported: (0, utils_1.getFeatureSupport)(target, true),
289
+ plugins: [
290
+ (0, sourcemap_ignorelist_plugin_1.createSourcemapIgnorelistPlugin)(),
291
+ (0, compiler_plugin_1.createCompilerPlugin)(
292
+ // JS/TS options
293
+ { ...pluginOptions, noopTypeScriptCompilation: true },
294
+ // Component stylesheet options
295
+ styleOptions),
296
+ ],
297
+ inject,
298
+ };
299
+ buildOptions.plugins ??= [];
300
+ if (externalPackages) {
301
+ buildOptions.packages = 'external';
202
302
  }
203
- serverPolyfills.push('@angular/platform-server/init');
204
- const namespace = 'angular:polyfills-server';
205
- const polyfillBundleOptions = getEsBuildCommonPolyfillsOptions({
206
- ...options,
207
- polyfills: serverPolyfills,
208
- }, namespace, false, sourceFileCache);
209
- if (!polyfillBundleOptions) {
210
- return;
303
+ else {
304
+ buildOptions.plugins.push((0, rxjs_esm_resolution_plugin_1.createRxjsEsmResolutionPlugin)());
211
305
  }
212
- const buildOptions = {
213
- ...polyfillBundleOptions,
214
- platform: 'node',
306
+ // Mark manifest file as external. As this will be generated later on.
307
+ (buildOptions.external ??= []).push('*/main.server.mjs', ...utils_1.SERVER_GENERATED_EXTERNALS);
308
+ if (!isNodePlatform) {
309
+ // `@angular/platform-server` lazily depends on `xhr2` for XHR usage with the HTTP client.
310
+ // Since `xhr2` has Node.js dependencies, it cannot be used when targeting non-Node.js platforms.
311
+ // Note: The framework already issues a warning when using XHR with SSR.
312
+ buildOptions.external.push('xhr2');
313
+ }
314
+ buildOptions.plugins.push((0, server_bundle_metadata_plugin_1.createServerBundleMetadata)({ ssrEntryBundle: true }), (0, virtual_module_plugin_1.createVirtualModulePlugin)({
315
+ namespace: ssrInjectRequireNamespace,
316
+ cache: sourceFileCache?.loadResultCache,
317
+ loadContent: () => {
318
+ const contents = [
319
+ // Note: Needed as esbuild does not provide require shims / proxy from ESModules.
320
+ // See: https://github.com/evanw/esbuild/issues/1921.
321
+ `import { createRequire } from 'node:module';`,
322
+ `globalThis['require'] ??= createRequire(import.meta.url);`,
323
+ ];
324
+ return {
325
+ contents: contents.join('\n'),
326
+ loader: 'js',
327
+ resolveDir: workspaceRoot,
328
+ };
329
+ },
330
+ }), (0, virtual_module_plugin_1.createVirtualModulePlugin)({
331
+ namespace: ssrInjectManifestNamespace,
332
+ cache: sourceFileCache?.loadResultCache,
333
+ loadContent: () => {
334
+ const contents = [
335
+ // Configure `@angular/ssr` app engine manifest.
336
+ `import manifest from './${manifest_1.SERVER_APP_ENGINE_MANIFEST_FILENAME}';`,
337
+ `import { ɵsetAngularAppEngineManifest } from '@angular/ssr';`,
338
+ `ɵsetAngularAppEngineManifest(manifest);`,
339
+ ];
340
+ return {
341
+ contents: contents.join('\n'),
342
+ loader: 'js',
343
+ resolveDir: workspaceRoot,
344
+ };
345
+ },
346
+ }), (0, virtual_module_plugin_1.createVirtualModulePlugin)({
347
+ namespace: ssrEntryNamespace,
348
+ cache: sourceFileCache?.loadResultCache,
349
+ loadContent: () => {
350
+ const serverEntryPointJsImport = entryFileToWorkspaceRelative(workspaceRoot, serverEntryPoint);
351
+ const contents = [
352
+ // Re-export all symbols including default export
353
+ `import * as server from '${serverEntryPointJsImport}';`,
354
+ `export * from '${serverEntryPointJsImport}';`,
355
+ // The below is needed to avoid
356
+ // `Import "default" will always be undefined because there is no matching export` warning when no default is present.
357
+ `const defaultExportName = 'default';`,
358
+ `export default server[defaultExportName]`,
359
+ // Add @angular/ssr exports
360
+ `export { AngularAppEngine } from '@angular/ssr';`,
361
+ ];
362
+ return {
363
+ contents: contents.join('\n'),
364
+ loader: 'js',
365
+ resolveDir: workspaceRoot,
366
+ };
367
+ },
368
+ }));
369
+ if (options.plugins) {
370
+ buildOptions.plugins.push(...options.plugins);
371
+ }
372
+ return buildOptions;
373
+ }
374
+ function getEsBuildServerCommonOptions(options) {
375
+ const isNodePlatform = options.ssrOptions?.platform !== schema_1.ExperimentalPlatform.Neutral;
376
+ return {
377
+ ...getEsBuildCommonOptions(options),
378
+ platform: isNodePlatform ? 'node' : 'neutral',
215
379
  outExtension: { '.js': '.mjs' },
216
380
  // Note: `es2015` is needed for RxJS v6. If not specified, `module` would
217
381
  // match and the ES5 distribution would be bundled and ends up breaking at
@@ -219,31 +383,18 @@ function createServerPolyfillBundleOptions(options, target, sourceFileCache) {
219
383
  // More details: https://github.com/angular/angular-cli/issues/25405.
220
384
  mainFields: ['es2020', 'es2015', 'module', 'main'],
221
385
  entryNames: '[name]',
222
- banner: {
223
- js: [
224
- // Note: Needed as esbuild does not provide require shims / proxy from ESModules.
225
- // See: https://github.com/evanw/esbuild/issues/1921.
226
- `import { createRequire } from 'node:module';`,
227
- `globalThis['require'] ??= createRequire(import.meta.url);`,
228
- ].join('\n'),
229
- },
230
- target,
231
- entryPoints: {
232
- 'polyfills.server': namespace,
233
- },
234
386
  };
235
- return () => buildOptions;
236
387
  }
237
388
  function getEsBuildCommonOptions(options) {
238
- const { workspaceRoot, outExtension, optimizationOptions, sourcemapOptions, tsconfig, externalDependencies, outputNames, preserveSymlinks, jit, loaderExtensions, jsonLogs, } = options;
389
+ const { workspaceRoot, outExtension, optimizationOptions, sourcemapOptions, tsconfig, externalDependencies, outputNames, preserveSymlinks, jit, loaderExtensions, jsonLogs, i18nOptions, } = options;
239
390
  // Ensure unique hashes for i18n translation changes when using post-process inlining.
240
391
  // This hash value is added as a footer to each file and ensures that the output file names (with hashes)
241
392
  // change when translation files have changed. If this is not done the post processed files may have
242
393
  // different content but would retain identical production file names which would lead to browser caching problems.
243
394
  let footer;
244
- if (options.i18nOptions.shouldInline) {
395
+ if (i18nOptions.shouldInline) {
245
396
  // Update file hashes to include translation file content
246
- const i18nHash = Object.values(options.i18nOptions.locales).reduce((data, locale) => data + locale.files.map((file) => file.integrity || '').join('|'), '');
397
+ const i18nHash = Object.values(i18nOptions.locales).reduce((data, locale) => data + locale.files.map((file) => file.integrity || '').join('|'), '');
247
398
  footer = { js: `/**i18n:${(0, node_crypto_1.createHash)('sha256').update(i18nHash).digest('hex')}*/` };
248
399
  }
249
400
  return {
@@ -252,7 +403,12 @@ function getEsBuildCommonOptions(options) {
252
403
  bundle: true,
253
404
  packages: 'bundle',
254
405
  assetNames: outputNames.media,
255
- conditions: ['es2020', 'es2015', 'module'],
406
+ conditions: [
407
+ 'es2020',
408
+ 'es2015',
409
+ 'module',
410
+ optimizationOptions.scripts ? 'production' : 'development',
411
+ ],
256
412
  resolveExtensions: ['.ts', '.tsx', '.mjs', '.js', '.cjs'],
257
413
  metafile: true,
258
414
  legalComments: options.extractLicenses ? 'none' : 'eof',
@@ -267,7 +423,7 @@ function getEsBuildCommonOptions(options) {
267
423
  splitting: true,
268
424
  chunkNames: options.namedChunks ? '[name]-[hash]' : 'chunk-[hash]',
269
425
  tsconfig,
270
- external: externalDependencies,
426
+ external: externalDependencies ? [...externalDependencies] : undefined,
271
427
  write: false,
272
428
  preserveSymlinks,
273
429
  define: {
@@ -360,3 +516,9 @@ function getEsBuildCommonPolyfillsOptions(options, namespace, tryToResolvePolyfi
360
516
  }));
361
517
  return buildOptions;
362
518
  }
519
+ function entryFileToWorkspaceRelative(workspaceRoot, entryFile) {
520
+ return ('./' +
521
+ (0, node_path_1.relative)(workspaceRoot, entryFile)
522
+ .replace(/.[mc]?ts$/, '')
523
+ .replace(/\\/g, '/'));
524
+ }
@@ -28,7 +28,7 @@ function generateBudgetStats(metafile, outputFiles, initialFiles) {
28
28
  continue;
29
29
  }
30
30
  // Exclude server bundles
31
- if (type === bundler_context_1.BuildOutputFileType.Server) {
31
+ if (type === bundler_context_1.BuildOutputFileType.ServerApplication || type === bundler_context_1.BuildOutputFileType.ServerRoot) {
32
32
  continue;
33
33
  }
34
34
  const initialRecord = initialFiles.get(file);
@@ -31,9 +31,10 @@ export interface InitialFileRecord {
31
31
  depth: number;
32
32
  }
33
33
  export declare enum BuildOutputFileType {
34
- Browser = 1,
35
- Media = 2,
36
- Server = 3,
34
+ Browser = 0,
35
+ Media = 1,
36
+ ServerApplication = 2,
37
+ ServerRoot = 3,
37
38
  Root = 4
38
39
  }
39
40
  export interface BuildOutputFile extends OutputFile {
@@ -18,9 +18,10 @@ const load_result_cache_1 = require("./load-result-cache");
18
18
  const utils_1 = require("./utils");
19
19
  var BuildOutputFileType;
20
20
  (function (BuildOutputFileType) {
21
- BuildOutputFileType[BuildOutputFileType["Browser"] = 1] = "Browser";
22
- BuildOutputFileType[BuildOutputFileType["Media"] = 2] = "Media";
23
- BuildOutputFileType[BuildOutputFileType["Server"] = 3] = "Server";
21
+ BuildOutputFileType[BuildOutputFileType["Browser"] = 0] = "Browser";
22
+ BuildOutputFileType[BuildOutputFileType["Media"] = 1] = "Media";
23
+ BuildOutputFileType[BuildOutputFileType["ServerApplication"] = 2] = "ServerApplication";
24
+ BuildOutputFileType[BuildOutputFileType["ServerRoot"] = 3] = "ServerRoot";
24
25
  BuildOutputFileType[BuildOutputFileType["Root"] = 4] = "Root";
25
26
  })(BuildOutputFileType || (exports.BuildOutputFileType = BuildOutputFileType = {}));
26
27
  /**
@@ -138,6 +139,7 @@ class BundlerContext {
138
139
  }
139
140
  return result;
140
141
  }
142
+ // eslint-disable-next-line max-lines-per-function
141
143
  async #performBundle() {
142
144
  // Create esbuild options if not present
143
145
  if (this.#esbuildOptions === undefined) {
@@ -165,12 +167,6 @@ class BundlerContext {
165
167
  // For non-incremental builds, perform a single build
166
168
  result = await (0, esbuild_1.build)(this.#esbuildOptions);
167
169
  }
168
- if (this.#platformIsServer) {
169
- for (const entry of Object.values(result.metafile.outputs)) {
170
- // eslint-disable-next-line @typescript-eslint/no-explicit-any
171
- entry['ng-platform-server'] = true;
172
- }
173
- }
174
170
  }
175
171
  catch (failure) {
176
172
  // Build failures will throw an exception which contains errors/warnings
@@ -215,6 +211,7 @@ class BundlerContext {
215
211
  warnings: result.warnings,
216
212
  };
217
213
  }
214
+ const { 'ng-platform-server': isPlatformServer = false, 'ng-ssr-entry-bundle': isSsrEntryBundle = false, } = result.metafile;
218
215
  // Find all initial files
219
216
  const initialFiles = new Map();
220
217
  for (const outputFile of result.outputFiles) {
@@ -235,7 +232,7 @@ class BundlerContext {
235
232
  name,
236
233
  type,
237
234
  entrypoint: true,
238
- serverFile: this.#platformIsServer,
235
+ serverFile: isPlatformServer,
239
236
  depth: 0,
240
237
  };
241
238
  if (!this.initialFilter || this.initialFilter(record)) {
@@ -263,7 +260,7 @@ class BundlerContext {
263
260
  type: initialImport.kind === 'import-rule' ? 'style' : 'script',
264
261
  entrypoint: false,
265
262
  external: initialImport.external,
266
- serverFile: this.#platformIsServer,
263
+ serverFile: isPlatformServer,
267
264
  depth: entryRecord.depth + 1,
268
265
  };
269
266
  if (!this.initialFilter || this.initialFilter(record)) {
@@ -280,6 +277,7 @@ class BundlerContext {
280
277
  for (const { imports } of Object.values(result.metafile.outputs)) {
281
278
  for (const importData of imports) {
282
279
  if (!importData.external ||
280
+ utils_1.SERVER_GENERATED_EXTERNALS.has(importData.path) ||
283
281
  (importData.kind !== 'import-statement' &&
284
282
  importData.kind !== 'dynamic-import' &&
285
283
  importData.kind !== 'require-call')) {
@@ -295,22 +293,32 @@ class BundlerContext {
295
293
  if (!/\.([cm]?js|css|wasm)(\.map)?$/i.test(file.path)) {
296
294
  fileType = BuildOutputFileType.Media;
297
295
  }
296
+ else if (isPlatformServer) {
297
+ fileType = isSsrEntryBundle
298
+ ? BuildOutputFileType.ServerRoot
299
+ : BuildOutputFileType.ServerApplication;
300
+ }
298
301
  else {
299
- fileType = this.#platformIsServer
300
- ? BuildOutputFileType.Server
301
- : BuildOutputFileType.Browser;
302
+ fileType = BuildOutputFileType.Browser;
302
303
  }
303
304
  return (0, utils_1.convertOutputFile)(file, fileType);
304
305
  });
306
+ let externalConfiguration = this.#esbuildOptions.external;
307
+ if (isPlatformServer && externalConfiguration) {
308
+ externalConfiguration = externalConfiguration.filter((dep) => !utils_1.SERVER_GENERATED_EXTERNALS.has(dep));
309
+ if (!externalConfiguration.length) {
310
+ externalConfiguration = undefined;
311
+ }
312
+ }
305
313
  // Return the successful build results
306
314
  return {
307
315
  ...result,
308
316
  outputFiles,
309
317
  initialFiles,
310
318
  externalImports: {
311
- [this.#platformIsServer ? 'server' : 'browser']: externalImports,
319
+ [isPlatformServer ? 'server' : 'browser']: externalImports,
312
320
  },
313
- externalConfiguration: this.#esbuildOptions.external,
321
+ externalConfiguration,
314
322
  errors: undefined,
315
323
  };
316
324
  }
@@ -328,9 +336,6 @@ class BundlerContext {
328
336
  }
329
337
  }
330
338
  }
331
- get #platformIsServer() {
332
- return this.#esbuildOptions?.platform === 'node';
333
- }
334
339
  /**
335
340
  * Invalidate a stored bundler result based on the previous watch files
336
341
  * and a list of changed files.
@@ -24,6 +24,9 @@ export interface ExternalResultMetadata {
24
24
  implicitServer: string[];
25
25
  explicit: string[];
26
26
  }
27
+ export type PrerenderedRoutesRecord = Record<string, {
28
+ headers?: Record<string, string>;
29
+ }>;
27
30
  /**
28
31
  * Represents the result of a single builder execute call.
29
32
  */
@@ -33,7 +36,7 @@ export declare class ExecutionResult {
33
36
  outputFiles: BuildOutputFile[];
34
37
  assetFiles: BuildOutputAsset[];
35
38
  errors: (Message | PartialMessage)[];
36
- prerenderedRoutes: string[];
39
+ prerenderedRoutes: PrerenderedRoutesRecord;
37
40
  warnings: (Message | PartialMessage)[];
38
41
  logs: string[];
39
42
  externalMetadata?: ExternalResultMetadata;
@@ -46,7 +49,7 @@ export declare class ExecutionResult {
46
49
  addLog(value: string): void;
47
50
  addError(error: PartialMessage | string): void;
48
51
  addErrors(errors: (PartialMessage | string)[]): void;
49
- addPrerenderedRoutes(routes: string[]): void;
52
+ addPrerenderedRoutes(routes: PrerenderedRoutesRecord): void;
50
53
  addWarning(error: PartialMessage | string): void;
51
54
  addWarnings(errors: (PartialMessage | string)[]): void;
52
55
  /**
@@ -19,7 +19,7 @@ class ExecutionResult {
19
19
  outputFiles = [];
20
20
  assetFiles = [];
21
21
  errors = [];
22
- prerenderedRoutes = [];
22
+ prerenderedRoutes = {};
23
23
  warnings = [];
24
24
  logs = [];
25
25
  externalMetadata;
@@ -53,9 +53,13 @@ class ExecutionResult {
53
53
  }
54
54
  }
55
55
  addPrerenderedRoutes(routes) {
56
- this.prerenderedRoutes.push(...routes);
56
+ Object.assign(this.prerenderedRoutes, routes);
57
57
  // Sort the prerendered routes.
58
- this.prerenderedRoutes.sort((a, b) => a.localeCompare(b));
58
+ const sortedObj = {};
59
+ for (const key of Object.keys(this.prerenderedRoutes).sort()) {
60
+ sortedObj[key] = this.prerenderedRoutes[key];
61
+ }
62
+ this.prerenderedRoutes = sortedObj;
59
63
  }
60
64
  addWarning(error) {
61
65
  if (typeof error === 'string') {
@@ -84,5 +84,10 @@ export declare class MemoryCache<V> extends Cache<V, Map<string, V>> {
84
84
  * Provides all the values currently present in the cache instance.
85
85
  * @returns An iterable of all values in the cache.
86
86
  */
87
- values(): IterableIterator<V>;
87
+ values(): MapIterator<V>;
88
+ /**
89
+ * Provides all the keys/values currently present in the cache instance.
90
+ * @returns An iterable of all key/value pairs in the cache.
91
+ */
92
+ entries(): MapIterator<[string, V]>;
88
93
  }
@@ -88,5 +88,12 @@ class MemoryCache extends Cache {
88
88
  values() {
89
89
  return this.store.values();
90
90
  }
91
+ /**
92
+ * Provides all the keys/values currently present in the cache instance.
93
+ * @returns An iterable of all key/value pairs in the cache.
94
+ */
95
+ entries() {
96
+ return this.store.entries();
97
+ }
91
98
  }
92
99
  exports.MemoryCache = MemoryCache;
@@ -9,7 +9,7 @@
9
9
  Object.defineProperty(exports, "__esModule", { value: true });
10
10
  exports.createCompilerPluginOptions = createCompilerPluginOptions;
11
11
  function createCompilerPluginOptions(options, target, sourceFileCache) {
12
- const { workspaceRoot, optimizationOptions, sourcemapOptions, tsconfig, outputNames, fileReplacements, externalDependencies, preserveSymlinks, stylePreprocessorOptions, advancedOptimizations, inlineStyleLanguage, jit, cacheOptions, tailwindConfiguration, postcssConfiguration, publicPath, } = options;
12
+ const { workspaceRoot, optimizationOptions, sourcemapOptions, tsconfig, outputNames, fileReplacements, externalDependencies, preserveSymlinks, stylePreprocessorOptions, advancedOptimizations, inlineStyleLanguage, jit, cacheOptions, tailwindConfiguration, postcssConfiguration, publicPath, externalRuntimeStyles, instrumentForCoverage, } = options;
13
13
  return {
14
14
  // JS/TS options
15
15
  pluginOptions: {
@@ -22,6 +22,8 @@ function createCompilerPluginOptions(options, target, sourceFileCache) {
22
22
  sourceFileCache,
23
23
  loadResultCache: sourceFileCache?.loadResultCache,
24
24
  incremental: !!options.watch,
25
+ externalRuntimeStyles,
26
+ instrumentForCoverage,
25
27
  },
26
28
  // Component stylesheet options
27
29
  styleOptions: {
@@ -35,6 +37,9 @@ function createCompilerPluginOptions(options, target, sourceFileCache) {
35
37
  sourcemapOptions.styles && !sourcemapOptions.hidden ? 'linked' : false,
36
38
  outputNames,
37
39
  includePaths: stylePreprocessorOptions?.includePaths,
40
+ // string[] | undefined' is not assignable to type '(Version | DeprecationOrId)[] | undefined'.
41
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
42
+ sass: stylePreprocessorOptions?.sass,
38
43
  externalDependencies,
39
44
  target,
40
45
  inlineStyleLanguage,
@@ -72,7 +72,7 @@ function createGlobalScriptsBundleOptions(options, target, initial) {
72
72
  entryNames: initial ? outputNames.bundles : '[name]',
73
73
  assetNames: outputNames.media,
74
74
  mainFields: ['script', 'browser', 'main'],
75
- conditions: ['script'],
75
+ conditions: ['script', optimizationOptions.scripts ? 'production' : 'development'],
76
76
  resolveExtensions: ['.mjs', '.js', '.cjs'],
77
77
  logLevel: options.verbose && !jsonLogs ? 'debug' : 'silent',
78
78
  metafile: true,