@angular/build 19.0.0-next.5 → 19.0.0-next.7

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 (28) hide show
  1. package/package.json +8 -8
  2. package/src/tools/angular/compilation/parallel-compilation.js +2 -15
  3. package/src/tools/esbuild/application-code-bundle.js +0 -1
  4. package/src/tools/esbuild/i18n-inliner.js +2 -3
  5. package/src/tools/esbuild/javascript-transformer.js +2 -15
  6. package/src/tools/sass/sass-service.js +2 -15
  7. package/src/tools/vite/angular-memory-plugin.js +1 -0
  8. package/src/tools/vite/middlewares/assets-middleware.js +6 -3
  9. package/src/tools/vite/middlewares/headers-middleware.d.ts +19 -0
  10. package/src/tools/vite/middlewares/headers-middleware.js +34 -0
  11. package/src/tools/vite/middlewares/html-fallback-middleware.d.ts +1 -1
  12. package/src/tools/vite/middlewares/html-fallback-middleware.js +1 -1
  13. package/src/tools/vite/middlewares/index-html-middleware.js +1 -2
  14. package/src/tools/vite/middlewares/index.d.ts +1 -0
  15. package/src/tools/vite/middlewares/index.js +3 -1
  16. package/src/tools/vite/middlewares/ssr-middleware.js +1 -3
  17. package/src/tools/vite/utils.d.ts +0 -3
  18. package/src/tools/vite/utils.js +0 -12
  19. package/src/utils/normalize-cache.js +1 -1
  20. package/src/utils/server-rendering/load-esm-from-memory.d.ts +1 -2
  21. package/src/utils/server-rendering/prerender.d.ts +1 -1
  22. package/src/utils/server-rendering/prerender.js +6 -11
  23. package/src/utils/server-rendering/render-worker.d.ts +1 -2
  24. package/src/utils/server-rendering/render-worker.js +3 -5
  25. package/src/utils/server-rendering/routes-extractor-worker.d.ts +5 -1
  26. package/src/utils/server-rendering/routes-extractor-worker.js +7 -2
  27. package/src/utils/worker-pool.d.ts +12 -0
  28. package/src/utils/worker-pool.js +43 -0
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@angular/build",
3
- "version": "19.0.0-next.5",
3
+ "version": "19.0.0-next.7",
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.5",
26
+ "@angular-devkit/architect": "0.1900.0-next.7",
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
30
  "@babel/plugin-syntax-import-attributes": "7.25.6",
31
- "@inquirer/confirm": "3.2.0",
31
+ "@inquirer/confirm": "4.0.1",
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.1.0",
39
+ "lmdb": "3.1.2",
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
- "piscina": "4.6.1",
44
+ "piscina": "4.7.0",
45
45
  "rollup": "4.21.3",
46
- "sass": "1.78.0",
46
+ "sass": "1.79.1",
47
47
  "semver": "7.6.3",
48
- "vite": "5.4.4",
48
+ "vite": "5.4.6",
49
49
  "watchpack": "2.4.2"
50
50
  },
51
51
  "peerDependencies": {
@@ -54,7 +54,7 @@
54
54
  "@angular/localize": "^19.0.0-next.0",
55
55
  "@angular/platform-server": "^19.0.0-next.0",
56
56
  "@angular/service-worker": "^19.0.0-next.0",
57
- "@angular/ssr": "^19.0.0-next.5",
57
+ "@angular/ssr": "^19.0.0-next.7",
58
58
  "less": "^4.2.0",
59
59
  "postcss": "^8.4.0",
60
60
  "tailwindcss": "^2.0.0 || ^3.0.0",
@@ -6,14 +6,11 @@
6
6
  * Use of this source code is governed by an MIT-style license that can be
7
7
  * found in the LICENSE file at https://angular.dev/license
8
8
  */
9
- var __importDefault = (this && this.__importDefault) || function (mod) {
10
- return (mod && mod.__esModule) ? mod : { "default": mod };
11
- };
12
9
  Object.defineProperty(exports, "__esModule", { value: true });
13
10
  exports.ParallelCompilation = void 0;
14
11
  const node_module_1 = require("node:module");
15
12
  const node_worker_threads_1 = require("node:worker_threads");
16
- const piscina_1 = __importDefault(require("piscina"));
13
+ const worker_pool_1 = require("../../../utils/worker-pool");
17
14
  const angular_compilation_1 = require("./angular-compilation");
18
15
  /**
19
16
  * An Angular compilation which uses a Node.js Worker thread to load and execute
@@ -31,20 +28,10 @@ class ParallelCompilation extends angular_compilation_1.AngularCompilation {
31
28
  this.jit = jit;
32
29
  // TODO: Convert to import.meta usage during ESM transition
33
30
  const localRequire = (0, node_module_1.createRequire)(__filename);
34
- this.#worker = new piscina_1.default({
35
- minThreads: 1,
31
+ this.#worker = new worker_pool_1.WorkerPool({
36
32
  maxThreads: 1,
37
33
  idleTimeout: Infinity,
38
- // Web containers do not support transferable objects with receiveOnMessagePort which
39
- // is used when the Atomics based wait loop is enable.
40
- useAtomics: !process.versions.webcontainer,
41
34
  filename: localRequire.resolve('./parallel-worker'),
42
- recordTiming: false,
43
- env: {
44
- ...process.env,
45
- // Enable compile code caching if enabled for the main process (only exists on Node.js v22.8+)
46
- 'NODE_COMPILE_CACHE': (0, node_module_1.getCompileCacheDir)?.(),
47
- },
48
35
  });
49
36
  }
50
37
  initialize(tsconfig, hostOptions, compilerOptionsTransformer) {
@@ -232,7 +232,6 @@ function createServerMainCodeBundleOptions(options, target, sourceFileCache) {
232
232
  `export * from '${mainServerEntryPointJsImport}';`,
233
233
  // Add @angular/ssr exports
234
234
  `export {
235
- ɵServerRenderContext,
236
235
  ɵdestroyAngularServerApp,
237
236
  ɵextractRoutesAndCreateRouteTree,
238
237
  ɵgetOrCreateAngularServerApp,
@@ -12,7 +12,7 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
12
12
  Object.defineProperty(exports, "__esModule", { value: true });
13
13
  exports.I18nInliner = void 0;
14
14
  const node_assert_1 = __importDefault(require("node:assert"));
15
- const piscina_1 = __importDefault(require("piscina"));
15
+ const worker_pool_1 = require("../../utils/worker-pool");
16
16
  const bundler_context_1 = require("./bundler-context");
17
17
  const utils_1 = require("./utils");
18
18
  /**
@@ -74,7 +74,7 @@ class I18nInliner {
74
74
  }
75
75
  }
76
76
  this.#localizeFiles = files;
77
- this.#workerPool = new piscina_1.default({
77
+ this.#workerPool = new worker_pool_1.WorkerPool({
78
78
  filename: require.resolve('./i18n-inliner-worker'),
79
79
  maxThreads,
80
80
  // Extract options to ensure only the named options are serialized and sent to the worker
@@ -83,7 +83,6 @@ class I18nInliner {
83
83
  shouldOptimize: options.shouldOptimize,
84
84
  files,
85
85
  },
86
- recordTiming: false,
87
86
  });
88
87
  }
89
88
  /**
@@ -6,15 +6,11 @@
6
6
  * Use of this source code is governed by an MIT-style license that can be
7
7
  * found in the LICENSE file at https://angular.dev/license
8
8
  */
9
- var __importDefault = (this && this.__importDefault) || function (mod) {
10
- return (mod && mod.__esModule) ? mod : { "default": mod };
11
- };
12
9
  Object.defineProperty(exports, "__esModule", { value: true });
13
10
  exports.JavaScriptTransformer = void 0;
14
11
  const node_crypto_1 = require("node:crypto");
15
12
  const promises_1 = require("node:fs/promises");
16
- const node_module_1 = require("node:module");
17
- const piscina_1 = __importDefault(require("piscina"));
13
+ const worker_pool_1 = require("../../utils/worker-pool");
18
14
  /**
19
15
  * A class that performs transformation of JavaScript files and raw data.
20
16
  * A worker pool is used to distribute the transformation actions and allow
@@ -42,18 +38,9 @@ class JavaScriptTransformer {
42
38
  this.#fileCacheKeyBase = Buffer.from(JSON.stringify(this.#commonOptions), 'utf-8');
43
39
  }
44
40
  #ensureWorkerPool() {
45
- this.#workerPool ??= new piscina_1.default({
41
+ this.#workerPool ??= new worker_pool_1.WorkerPool({
46
42
  filename: require.resolve('./javascript-transformer-worker'),
47
- minThreads: 1,
48
43
  maxThreads: this.maxThreads,
49
- // Shutdown idle threads after 1 second of inactivity
50
- idleTimeout: 1000,
51
- recordTiming: false,
52
- env: {
53
- ...process.env,
54
- // Enable compile code caching if enabled for the main process (only exists on Node.js v22.8+)
55
- 'NODE_COMPILE_CACHE': (0, node_module_1.getCompileCacheDir)?.(),
56
- },
57
44
  });
58
45
  return this.#workerPool;
59
46
  }
@@ -64,11 +64,10 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
64
64
  Object.defineProperty(exports, "__esModule", { value: true });
65
65
  exports.SassWorkerImplementation = void 0;
66
66
  const node_assert_1 = __importDefault(require("node:assert"));
67
- const node_module_1 = require("node:module");
68
67
  const node_url_1 = require("node:url");
69
68
  const node_worker_threads_1 = require("node:worker_threads");
70
- const piscina_1 = require("piscina");
71
69
  const environment_options_1 = require("../../utils/environment-options");
70
+ const worker_pool_1 = require("../../utils/worker-pool");
72
71
  // Polyfill Symbol.dispose if not present
73
72
  // eslint-disable-next-line @typescript-eslint/no-explicit-any
74
73
  Symbol.dispose ??= Symbol('Symbol Dispose');
@@ -91,21 +90,9 @@ class SassWorkerImplementation {
91
90
  this.maxThreads = maxThreads;
92
91
  }
93
92
  #ensureWorkerPool() {
94
- this.#workerPool ??= new piscina_1.Piscina({
93
+ this.#workerPool ??= new worker_pool_1.WorkerPool({
95
94
  filename: require.resolve('./worker'),
96
- minThreads: 1,
97
95
  maxThreads: this.maxThreads,
98
- // Web containers do not support transferable objects with receiveOnMessagePort which
99
- // is used when the Atomics based wait loop is enable.
100
- useAtomics: !process.versions.webcontainer,
101
- // Shutdown idle threads after 1 second of inactivity
102
- idleTimeout: 1000,
103
- recordTiming: false,
104
- env: {
105
- ...process.env,
106
- // Enable compile code caching if enabled for the main process (only exists on Node.js v22.8+)
107
- 'NODE_COMPILE_CACHE': (0, node_module_1.getCompileCacheDir)?.(),
108
- },
109
96
  });
110
97
  return this.#workerPool;
111
98
  }
@@ -74,6 +74,7 @@ function createAngularMemoryPlugin(options) {
74
74
  map: remappedMap,
75
75
  };
76
76
  };
77
+ server.middlewares.use((0, middlewares_1.createAngularHeadersMiddleware)(server));
77
78
  // Assets and resources get handled first
78
79
  server.middlewares.use((0, middlewares_1.createAngularAssetsMiddleware)(server, assets, outputFiles, usedComponentStyles));
79
80
  if (extensionMiddleware?.length) {
@@ -14,7 +14,7 @@ const load_esm_1 = require("../../../utils/load-esm");
14
14
  const utils_1 = require("../utils");
15
15
  const COMPONENT_REGEX = /%COMP%/g;
16
16
  function createAngularAssetsMiddleware(server, assets, outputFiles, usedComponentStyles) {
17
- return function (req, res, next) {
17
+ return function angularAssetsMiddleware(req, res, next) {
18
18
  if (req.url === undefined || res.writableEnded) {
19
19
  return;
20
20
  }
@@ -49,6 +49,11 @@ function createAngularAssetsMiddleware(server, assets, outputFiles, usedComponen
49
49
  next();
50
50
  return;
51
51
  }
52
+ // Support HTTP HEAD requests for the virtual output files from the Angular build
53
+ if (req.method === 'HEAD' && outputFiles.get(pathname)?.servable) {
54
+ // While a GET will also generate content, the rest of the response is equivalent
55
+ req.method = 'GET';
56
+ }
52
57
  // Resource files are handled directly.
53
58
  // Global stylesheets (CSS files) are currently considered resources to workaround
54
59
  // dev server sourcemap issues with stylesheets.
@@ -79,7 +84,6 @@ function createAngularAssetsMiddleware(server, assets, outputFiles, usedComponen
79
84
  .replaceAll(COMPONENT_REGEX, componentId);
80
85
  res.setHeader('Content-Type', 'text/css');
81
86
  res.setHeader('Cache-Control', 'no-cache');
82
- (0, utils_1.appendServerConfiguredHeaders)(server, res);
83
87
  res.end(encapsulatedData);
84
88
  })
85
89
  .catch((e) => next(e));
@@ -97,7 +101,6 @@ function createAngularAssetsMiddleware(server, assets, outputFiles, usedComponen
97
101
  res.setHeader('Content-Type', mimeType);
98
102
  }
99
103
  res.setHeader('Cache-Control', 'no-cache');
100
- (0, utils_1.appendServerConfiguredHeaders)(server, res);
101
104
  res.end(data);
102
105
  return;
103
106
  }
@@ -0,0 +1,19 @@
1
+ /**
2
+ * @license
3
+ * Copyright Google LLC All Rights Reserved.
4
+ *
5
+ * Use of this source code is governed by an MIT-style license that can be
6
+ * found in the LICENSE file at https://angular.dev/license
7
+ */
8
+ import type { Connect, ViteDevServer } from 'vite';
9
+ /**
10
+ * Creates a middleware for adding custom headers.
11
+ *
12
+ * This middleware is responsible for setting HTTP headers as configured in the Vite server options.
13
+ * If headers are defined in the server configuration, they are applied to the server response.
14
+ *
15
+ * @param server - The instance of `ViteDevServer` containing the configuration, including custom headers.
16
+ * @returns A middleware function that processes the incoming request, sets headers if available,
17
+ * and passes control to the next middleware in the chain.
18
+ */
19
+ export declare function createAngularHeadersMiddleware(server: ViteDevServer): Connect.NextHandleFunction;
@@ -0,0 +1,34 @@
1
+ "use strict";
2
+ /**
3
+ * @license
4
+ * Copyright Google LLC All Rights Reserved.
5
+ *
6
+ * Use of this source code is governed by an MIT-style license that can be
7
+ * found in the LICENSE file at https://angular.dev/license
8
+ */
9
+ Object.defineProperty(exports, "__esModule", { value: true });
10
+ exports.createAngularHeadersMiddleware = createAngularHeadersMiddleware;
11
+ /**
12
+ * Creates a middleware for adding custom headers.
13
+ *
14
+ * This middleware is responsible for setting HTTP headers as configured in the Vite server options.
15
+ * If headers are defined in the server configuration, they are applied to the server response.
16
+ *
17
+ * @param server - The instance of `ViteDevServer` containing the configuration, including custom headers.
18
+ * @returns A middleware function that processes the incoming request, sets headers if available,
19
+ * and passes control to the next middleware in the chain.
20
+ */
21
+ function createAngularHeadersMiddleware(server) {
22
+ return function angularHeadersMiddleware(_req, res, next) {
23
+ const headers = server.config.server.headers;
24
+ if (!headers) {
25
+ return next();
26
+ }
27
+ for (const [name, value] of Object.entries(headers)) {
28
+ if (value !== undefined) {
29
+ res.setHeader(name, value);
30
+ }
31
+ }
32
+ next();
33
+ };
34
+ }
@@ -7,4 +7,4 @@
7
7
  */
8
8
  import type { ServerResponse } from 'node:http';
9
9
  import type { Connect } from 'vite';
10
- export declare function angularHtmlFallbackMiddleware(req: Connect.IncomingMessage, res: ServerResponse, next: Connect.NextFunction): void;
10
+ export declare function angularHtmlFallbackMiddleware(req: Connect.IncomingMessage, _res: ServerResponse, next: Connect.NextFunction): void;
@@ -9,7 +9,7 @@
9
9
  Object.defineProperty(exports, "__esModule", { value: true });
10
10
  exports.angularHtmlFallbackMiddleware = angularHtmlFallbackMiddleware;
11
11
  const utils_1 = require("../utils");
12
- function angularHtmlFallbackMiddleware(req, res, next) {
12
+ function angularHtmlFallbackMiddleware(req, _res, next) {
13
13
  // Similar to how it is handled in vite
14
14
  // https://github.com/vitejs/vite/blob/main/packages/vite/src/node/server/middlewares/htmlFallback.ts#L15C19-L15C45
15
15
  if ((req.method === 'GET' || req.method === 'HEAD') &&
@@ -11,7 +11,7 @@ exports.createAngularIndexHtmlMiddleware = createAngularIndexHtmlMiddleware;
11
11
  const node_path_1 = require("node:path");
12
12
  const utils_1 = require("../utils");
13
13
  function createAngularIndexHtmlMiddleware(server, outputFiles, indexHtmlTransformer) {
14
- return function (req, res, next) {
14
+ return function angularIndexHtmlMiddleware(req, res, next) {
15
15
  if (!req.url) {
16
16
  next();
17
17
  return;
@@ -37,7 +37,6 @@ function createAngularIndexHtmlMiddleware(server, outputFiles, indexHtmlTransfor
37
37
  }
38
38
  res.setHeader('Content-Type', 'text/html');
39
39
  res.setHeader('Cache-Control', 'no-cache');
40
- (0, utils_1.appendServerConfiguredHeaders)(server, res);
41
40
  res.end(processedHtml);
42
41
  })
43
42
  .catch((error) => next(error));
@@ -9,3 +9,4 @@ export { createAngularAssetsMiddleware } from './assets-middleware';
9
9
  export { angularHtmlFallbackMiddleware } from './html-fallback-middleware';
10
10
  export { createAngularIndexHtmlMiddleware } from './index-html-middleware';
11
11
  export { createAngularSSRMiddleware } from './ssr-middleware';
12
+ export { createAngularHeadersMiddleware } from './headers-middleware';
@@ -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.createAngularSSRMiddleware = exports.createAngularIndexHtmlMiddleware = exports.angularHtmlFallbackMiddleware = exports.createAngularAssetsMiddleware = void 0;
10
+ exports.createAngularHeadersMiddleware = exports.createAngularSSRMiddleware = exports.createAngularIndexHtmlMiddleware = exports.angularHtmlFallbackMiddleware = exports.createAngularAssetsMiddleware = void 0;
11
11
  var assets_middleware_1 = require("./assets-middleware");
12
12
  Object.defineProperty(exports, "createAngularAssetsMiddleware", { enumerable: true, get: function () { return assets_middleware_1.createAngularAssetsMiddleware; } });
13
13
  var html_fallback_middleware_1 = require("./html-fallback-middleware");
@@ -16,3 +16,5 @@ var index_html_middleware_1 = require("./index-html-middleware");
16
16
  Object.defineProperty(exports, "createAngularIndexHtmlMiddleware", { enumerable: true, get: function () { return index_html_middleware_1.createAngularIndexHtmlMiddleware; } });
17
17
  var ssr_middleware_1 = require("./ssr-middleware");
18
18
  Object.defineProperty(exports, "createAngularSSRMiddleware", { enumerable: true, get: function () { return ssr_middleware_1.createAngularSSRMiddleware; } });
19
+ var headers_middleware_1 = require("./headers-middleware");
20
+ Object.defineProperty(exports, "createAngularHeadersMiddleware", { enumerable: true, get: function () { return headers_middleware_1.createAngularHeadersMiddleware; } });
@@ -8,10 +8,9 @@
8
8
  */
9
9
  Object.defineProperty(exports, "__esModule", { value: true });
10
10
  exports.createAngularSSRMiddleware = createAngularSSRMiddleware;
11
- const utils_1 = require("../utils");
12
11
  function createAngularSSRMiddleware(server, indexHtmlTransformer) {
13
12
  let cachedAngularServerApp;
14
- return function (req, res, next) {
13
+ return function angularSSRMiddleware(req, res, next) {
15
14
  if (req.url === undefined) {
16
15
  return next();
17
16
  }
@@ -36,7 +35,6 @@ function createAngularSSRMiddleware(server, indexHtmlTransformer) {
36
35
  if (typeof content !== 'string') {
37
36
  return next();
38
37
  }
39
- (0, utils_1.appendServerConfiguredHeaders)(server, res);
40
38
  res.end(content);
41
39
  })
42
40
  .catch((error) => next(error));
@@ -5,12 +5,9 @@
5
5
  * Use of this source code is governed by an MIT-style license that can be
6
6
  * found in the LICENSE file at https://angular.dev/license
7
7
  */
8
- import type { IncomingMessage, ServerResponse } from 'node:http';
9
- import type { ViteDevServer } from 'vite';
10
8
  export type AngularMemoryOutputFiles = Map<string, {
11
9
  contents: Uint8Array;
12
10
  servable: boolean;
13
11
  }>;
14
12
  export declare function pathnameWithoutBasePath(url: string, basePath: string): string;
15
13
  export declare function lookupMimeTypeFromRequest(url: string): string | undefined;
16
- export declare function appendServerConfiguredHeaders(server: ViteDevServer, res: ServerResponse<IncomingMessage>): void;
@@ -9,7 +9,6 @@
9
9
  Object.defineProperty(exports, "__esModule", { value: true });
10
10
  exports.pathnameWithoutBasePath = pathnameWithoutBasePath;
11
11
  exports.lookupMimeTypeFromRequest = lookupMimeTypeFromRequest;
12
- exports.appendServerConfiguredHeaders = appendServerConfiguredHeaders;
13
12
  const mrmime_1 = require("mrmime");
14
13
  const node_path_1 = require("node:path");
15
14
  function pathnameWithoutBasePath(url, basePath) {
@@ -27,14 +26,3 @@ function lookupMimeTypeFromRequest(url) {
27
26
  }
28
27
  return extension && (0, mrmime_1.lookup)(extension);
29
28
  }
30
- function appendServerConfiguredHeaders(server, res) {
31
- const headers = server.config.server.headers;
32
- if (!headers) {
33
- return;
34
- }
35
- for (const [name, value] of Object.entries(headers)) {
36
- if (value !== undefined) {
37
- res.setHeader(name, value);
38
- }
39
- }
40
- }
@@ -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-next.5';
13
+ const VERSION = '19.0.0-next.7';
14
14
  function hasCacheMetadata(value) {
15
15
  return (!!value &&
16
16
  typeof value === 'object' &&
@@ -6,13 +6,12 @@
6
6
  * found in the LICENSE file at https://angular.dev/license
7
7
  */
8
8
  import type { ApplicationRef, Type } from '@angular/core';
9
- import type { ɵServerRenderContext, ɵextractRoutesAndCreateRouteTree, ɵgetOrCreateAngularServerApp } from '@angular/ssr';
9
+ import type { ɵextractRoutesAndCreateRouteTree, ɵgetOrCreateAngularServerApp } from '@angular/ssr';
10
10
  /**
11
11
  * Represents the exports available from the main server bundle.
12
12
  */
13
13
  interface MainServerBundleExports {
14
14
  default: (() => Promise<ApplicationRef>) | Type<unknown>;
15
- ɵServerRenderContext: typeof ɵServerRenderContext;
16
15
  ɵextractRoutesAndCreateRouteTree: typeof ɵextractRoutesAndCreateRouteTree;
17
16
  ɵgetOrCreateAngularServerApp: typeof ɵgetOrCreateAngularServerApp;
18
17
  }
@@ -7,7 +7,7 @@
7
7
  */
8
8
  import { BuildOutputFile } from '../../tools/esbuild/bundler-context';
9
9
  import { BuildOutputAsset } from '../../tools/esbuild/bundler-execution-result';
10
- import type { RoutersExtractorWorkerResult as SerializableRouteTreeNode } from './routes-extractor-worker';
10
+ import type { SerializableRouteTreeNode } from './routes-extractor-worker';
11
11
  interface PrerenderOptions {
12
12
  routesFile?: string;
13
13
  discoverRoutes?: boolean;
@@ -6,17 +6,14 @@
6
6
  * Use of this source code is governed by an MIT-style license that can be
7
7
  * found in the LICENSE file at https://angular.dev/license
8
8
  */
9
- var __importDefault = (this && this.__importDefault) || function (mod) {
10
- return (mod && mod.__esModule) ? mod : { "default": mod };
11
- };
12
9
  Object.defineProperty(exports, "__esModule", { value: true });
13
10
  exports.prerenderPages = prerenderPages;
14
11
  const promises_1 = require("node:fs/promises");
15
12
  const node_path_1 = require("node:path");
16
13
  const node_url_1 = require("node:url");
17
- const piscina_1 = __importDefault(require("piscina"));
18
14
  const bundler_context_1 = require("../../tools/esbuild/bundler-context");
19
15
  const url_1 = require("../url");
16
+ const worker_pool_1 = require("../worker-pool");
20
17
  async function prerenderPages(workspaceRoot, baseHref, appShellOptions = {}, prerenderOptions = {}, outputFiles, assets, sourcemap = false, maxThreads = 1, verbose = false) {
21
18
  const outputFilesForWorker = {};
22
19
  const serverBundlesSourceMaps = new Map();
@@ -94,7 +91,7 @@ async function renderPages(baseHref, sourcemap, allRoutes, maxThreads, workspace
94
91
  if (sourcemap) {
95
92
  workerExecArgv.push('--enable-source-maps');
96
93
  }
97
- const renderWorker = new piscina_1.default({
94
+ const renderWorker = new worker_pool_1.WorkerPool({
98
95
  filename: require.resolve('./render-worker'),
99
96
  maxThreads: Math.min(allRoutes.size, maxThreads),
100
97
  workerData: {
@@ -103,7 +100,6 @@ async function renderPages(baseHref, sourcemap, allRoutes, maxThreads, workspace
103
100
  assetFiles: assetFilesForWorker,
104
101
  },
105
102
  execArgv: workerExecArgv,
106
- recordTiming: false,
107
103
  });
108
104
  try {
109
105
  const renderingPromises = [];
@@ -112,12 +108,12 @@ async function renderPages(baseHref, sourcemap, allRoutes, maxThreads, workspace
112
108
  for (const route of allRoutes) {
113
109
  // Remove base href from file output path.
114
110
  const routeWithoutBaseHref = addLeadingSlash(route.slice(baseHrefWithLeadingSlash.length - 1));
115
- const isAppShellRoute = appShellRoute === routeWithoutBaseHref;
116
- const render = renderWorker.run({ url: route, isAppShellRoute });
111
+ const render = renderWorker.run({ url: route });
117
112
  const renderResult = render
118
113
  .then((content) => {
119
114
  if (content !== null) {
120
115
  const outPath = node_path_1.posix.join(removeLeadingSlash(routeWithoutBaseHref), 'index.html');
116
+ const isAppShellRoute = appShellRoute === routeWithoutBaseHref;
121
117
  output[outPath] = { content, appShellRoute: isAppShellRoute };
122
118
  }
123
119
  })
@@ -161,7 +157,7 @@ async function getAllRoutes(workspaceRoot, baseHref, outputFilesForWorker, asset
161
157
  if (sourcemap) {
162
158
  workerExecArgv.push('--enable-source-maps');
163
159
  }
164
- const renderWorker = new piscina_1.default({
160
+ const renderWorker = new worker_pool_1.WorkerPool({
165
161
  filename: require.resolve('./routes-extractor-worker'),
166
162
  maxThreads: 1,
167
163
  workerData: {
@@ -170,10 +166,9 @@ async function getAllRoutes(workspaceRoot, baseHref, outputFilesForWorker, asset
170
166
  assetFiles: assetFilesForWorker,
171
167
  },
172
168
  execArgv: workerExecArgv,
173
- recordTiming: false,
174
169
  });
175
170
  const errors = [];
176
- const serializableRouteTreeNode = await renderWorker
171
+ const { serializedRouteTree: serializableRouteTreeNode } = await renderWorker
177
172
  .run({})
178
173
  .catch((err) => {
179
174
  errors.push(`An error occurred while extracting routes.\n\n${err.stack}`);
@@ -11,11 +11,10 @@ export interface RenderWorkerData extends ESMInMemoryFileLoaderWorkerData {
11
11
  }
12
12
  export interface RenderOptions {
13
13
  url: string;
14
- isAppShellRoute: boolean;
15
14
  }
16
15
  /**
17
16
  * Renders each route in routes and writes them to <outputPath>/<route>/index.html.
18
17
  */
19
- declare function renderPage({ url, isAppShellRoute }: RenderOptions): Promise<string | null>;
18
+ declare function renderPage({ url }: RenderOptions): Promise<string | null>;
20
19
  declare const _default: typeof renderPage;
21
20
  export default _default;
@@ -12,12 +12,10 @@ const load_esm_from_memory_1 = require("./load-esm-from-memory");
12
12
  /**
13
13
  * Renders each route in routes and writes them to <outputPath>/<route>/index.html.
14
14
  */
15
- async function renderPage({ url, isAppShellRoute }) {
16
- const { ɵgetOrCreateAngularServerApp: getOrCreateAngularServerApp, ɵServerRenderContext: ServerRenderContext, } = await (0, load_esm_from_memory_1.loadEsmModuleFromMemory)('./main.server.mjs');
15
+ async function renderPage({ url }) {
16
+ const { ɵgetOrCreateAngularServerApp: getOrCreateAngularServerApp } = await (0, load_esm_from_memory_1.loadEsmModuleFromMemory)('./main.server.mjs');
17
17
  const angularServerApp = getOrCreateAngularServerApp();
18
- const response = await angularServerApp.render(new Request(new URL(url, 'http://local-angular-prerender'), {
19
- signal: AbortSignal.timeout(30_000),
20
- }), undefined, isAppShellRoute ? ServerRenderContext.AppShell : ServerRenderContext.SSG);
18
+ const response = await angularServerApp.renderStatic(new URL(url, 'http://local-angular-prerender'), AbortSignal.timeout(30_000));
21
19
  return response ? response.text() : null;
22
20
  }
23
21
  function initialize() {
@@ -10,7 +10,11 @@ import type { ESMInMemoryFileLoaderWorkerData } from './esm-in-memory-loader/loa
10
10
  export interface RoutesExtractorWorkerData extends ESMInMemoryFileLoaderWorkerData {
11
11
  assetFiles: Record</** Destination */ string, /** Source */ string>;
12
12
  }
13
- export type RoutersExtractorWorkerResult = ReturnType<Awaited<ReturnType<typeof ɵextractRoutesAndCreateRouteTree>>['toObject']>;
13
+ export type SerializableRouteTreeNode = ReturnType<Awaited<ReturnType<typeof ɵextractRoutesAndCreateRouteTree>>['routeTree']['toObject']>;
14
+ export interface RoutersExtractorWorkerResult {
15
+ serializedRouteTree: SerializableRouteTreeNode;
16
+ errors: string[];
17
+ }
14
18
  /** Renders an application based on a provided options. */
15
19
  declare function extractRoutes(): Promise<RoutersExtractorWorkerResult>;
16
20
  declare const _default: typeof extractRoutes;
@@ -12,8 +12,13 @@ const load_esm_from_memory_1 = require("./load-esm-from-memory");
12
12
  /** Renders an application based on a provided options. */
13
13
  async function extractRoutes() {
14
14
  const { ɵextractRoutesAndCreateRouteTree: extractRoutesAndCreateRouteTree } = await (0, load_esm_from_memory_1.loadEsmModuleFromMemory)('./main.server.mjs');
15
- const routeTree = await extractRoutesAndCreateRouteTree(new URL('http://local-angular-prerender/'));
16
- return routeTree.toObject();
15
+ const { routeTree, errors } = await extractRoutesAndCreateRouteTree(new URL('http://local-angular-prerender/'),
16
+ /** manifest */ undefined,
17
+ /** invokeGetPrerenderParams */ true);
18
+ return {
19
+ errors,
20
+ serializedRouteTree: routeTree.toObject(),
21
+ };
17
22
  }
18
23
  function initialize() {
19
24
  (0, fetch_patch_1.patchFetchToLoadInMemoryAssets)();
@@ -0,0 +1,12 @@
1
+ /**
2
+ * @license
3
+ * Copyright Google LLC All Rights Reserved.
4
+ *
5
+ * Use of this source code is governed by an MIT-style license that can be
6
+ * found in the LICENSE file at https://angular.dev/license
7
+ */
8
+ import { Piscina } from 'piscina';
9
+ export type WorkerPoolOptions = ConstructorParameters<typeof Piscina>[0];
10
+ export declare class WorkerPool extends Piscina {
11
+ constructor(options: WorkerPoolOptions);
12
+ }
@@ -0,0 +1,43 @@
1
+ "use strict";
2
+ /**
3
+ * @license
4
+ * Copyright Google LLC All Rights Reserved.
5
+ *
6
+ * Use of this source code is governed by an MIT-style license that can be
7
+ * found in the LICENSE file at https://angular.dev/license
8
+ */
9
+ Object.defineProperty(exports, "__esModule", { value: true });
10
+ exports.WorkerPool = void 0;
11
+ const node_module_1 = require("node:module");
12
+ const piscina_1 = require("piscina");
13
+ class WorkerPool extends piscina_1.Piscina {
14
+ constructor(options) {
15
+ const piscinaOptions = {
16
+ minThreads: 1,
17
+ idleTimeout: 1000,
18
+ // Web containers do not support transferable objects with receiveOnMessagePort which
19
+ // is used when the Atomics based wait loop is enable.
20
+ useAtomics: !process.versions.webcontainer,
21
+ recordTiming: false,
22
+ ...options,
23
+ };
24
+ // Enable compile code caching if enabled for the main process (only exists on Node.js v22.8+).
25
+ // Skip if running inside Bazel via a RUNFILES environment variable check. The cache does not work
26
+ // well with Bazel's hermeticity requirements.
27
+ const compileCacheDirectory = process.env['RUNFILES'] ? undefined : (0, node_module_1.getCompileCacheDir)?.();
28
+ if (compileCacheDirectory) {
29
+ if (typeof piscinaOptions.env === 'object') {
30
+ piscinaOptions.env['NODE_COMPILE_CACHE'] = compileCacheDirectory;
31
+ }
32
+ else {
33
+ // Default behavior of `env` option is to copy current process values
34
+ piscinaOptions.env = {
35
+ ...process.env,
36
+ 'NODE_COMPILE_CACHE': compileCacheDirectory,
37
+ };
38
+ }
39
+ }
40
+ super(piscinaOptions);
41
+ }
42
+ }
43
+ exports.WorkerPool = WorkerPool;