@angular/build 19.0.0-next.0 → 19.0.0-next.10

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 (116) hide show
  1. package/LICENSE +5 -5
  2. package/package.json +20 -16
  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 +36 -1
  12. package/src/builders/application/options.js +60 -3
  13. package/src/builders/application/schema.d.ts +15 -0
  14. package/src/builders/application/schema.js +11 -1
  15. package/src/builders/application/schema.json +5 -0
  16. package/src/builders/application/setup-bundling.js +12 -9
  17. package/src/builders/dev-server/internal.d.ts +0 -1
  18. package/src/builders/dev-server/internal.js +1 -3
  19. package/src/builders/dev-server/vite-server.d.ts +8 -2
  20. package/src/builders/dev-server/vite-server.js +111 -56
  21. package/src/builders/extract-i18n/application-extraction.js +7 -3
  22. package/src/tools/angular/angular-host.d.ts +2 -1
  23. package/src/tools/angular/angular-host.js +20 -1
  24. package/src/tools/angular/compilation/angular-compilation.d.ts +1 -0
  25. package/src/tools/angular/compilation/aot-compilation.d.ts +1 -0
  26. package/src/tools/angular/compilation/aot-compilation.js +9 -1
  27. package/src/tools/angular/compilation/jit-compilation.js +2 -1
  28. package/src/tools/angular/compilation/parallel-compilation.d.ts +2 -1
  29. package/src/tools/angular/compilation/parallel-compilation.js +2 -10
  30. package/src/tools/angular/compilation/parallel-worker.d.ts +1 -0
  31. package/src/tools/angular/compilation/parallel-worker.js +2 -1
  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 +46 -4
  37. package/src/tools/esbuild/angular/component-stylesheets.d.ts +8 -3
  38. package/src/tools/esbuild/angular/component-stylesheets.js +46 -11
  39. package/src/tools/esbuild/angular/file-reference-tracker.d.ts +1 -1
  40. package/src/tools/esbuild/application-code-bundle.d.ts +2 -6
  41. package/src/tools/esbuild/application-code-bundle.js +208 -92
  42. package/src/tools/esbuild/budget-stats.js +1 -1
  43. package/src/tools/esbuild/bundler-context.d.ts +4 -3
  44. package/src/tools/esbuild/bundler-context.js +21 -13
  45. package/src/tools/esbuild/bundler-execution-result.d.ts +5 -2
  46. package/src/tools/esbuild/bundler-execution-result.js +7 -3
  47. package/src/tools/esbuild/cache.d.ts +6 -1
  48. package/src/tools/esbuild/cache.js +7 -0
  49. package/src/tools/esbuild/compiler-plugin-options.js +3 -1
  50. package/src/tools/esbuild/i18n-inliner.js +4 -4
  51. package/src/tools/esbuild/javascript-transformer-worker.d.ts +1 -0
  52. package/src/tools/esbuild/javascript-transformer-worker.js +5 -1
  53. package/src/tools/esbuild/javascript-transformer.d.ts +2 -2
  54. package/src/tools/esbuild/javascript-transformer.js +7 -12
  55. package/src/tools/esbuild/utils.d.ts +9 -0
  56. package/src/tools/esbuild/utils.js +21 -3
  57. package/src/tools/sass/sass-service.js +11 -13
  58. package/src/tools/sass/worker.d.ts +13 -32
  59. package/src/tools/sass/worker.js +1 -0
  60. package/src/tools/vite/middlewares/assets-middleware.d.ts +1 -1
  61. package/src/tools/vite/middlewares/assets-middleware.js +43 -4
  62. package/src/tools/vite/middlewares/headers-middleware.d.ts +19 -0
  63. package/src/tools/vite/middlewares/headers-middleware.js +34 -0
  64. package/src/tools/vite/middlewares/html-fallback-middleware.d.ts +1 -1
  65. package/src/tools/vite/middlewares/html-fallback-middleware.js +23 -7
  66. package/src/tools/vite/middlewares/index-html-middleware.js +1 -2
  67. package/src/tools/vite/middlewares/index.d.ts +2 -1
  68. package/src/tools/vite/middlewares/index.js +5 -2
  69. package/src/tools/vite/middlewares/ssr-middleware.d.ts +2 -4
  70. package/src/tools/vite/middlewares/ssr-middleware.js +75 -43
  71. package/src/tools/vite/plugins/angular-memory-plugin.d.ts +16 -0
  72. package/src/tools/vite/{angular-memory-plugin.js → plugins/angular-memory-plugin.js} +19 -40
  73. package/src/tools/vite/{i18n-locale-plugin.d.ts → plugins/i18n-locale-plugin.d.ts} +0 -4
  74. package/src/tools/vite/{i18n-locale-plugin.js → plugins/i18n-locale-plugin.js} +2 -3
  75. package/src/tools/vite/plugins/index.d.ts +12 -0
  76. package/src/tools/vite/plugins/index.js +21 -0
  77. package/src/tools/vite/plugins/setup-middlewares-plugin.d.ts +41 -0
  78. package/src/tools/vite/plugins/setup-middlewares-plugin.js +62 -0
  79. package/src/{utils/server-rendering/main-bundle-exports.js → tools/vite/plugins/ssr-transform-plugin.d.ts} +2 -2
  80. package/src/tools/vite/plugins/ssr-transform-plugin.js +38 -0
  81. package/src/tools/vite/utils.d.ts +0 -3
  82. package/src/tools/vite/utils.js +0 -12
  83. package/src/typings.d.ts +26 -0
  84. package/src/utils/environment-options.d.ts +2 -0
  85. package/src/utils/environment-options.js +5 -1
  86. package/src/utils/index-file/index-html-generator.js +5 -0
  87. package/src/utils/index-file/inline-critical-css.js +43 -33
  88. package/src/utils/index-file/ngcm-attribute.d.ts +15 -0
  89. package/src/utils/index-file/ngcm-attribute.js +37 -0
  90. package/src/utils/index-file/valid-self-closing-tags.js +28 -0
  91. package/src/utils/normalize-cache.js +1 -1
  92. package/src/utils/server-rendering/fetch-patch.d.ts +1 -1
  93. package/src/utils/server-rendering/fetch-patch.js +5 -6
  94. package/src/utils/server-rendering/launch-server.d.ts +14 -0
  95. package/src/utils/server-rendering/launch-server.js +63 -0
  96. package/src/utils/server-rendering/load-esm-from-memory.d.ts +18 -2
  97. package/src/utils/server-rendering/manifest.d.ts +50 -0
  98. package/src/utils/server-rendering/manifest.js +126 -0
  99. package/src/utils/server-rendering/models.d.ts +27 -0
  100. package/src/utils/server-rendering/models.js +22 -0
  101. package/src/utils/server-rendering/prerender.d.ts +26 -10
  102. package/src/utils/server-rendering/prerender.js +126 -67
  103. package/src/utils/server-rendering/render-worker.d.ts +9 -8
  104. package/src/utils/server-rendering/render-worker.js +19 -14
  105. package/src/utils/server-rendering/routes-extractor-worker.d.ts +6 -10
  106. package/src/utils/server-rendering/routes-extractor-worker.js +16 -33
  107. package/src/utils/server-rendering/utils.d.ts +11 -0
  108. package/src/utils/server-rendering/utils.js +17 -0
  109. package/src/utils/worker-pool.d.ts +12 -0
  110. package/src/utils/worker-pool.js +43 -0
  111. package/src/tools/vite/angular-memory-plugin.d.ts +0 -21
  112. package/src/utils/server-rendering/main-bundle-exports.d.ts +0 -27
  113. package/src/utils/server-rendering/render-page.d.ts +0 -26
  114. package/src/utils/server-rendering/render-page.js +0 -114
  115. /package/src/tools/vite/{id-prefix-plugin.d.ts → plugins/id-prefix-plugin.d.ts} +0 -0
  116. /package/src/tools/vite/{id-prefix-plugin.js → plugins/id-prefix-plugin.js} +0 -0
@@ -22,38 +22,53 @@ const MEDIA_SET_HANDLER_PATTERN = /^this\.media=["'](.*)["'];?$/;
22
22
  */
23
23
  const CSP_MEDIA_ATTR = 'ngCspMedia';
24
24
  /**
25
- * Script text used to change the media value of the link tags.
25
+ * Script that dynamically updates the `media` attribute of `<link>` tags based on a custom attribute (`CSP_MEDIA_ATTR`).
26
26
  *
27
27
  * NOTE:
28
28
  * We do not use `document.querySelectorAll('link').forEach((s) => s.addEventListener('load', ...)`
29
- * because this does not always fire on Chome.
29
+ * because load events are not always triggered reliably on Chrome.
30
30
  * See: https://github.com/angular/angular-cli/issues/26932 and https://crbug.com/1521256
31
+ *
32
+ * The script:
33
+ * - Ensures the event target is a `<link>` tag with the `CSP_MEDIA_ATTR` attribute.
34
+ * - Updates the `media` attribute with the value of `CSP_MEDIA_ATTR` and then removes the attribute.
35
+ * - Removes the event listener when all relevant `<link>` tags have been processed.
36
+ * - Uses event capturing (the `true` parameter) since load events do not bubble up the DOM.
31
37
  */
32
- const LINK_LOAD_SCRIPT_CONTENT = [
33
- '(() => {',
34
- ` const CSP_MEDIA_ATTR = '${CSP_MEDIA_ATTR}';`,
35
- ' const documentElement = document.documentElement;',
36
- ' const listener = (e) => {',
37
- ' const target = e.target;',
38
- ` if (!target || target.tagName !== 'LINK' || !target.hasAttribute(CSP_MEDIA_ATTR)) {`,
39
- ' return;',
40
- ' }',
41
- ' target.media = target.getAttribute(CSP_MEDIA_ATTR);',
42
- ' target.removeAttribute(CSP_MEDIA_ATTR);',
43
- // Remove onload listener when there are no longer styles that need to be loaded.
44
- ' if (!document.head.querySelector(`link[${CSP_MEDIA_ATTR}]`)) {',
45
- ` documentElement.removeEventListener('load', listener);`,
46
- ' }',
47
- ' };',
48
- // We use an event with capturing (the true parameter) because load events don't bubble.
49
- ` documentElement.addEventListener('load', listener, true);`,
50
- '})();',
51
- ].join('\n');
52
- class CrittersExtended extends critters_1.default {
38
+ const LINK_LOAD_SCRIPT_CONTENT = `
39
+ (() => {
40
+ const CSP_MEDIA_ATTR = '${CSP_MEDIA_ATTR}';
41
+ const documentElement = document.documentElement;
42
+
43
+ // Listener for load events on link tags.
44
+ const listener = (e) => {
45
+ const target = e.target;
46
+ if (
47
+ !target ||
48
+ target.tagName !== 'LINK' ||
49
+ !target.hasAttribute(CSP_MEDIA_ATTR)
50
+ ) {
51
+ return;
52
+ }
53
+
54
+ target.media = target.getAttribute(CSP_MEDIA_ATTR);
55
+ target.removeAttribute(CSP_MEDIA_ATTR);
56
+
57
+ if (!document.head.querySelector(\`link[\${CSP_MEDIA_ATTR}]\`)) {
58
+ documentElement.removeEventListener('load', listener);
59
+ }
60
+ };
61
+
62
+ documentElement.addEventListener('load', listener, true);
63
+ })();
64
+ `.trim();
65
+ class CrittersBase extends critters_1.default {
66
+ }
67
+ /* eslint-enable @typescript-eslint/no-unsafe-declaration-merging */
68
+ class CrittersExtended extends CrittersBase {
53
69
  optionsExtended;
54
70
  warnings = [];
55
71
  errors = [];
56
- initialEmbedLinkedStylesheet;
57
72
  addedCspScriptsDocuments = new WeakSet();
58
73
  documentNonces = new WeakMap();
59
74
  constructor(optionsExtended) {
@@ -71,17 +86,12 @@ class CrittersExtended extends critters_1.default {
71
86
  reduceInlineStyles: false,
72
87
  mergeStylesheets: false,
73
88
  // Note: if `preload` changes to anything other than `media`, the logic in
74
- // `embedLinkedStylesheetOverride` will have to be updated.
89
+ // `embedLinkedStylesheet` will have to be updated.
75
90
  preload: 'media',
76
91
  noscriptFallback: true,
77
92
  inlineFonts: true,
78
93
  });
79
94
  this.optionsExtended = optionsExtended;
80
- // We can't use inheritance to override `embedLinkedStylesheet`, because it's not declared in
81
- // the `Critters` .d.ts which means that we can't call the `super` implementation. TS doesn't
82
- // allow for `super` to be cast to a different type.
83
- this.initialEmbedLinkedStylesheet = this.embedLinkedStylesheet;
84
- this.embedLinkedStylesheet = this.embedLinkedStylesheetOverride;
85
95
  }
86
96
  readFile(path) {
87
97
  const readAsset = this.optionsExtended.readAsset;
@@ -91,7 +101,7 @@ class CrittersExtended extends critters_1.default {
91
101
  * Override of the Critters `embedLinkedStylesheet` method
92
102
  * that makes it work with Angular's CSP APIs.
93
103
  */
94
- embedLinkedStylesheetOverride = async (link, document) => {
104
+ async embedLinkedStylesheet(link, document) {
95
105
  if (link.getAttribute('media') === 'print' && link.next?.name === 'noscript') {
96
106
  // Workaround for https://github.com/GoogleChromeLabs/critters/issues/64
97
107
  // NB: this is only needed for the webpack based builders.
@@ -102,7 +112,7 @@ class CrittersExtended extends critters_1.default {
102
112
  link?.next?.remove();
103
113
  }
104
114
  }
105
- const returnValue = await this.initialEmbedLinkedStylesheet(link, document);
115
+ const returnValue = await super.embedLinkedStylesheet(link, document);
106
116
  const cspNonce = this.findCspNonce(document);
107
117
  if (cspNonce) {
108
118
  const crittersMedia = link.getAttribute('onload')?.match(MEDIA_SET_HANDLER_PATTERN);
@@ -126,7 +136,7 @@ class CrittersExtended extends critters_1.default {
126
136
  });
127
137
  }
128
138
  return returnValue;
129
- };
139
+ }
130
140
  /**
131
141
  * Finds the CSP nonce for a specific document.
132
142
  */
@@ -0,0 +1,15 @@
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
+ /**
9
+ * Transforms the provided HTML by adding the `ngcm` attribute to the `<body>` tag.
10
+ * This is used in the client-side rendered (CSR) version of `index.html` to prevent hydration warnings.
11
+ *
12
+ * @param html The HTML markup to be transformed.
13
+ * @returns A promise that resolves to the transformed HTML string with the necessary modifications.
14
+ */
15
+ export declare function addNgcmAttribute(html: string): Promise<string>;
@@ -0,0 +1,37 @@
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.addNgcmAttribute = addNgcmAttribute;
11
+ const html_rewriting_stream_1 = require("./html-rewriting-stream");
12
+ /**
13
+ * Defines a name of an attribute that is added to the `<body>` tag
14
+ * in the `index.html` file in case a given route was configured
15
+ * with `RenderMode.Client`. 'cm' is an abbreviation for "Client Mode".
16
+ *
17
+ * @see https://github.com/angular/angular/pull/58004
18
+ */
19
+ const CLIENT_RENDER_MODE_FLAG = 'ngcm';
20
+ /**
21
+ * Transforms the provided HTML by adding the `ngcm` attribute to the `<body>` tag.
22
+ * This is used in the client-side rendered (CSR) version of `index.html` to prevent hydration warnings.
23
+ *
24
+ * @param html The HTML markup to be transformed.
25
+ * @returns A promise that resolves to the transformed HTML string with the necessary modifications.
26
+ */
27
+ async function addNgcmAttribute(html) {
28
+ const { rewriter, transformedContent } = await (0, html_rewriting_stream_1.htmlRewritingStream)(html);
29
+ rewriter.on('startTag', (tag) => {
30
+ if (tag.tagName === 'body' &&
31
+ !tag.attrs.some((attr) => attr.name === CLIENT_RENDER_MODE_FLAG)) {
32
+ tag.attrs.push({ name: CLIENT_RENDER_MODE_FLAG, value: '' });
33
+ }
34
+ rewriter.emitStartTag(tag);
35
+ });
36
+ return transformedContent();
37
+ }
@@ -25,8 +25,36 @@ exports.VALID_SELF_CLOSING_TAGS = new Set([
25
25
  'track',
26
26
  'wbr',
27
27
  /** SVG tags */
28
+ 'animate',
29
+ 'animateMotion',
30
+ 'animateTransform',
28
31
  'circle',
29
32
  'ellipse',
33
+ 'feBlend',
34
+ 'feColorMatrix',
35
+ 'feComponentTransfer',
36
+ 'feComposite',
37
+ 'feConvolveMatrix',
38
+ 'feDiffuseLighting',
39
+ 'feDisplacementMap',
40
+ 'feDistantLight',
41
+ 'feDropShadow',
42
+ 'feFlood',
43
+ 'feFuncA',
44
+ 'feFuncB',
45
+ 'feFuncG',
46
+ 'feFuncR',
47
+ 'feGaussianBlur',
48
+ 'feImage',
49
+ 'feMerge',
50
+ 'feMergeNode',
51
+ 'feMorphology',
52
+ 'feOffset',
53
+ 'fePointLight',
54
+ 'feSpecularLighting',
55
+ 'feSpotLight',
56
+ 'feTile',
57
+ 'feTurbulence',
30
58
  'line',
31
59
  'path',
32
60
  'polygon',
@@ -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.0';
13
+ const VERSION = '19.0.0-next.10';
14
14
  function hasCacheMetadata(value) {
15
15
  return (!!value &&
16
16
  typeof value === 'object' &&
@@ -5,4 +5,4 @@
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
- export declare function patchFetchToLoadInMemoryAssets(): void;
8
+ export declare function patchFetchToLoadInMemoryAssets(baseURL: URL): void;
@@ -17,8 +17,7 @@ const node_worker_threads_1 = require("node:worker_threads");
17
17
  */
18
18
  const { assetFiles } = node_worker_threads_1.workerData;
19
19
  const assetsCache = new Map();
20
- const RESOLVE_PROTOCOL = 'resolve:';
21
- function patchFetchToLoadInMemoryAssets() {
20
+ function patchFetchToLoadInMemoryAssets(baseURL) {
22
21
  const originalFetch = globalThis.fetch;
23
22
  const patchedFetch = async (input, init) => {
24
23
  let url;
@@ -26,17 +25,17 @@ function patchFetchToLoadInMemoryAssets() {
26
25
  url = input;
27
26
  }
28
27
  else if (typeof input === 'string') {
29
- url = new URL(input, RESOLVE_PROTOCOL + '//');
28
+ url = new URL(input);
30
29
  }
31
30
  else if (typeof input === 'object' && 'url' in input) {
32
- url = new URL(input.url, RESOLVE_PROTOCOL + '//');
31
+ url = new URL(input.url);
33
32
  }
34
33
  else {
35
34
  return originalFetch(input, init);
36
35
  }
37
- const { protocol } = url;
36
+ const { hostname } = url;
38
37
  const pathname = decodeURIComponent(url.pathname);
39
- if (protocol !== RESOLVE_PROTOCOL || !assetFiles[pathname]) {
38
+ if (hostname !== baseURL.hostname || !assetFiles[pathname]) {
40
39
  // Only handle relative requests or files that are in assets.
41
40
  return originalFetch(input, init);
42
41
  }
@@ -0,0 +1,14 @@
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
+ export declare const DEFAULT_URL: import("url").URL;
9
+ /**
10
+ * Launches a server that handles local requests.
11
+ *
12
+ * @returns A promise that resolves to the URL of the running server.
13
+ */
14
+ export declare function launchServer(): Promise<URL>;
@@ -0,0 +1,63 @@
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
+ var __importDefault = (this && this.__importDefault) || function (mod) {
10
+ return (mod && mod.__esModule) ? mod : { "default": mod };
11
+ };
12
+ Object.defineProperty(exports, "__esModule", { value: true });
13
+ exports.DEFAULT_URL = void 0;
14
+ exports.launchServer = launchServer;
15
+ const node_assert_1 = __importDefault(require("node:assert"));
16
+ const node_http_1 = require("node:http");
17
+ const load_esm_1 = require("../load-esm");
18
+ const load_esm_from_memory_1 = require("./load-esm-from-memory");
19
+ const utils_1 = require("./utils");
20
+ exports.DEFAULT_URL = new URL('http://ng-localhost/');
21
+ /**
22
+ * Launches a server that handles local requests.
23
+ *
24
+ * @returns A promise that resolves to the URL of the running server.
25
+ */
26
+ async function launchServer() {
27
+ const { default: handler } = await (0, load_esm_from_memory_1.loadEsmModuleFromMemory)('./server.mjs');
28
+ const { createWebRequestFromNodeRequest, writeResponseToNodeResponse } = await (0, load_esm_1.loadEsmModule)('@angular/ssr/node');
29
+ if (!(0, utils_1.isSsrNodeRequestHandler)(handler) && !(0, utils_1.isSsrRequestHandler)(handler)) {
30
+ return exports.DEFAULT_URL;
31
+ }
32
+ const server = (0, node_http_1.createServer)((req, res) => {
33
+ (async () => {
34
+ // handle request
35
+ if ((0, utils_1.isSsrNodeRequestHandler)(handler)) {
36
+ await handler(req, res, (e) => {
37
+ throw e;
38
+ });
39
+ }
40
+ else {
41
+ const webRes = await handler(createWebRequestFromNodeRequest(req));
42
+ if (webRes) {
43
+ await writeResponseToNodeResponse(webRes, res);
44
+ }
45
+ else {
46
+ res.statusCode = 501;
47
+ res.end('Not Implemented.');
48
+ }
49
+ }
50
+ })().catch((e) => {
51
+ res.statusCode = 500;
52
+ res.end('Internal Server Error.');
53
+ // eslint-disable-next-line no-console
54
+ console.error(e);
55
+ });
56
+ });
57
+ server.unref();
58
+ await new Promise((resolve) => server.listen(0, 'localhost', resolve));
59
+ const serverAddress = server.address();
60
+ (0, node_assert_1.default)(serverAddress, 'Server address should be defined.');
61
+ (0, node_assert_1.default)(typeof serverAddress !== 'string', 'Server address should not be a string.');
62
+ return new URL(`http://localhost:${serverAddress.port}/`);
63
+ }
@@ -5,6 +5,22 @@
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 { MainServerBundleExports, RenderUtilsServerBundleExports } from './main-bundle-exports';
8
+ import type { ApplicationRef, Type } from '@angular/core';
9
+ import type { ɵextractRoutesAndCreateRouteTree, ɵgetOrCreateAngularServerApp } from '@angular/ssr';
10
+ /**
11
+ * Represents the exports available from the main server bundle.
12
+ */
13
+ interface MainServerBundleExports {
14
+ default: (() => Promise<ApplicationRef>) | Type<unknown>;
15
+ ɵextractRoutesAndCreateRouteTree: typeof ɵextractRoutesAndCreateRouteTree;
16
+ ɵgetOrCreateAngularServerApp: typeof ɵgetOrCreateAngularServerApp;
17
+ }
18
+ /**
19
+ * Represents the exports available from the server bundle.
20
+ */
21
+ interface ServerBundleExports {
22
+ default: unknown;
23
+ }
9
24
  export declare function loadEsmModuleFromMemory(path: './main.server.mjs'): Promise<MainServerBundleExports>;
10
- export declare function loadEsmModuleFromMemory(path: './render-utils.server.mjs'): Promise<RenderUtilsServerBundleExports>;
25
+ export declare function loadEsmModuleFromMemory(path: './server.mjs'): Promise<ServerBundleExports>;
26
+ export {};
@@ -0,0 +1,50 @@
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 { NormalizedApplicationBuildOptions } from '../../builders/application/options';
9
+ import type { BuildOutputFile } from '../../tools/esbuild/bundler-context';
10
+ import { PrerenderedRoutesRecord } from '../../tools/esbuild/bundler-execution-result';
11
+ export declare const SERVER_APP_MANIFEST_FILENAME = "angular-app-manifest.mjs";
12
+ export declare const SERVER_APP_ENGINE_MANIFEST_FILENAME = "angular-app-engine-manifest.mjs";
13
+ /**
14
+ * Generates the server manifest for the App Engine environment.
15
+ *
16
+ * This manifest is used to configure the server-side rendering (SSR) setup for the
17
+ * Angular application when deployed to Google App Engine. It includes the entry points
18
+ * for different locales and the base HREF for the application.
19
+ *
20
+ * @param i18nOptions - The internationalization options for the application build. This
21
+ * includes settings for inlining locales and determining the output structure.
22
+ * @param baseHref - The base HREF for the application. This is used to set the base URL
23
+ * for all relative URLs in the application.
24
+ * @param perenderedRoutes - A record mapping static paths to their associated data.
25
+ * @returns A string representing the content of the SSR server manifest for App Engine.
26
+ */
27
+ export declare function generateAngularServerAppEngineManifest(i18nOptions: NormalizedApplicationBuildOptions['i18nOptions'], baseHref: string | undefined, perenderedRoutes?: PrerenderedRoutesRecord | undefined): string;
28
+ /**
29
+ * Generates the server manifest for the standard Node.js environment.
30
+ *
31
+ * This manifest is used to configure the server-side rendering (SSR) setup for the
32
+ * Angular application when running in a standard Node.js environment. It includes
33
+ * information about the bootstrap module, whether to inline critical CSS, and any
34
+ * additional HTML and CSS output files.
35
+ *
36
+ * @param additionalHtmlOutputFiles - A map of additional HTML output files generated
37
+ * during the build process, keyed by their file paths.
38
+ * @param outputFiles - An array of all output files from the build process, including
39
+ * JavaScript and CSS files.
40
+ * @param inlineCriticalCss - A boolean indicating whether critical CSS should be inlined
41
+ * in the server-side rendered pages.
42
+ * @param routes - An optional array of route definitions for the application, used for
43
+ * server-side rendering and routing.
44
+ * @param locale - An optional string representing the locale or language code to be used for
45
+ * the application, helping with localization and rendering content specific to the locale.
46
+ *
47
+ * @returns A string representing the content of the SSR server manifest for the Node.js
48
+ * environment.
49
+ */
50
+ export declare function generateAngularServerAppManifest(additionalHtmlOutputFiles: Map<string, BuildOutputFile>, outputFiles: BuildOutputFile[], inlineCriticalCss: boolean, routes: readonly unknown[] | undefined, locale: string | undefined): string;
@@ -0,0 +1,126 @@
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.SERVER_APP_ENGINE_MANIFEST_FILENAME = exports.SERVER_APP_MANIFEST_FILENAME = void 0;
11
+ exports.generateAngularServerAppEngineManifest = generateAngularServerAppEngineManifest;
12
+ exports.generateAngularServerAppManifest = generateAngularServerAppManifest;
13
+ const options_1 = require("../../builders/application/options");
14
+ exports.SERVER_APP_MANIFEST_FILENAME = 'angular-app-manifest.mjs';
15
+ exports.SERVER_APP_ENGINE_MANIFEST_FILENAME = 'angular-app-engine-manifest.mjs';
16
+ const MAIN_SERVER_OUTPUT_FILENAME = 'main.server.mjs';
17
+ /**
18
+ * A mapping of unsafe characters to their escaped Unicode equivalents.
19
+ */
20
+ const UNSAFE_CHAR_MAP = {
21
+ '`': '\\`',
22
+ '$': '\\$',
23
+ '\\': '\\\\',
24
+ };
25
+ /**
26
+ * Escapes unsafe characters in a given string by replacing them with
27
+ * their Unicode escape sequences.
28
+ *
29
+ * @param str - The string to be escaped.
30
+ * @returns The escaped string where unsafe characters are replaced.
31
+ */
32
+ function escapeUnsafeChars(str) {
33
+ return str.replace(/[$`\\]/g, (c) => UNSAFE_CHAR_MAP[c]);
34
+ }
35
+ /**
36
+ * Generates the server manifest for the App Engine environment.
37
+ *
38
+ * This manifest is used to configure the server-side rendering (SSR) setup for the
39
+ * Angular application when deployed to Google App Engine. It includes the entry points
40
+ * for different locales and the base HREF for the application.
41
+ *
42
+ * @param i18nOptions - The internationalization options for the application build. This
43
+ * includes settings for inlining locales and determining the output structure.
44
+ * @param baseHref - The base HREF for the application. This is used to set the base URL
45
+ * for all relative URLs in the application.
46
+ * @param perenderedRoutes - A record mapping static paths to their associated data.
47
+ * @returns A string representing the content of the SSR server manifest for App Engine.
48
+ */
49
+ function generateAngularServerAppEngineManifest(i18nOptions, baseHref, perenderedRoutes = {}) {
50
+ const entryPointsContent = [];
51
+ if (i18nOptions.shouldInline) {
52
+ for (const locale of i18nOptions.inlineLocales) {
53
+ const importPath = './' + (i18nOptions.flatOutput ? '' : locale + '/') + MAIN_SERVER_OUTPUT_FILENAME;
54
+ let localeWithBaseHref = (0, options_1.getLocaleBaseHref)('', i18nOptions, locale) || '/';
55
+ // Remove leading and trailing slashes.
56
+ const start = localeWithBaseHref[0] === '/' ? 1 : 0;
57
+ const end = localeWithBaseHref[localeWithBaseHref.length - 1] === '/' ? -1 : undefined;
58
+ localeWithBaseHref = localeWithBaseHref.slice(start, end);
59
+ entryPointsContent.push(`['${localeWithBaseHref}', () => import('${importPath}')]`);
60
+ }
61
+ }
62
+ else {
63
+ entryPointsContent.push(`['', () => import('./${MAIN_SERVER_OUTPUT_FILENAME}')]`);
64
+ }
65
+ const staticHeaders = [];
66
+ for (const [path, { headers }] of Object.entries(perenderedRoutes)) {
67
+ if (!headers) {
68
+ continue;
69
+ }
70
+ const headersValues = [];
71
+ for (const [name, value] of Object.entries(headers)) {
72
+ headersValues.push(`['${name}', '${encodeURIComponent(value)}']`);
73
+ }
74
+ staticHeaders.push(`['${path}', [${headersValues.join(', ')}]]`);
75
+ }
76
+ const manifestContent = `
77
+ export default {
78
+ basePath: '${baseHref ?? '/'}',
79
+ entryPoints: new Map([${entryPointsContent.join(', \n')}]),
80
+ staticPathsHeaders: new Map([${staticHeaders.join(', \n')}]),
81
+ };
82
+ `;
83
+ return manifestContent;
84
+ }
85
+ /**
86
+ * Generates the server manifest for the standard Node.js environment.
87
+ *
88
+ * This manifest is used to configure the server-side rendering (SSR) setup for the
89
+ * Angular application when running in a standard Node.js environment. It includes
90
+ * information about the bootstrap module, whether to inline critical CSS, and any
91
+ * additional HTML and CSS output files.
92
+ *
93
+ * @param additionalHtmlOutputFiles - A map of additional HTML output files generated
94
+ * during the build process, keyed by their file paths.
95
+ * @param outputFiles - An array of all output files from the build process, including
96
+ * JavaScript and CSS files.
97
+ * @param inlineCriticalCss - A boolean indicating whether critical CSS should be inlined
98
+ * in the server-side rendered pages.
99
+ * @param routes - An optional array of route definitions for the application, used for
100
+ * server-side rendering and routing.
101
+ * @param locale - An optional string representing the locale or language code to be used for
102
+ * the application, helping with localization and rendering content specific to the locale.
103
+ *
104
+ * @returns A string representing the content of the SSR server manifest for the Node.js
105
+ * environment.
106
+ */
107
+ function generateAngularServerAppManifest(additionalHtmlOutputFiles, outputFiles, inlineCriticalCss, routes, locale) {
108
+ const serverAssetsContent = [];
109
+ for (const file of [...additionalHtmlOutputFiles.values(), ...outputFiles]) {
110
+ if (file.path === options_1.INDEX_HTML_SERVER ||
111
+ file.path === options_1.INDEX_HTML_CSR ||
112
+ (inlineCriticalCss && file.path.endsWith('.css'))) {
113
+ serverAssetsContent.push(`['${file.path}', async () => \`${escapeUnsafeChars(file.text)}\`]`);
114
+ }
115
+ }
116
+ const manifestContent = `
117
+ export default {
118
+ bootstrap: () => import('./main.server.mjs').then(m => m.default),
119
+ inlineCriticalCss: ${inlineCriticalCss},
120
+ routes: ${JSON.stringify(routes, undefined, 2)},
121
+ assets: new Map([${serverAssetsContent.join(', \n')}]),
122
+ locale: ${locale !== undefined ? `'${locale}'` : undefined},
123
+ };
124
+ `;
125
+ return manifestContent;
126
+ }
@@ -0,0 +1,27 @@
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 { RenderMode, ɵextractRoutesAndCreateRouteTree } from '@angular/ssr';
9
+ import { ESMInMemoryFileLoaderWorkerData } from './esm-in-memory-loader/loader-hooks';
10
+ type Writeable<T extends readonly unknown[]> = T extends readonly (infer U)[] ? U[] : never;
11
+ export interface RoutesExtractorWorkerData extends ESMInMemoryFileLoaderWorkerData {
12
+ assetFiles: Record</** Destination */ string, /** Source */ string>;
13
+ }
14
+ export type SerializableRouteTreeNode = ReturnType<Awaited<ReturnType<typeof ɵextractRoutesAndCreateRouteTree>>['routeTree']['toObject']>;
15
+ export type WritableSerializableRouteTreeNode = Writeable<SerializableRouteTreeNode>;
16
+ export interface RoutersExtractorWorkerResult {
17
+ serializedRouteTree: SerializableRouteTreeNode;
18
+ errors: string[];
19
+ }
20
+ /**
21
+ * Local copy of `RenderMode` exported from `@angular/ssr`.
22
+ * This constant is needed to handle interop between CommonJS (CJS) and ES Modules (ESM) formats.
23
+ *
24
+ * It maps `RenderMode` enum values to their corresponding numeric identifiers.
25
+ */
26
+ export declare const RouteRenderMode: Record<keyof typeof RenderMode, RenderMode>;
27
+ export {};
@@ -0,0 +1,22 @@
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.RouteRenderMode = void 0;
11
+ /**
12
+ * Local copy of `RenderMode` exported from `@angular/ssr`.
13
+ * This constant is needed to handle interop between CommonJS (CJS) and ES Modules (ESM) formats.
14
+ *
15
+ * It maps `RenderMode` enum values to their corresponding numeric identifiers.
16
+ */
17
+ exports.RouteRenderMode = {
18
+ AppShell: 0,
19
+ Server: 1,
20
+ Client: 2,
21
+ Prerender: 3,
22
+ };
@@ -5,19 +5,35 @@
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 { NormalizedApplicationBuildOptions } from '../../builders/application/options';
9
+ import { OutputMode } from '../../builders/application/schema';
8
10
  import { BuildOutputFile } from '../../tools/esbuild/bundler-context';
9
11
  import { BuildOutputAsset } from '../../tools/esbuild/bundler-execution-result';
10
- interface PrerenderOptions {
11
- routesFile?: string;
12
- discoverRoutes?: boolean;
13
- }
14
- interface AppShellOptions {
15
- route?: string;
16
- }
17
- export declare function prerenderPages(workspaceRoot: string, appShellOptions: AppShellOptions | undefined, prerenderOptions: PrerenderOptions | undefined, outputFiles: Readonly<BuildOutputFile[]>, assets: Readonly<BuildOutputAsset[]>, document: string, sourcemap?: boolean, inlineCriticalCss?: boolean, maxThreads?: number, verbose?: boolean): Promise<{
18
- output: Record<string, string>;
12
+ import { SerializableRouteTreeNode } from './models';
13
+ type PrerenderOptions = NormalizedApplicationBuildOptions['prerenderOptions'];
14
+ type AppShellOptions = NormalizedApplicationBuildOptions['appShellOptions'];
15
+ /**
16
+ * Represents the output of a prerendering process.
17
+ *
18
+ * The key is the file path, and the value is an object containing the following properties:
19
+ *
20
+ * - `content`: The HTML content or output generated for the corresponding file path.
21
+ * - `appShellRoute`: A boolean flag indicating whether the content is an app shell.
22
+ *
23
+ * @example
24
+ * {
25
+ * '/index.html': { content: '<html>...</html>', appShell: false },
26
+ * '/shell/index.html': { content: '<html>...</html>', appShellRoute: true }
27
+ * }
28
+ */
29
+ type PrerenderOutput = Record<string, {
30
+ content: string;
31
+ appShellRoute: boolean;
32
+ }>;
33
+ export declare function prerenderPages(workspaceRoot: string, baseHref: string, appShellOptions: AppShellOptions | undefined, prerenderOptions: PrerenderOptions | undefined, outputFiles: Readonly<BuildOutputFile[]>, assets: Readonly<BuildOutputAsset[]>, outputMode: OutputMode | undefined, sourcemap?: boolean, maxThreads?: number): Promise<{
34
+ output: PrerenderOutput;
19
35
  warnings: string[];
20
36
  errors: string[];
21
- prerenderedRoutes: Set<string>;
37
+ serializableRouteTreeNode: SerializableRouteTreeNode;
22
38
  }>;
23
39
  export {};