@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.
- package/LICENSE +5 -5
- package/package.json +20 -16
- package/src/builders/application/build-action.js +9 -9
- package/src/builders/application/chunk-optimizer.js +1 -4
- package/src/builders/application/execute-build.js +19 -2
- package/src/builders/application/execute-post-bundle.d.ts +2 -2
- package/src/builders/application/execute-post-bundle.js +58 -20
- package/src/builders/application/i18n.d.ts +2 -2
- package/src/builders/application/i18n.js +6 -16
- package/src/builders/application/index.js +8 -5
- package/src/builders/application/options.d.ts +36 -1
- package/src/builders/application/options.js +60 -3
- package/src/builders/application/schema.d.ts +15 -0
- package/src/builders/application/schema.js +11 -1
- package/src/builders/application/schema.json +5 -0
- package/src/builders/application/setup-bundling.js +12 -9
- package/src/builders/dev-server/internal.d.ts +0 -1
- package/src/builders/dev-server/internal.js +1 -3
- package/src/builders/dev-server/vite-server.d.ts +8 -2
- package/src/builders/dev-server/vite-server.js +111 -56
- package/src/builders/extract-i18n/application-extraction.js +7 -3
- package/src/tools/angular/angular-host.d.ts +2 -1
- package/src/tools/angular/angular-host.js +20 -1
- package/src/tools/angular/compilation/angular-compilation.d.ts +1 -0
- package/src/tools/angular/compilation/aot-compilation.d.ts +1 -0
- package/src/tools/angular/compilation/aot-compilation.js +9 -1
- package/src/tools/angular/compilation/jit-compilation.js +2 -1
- package/src/tools/angular/compilation/parallel-compilation.d.ts +2 -1
- package/src/tools/angular/compilation/parallel-compilation.js +2 -10
- package/src/tools/angular/compilation/parallel-worker.d.ts +1 -0
- package/src/tools/angular/compilation/parallel-worker.js +2 -1
- package/src/tools/babel/plugins/add-code-coverage.d.ts +14 -0
- package/src/tools/babel/plugins/add-code-coverage.js +44 -0
- package/src/tools/babel/plugins/types.d.ts +20 -0
- package/src/tools/esbuild/angular/compiler-plugin.d.ts +2 -0
- package/src/tools/esbuild/angular/compiler-plugin.js +46 -4
- package/src/tools/esbuild/angular/component-stylesheets.d.ts +8 -3
- package/src/tools/esbuild/angular/component-stylesheets.js +46 -11
- package/src/tools/esbuild/angular/file-reference-tracker.d.ts +1 -1
- package/src/tools/esbuild/application-code-bundle.d.ts +2 -6
- package/src/tools/esbuild/application-code-bundle.js +208 -92
- package/src/tools/esbuild/budget-stats.js +1 -1
- package/src/tools/esbuild/bundler-context.d.ts +4 -3
- package/src/tools/esbuild/bundler-context.js +21 -13
- package/src/tools/esbuild/bundler-execution-result.d.ts +5 -2
- package/src/tools/esbuild/bundler-execution-result.js +7 -3
- package/src/tools/esbuild/cache.d.ts +6 -1
- package/src/tools/esbuild/cache.js +7 -0
- package/src/tools/esbuild/compiler-plugin-options.js +3 -1
- package/src/tools/esbuild/i18n-inliner.js +4 -4
- package/src/tools/esbuild/javascript-transformer-worker.d.ts +1 -0
- package/src/tools/esbuild/javascript-transformer-worker.js +5 -1
- package/src/tools/esbuild/javascript-transformer.d.ts +2 -2
- package/src/tools/esbuild/javascript-transformer.js +7 -12
- package/src/tools/esbuild/utils.d.ts +9 -0
- package/src/tools/esbuild/utils.js +21 -3
- package/src/tools/sass/sass-service.js +11 -13
- package/src/tools/sass/worker.d.ts +13 -32
- package/src/tools/sass/worker.js +1 -0
- package/src/tools/vite/middlewares/assets-middleware.d.ts +1 -1
- package/src/tools/vite/middlewares/assets-middleware.js +43 -4
- package/src/tools/vite/middlewares/headers-middleware.d.ts +19 -0
- package/src/tools/vite/middlewares/headers-middleware.js +34 -0
- package/src/tools/vite/middlewares/html-fallback-middleware.d.ts +1 -1
- package/src/tools/vite/middlewares/html-fallback-middleware.js +23 -7
- package/src/tools/vite/middlewares/index-html-middleware.js +1 -2
- package/src/tools/vite/middlewares/index.d.ts +2 -1
- package/src/tools/vite/middlewares/index.js +5 -2
- package/src/tools/vite/middlewares/ssr-middleware.d.ts +2 -4
- package/src/tools/vite/middlewares/ssr-middleware.js +75 -43
- package/src/tools/vite/plugins/angular-memory-plugin.d.ts +16 -0
- package/src/tools/vite/{angular-memory-plugin.js → plugins/angular-memory-plugin.js} +19 -40
- package/src/tools/vite/{i18n-locale-plugin.d.ts → plugins/i18n-locale-plugin.d.ts} +0 -4
- package/src/tools/vite/{i18n-locale-plugin.js → plugins/i18n-locale-plugin.js} +2 -3
- package/src/tools/vite/plugins/index.d.ts +12 -0
- package/src/tools/vite/plugins/index.js +21 -0
- package/src/tools/vite/plugins/setup-middlewares-plugin.d.ts +41 -0
- package/src/tools/vite/plugins/setup-middlewares-plugin.js +62 -0
- package/src/{utils/server-rendering/main-bundle-exports.js → tools/vite/plugins/ssr-transform-plugin.d.ts} +2 -2
- package/src/tools/vite/plugins/ssr-transform-plugin.js +38 -0
- package/src/tools/vite/utils.d.ts +0 -3
- package/src/tools/vite/utils.js +0 -12
- package/src/typings.d.ts +26 -0
- package/src/utils/environment-options.d.ts +2 -0
- package/src/utils/environment-options.js +5 -1
- package/src/utils/index-file/index-html-generator.js +5 -0
- package/src/utils/index-file/inline-critical-css.js +43 -33
- package/src/utils/index-file/ngcm-attribute.d.ts +15 -0
- package/src/utils/index-file/ngcm-attribute.js +37 -0
- package/src/utils/index-file/valid-self-closing-tags.js +28 -0
- package/src/utils/normalize-cache.js +1 -1
- package/src/utils/server-rendering/fetch-patch.d.ts +1 -1
- package/src/utils/server-rendering/fetch-patch.js +5 -6
- package/src/utils/server-rendering/launch-server.d.ts +14 -0
- package/src/utils/server-rendering/launch-server.js +63 -0
- package/src/utils/server-rendering/load-esm-from-memory.d.ts +18 -2
- package/src/utils/server-rendering/manifest.d.ts +50 -0
- package/src/utils/server-rendering/manifest.js +126 -0
- package/src/utils/server-rendering/models.d.ts +27 -0
- package/src/utils/server-rendering/models.js +22 -0
- package/src/utils/server-rendering/prerender.d.ts +26 -10
- package/src/utils/server-rendering/prerender.js +126 -67
- package/src/utils/server-rendering/render-worker.d.ts +9 -8
- package/src/utils/server-rendering/render-worker.js +19 -14
- package/src/utils/server-rendering/routes-extractor-worker.d.ts +6 -10
- package/src/utils/server-rendering/routes-extractor-worker.js +16 -33
- package/src/utils/server-rendering/utils.d.ts +11 -0
- package/src/utils/server-rendering/utils.js +17 -0
- package/src/utils/worker-pool.d.ts +12 -0
- package/src/utils/worker-pool.js +43 -0
- package/src/tools/vite/angular-memory-plugin.d.ts +0 -21
- package/src/utils/server-rendering/main-bundle-exports.d.ts +0 -27
- package/src/utils/server-rendering/render-page.d.ts +0 -26
- package/src/utils/server-rendering/render-page.js +0 -114
- /package/src/tools/vite/{id-prefix-plugin.d.ts → plugins/id-prefix-plugin.d.ts} +0 -0
- /package/src/tools/vite/{id-prefix-plugin.js → plugins/id-prefix-plugin.js} +0 -0
|
@@ -6,29 +6,31 @@
|
|
|
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
|
|
14
|
+
const schema_1 = require("../../builders/application/schema");
|
|
18
15
|
const bundler_context_1 = require("../../tools/esbuild/bundler-context");
|
|
19
|
-
|
|
16
|
+
const error_1 = require("../error");
|
|
17
|
+
const url_1 = require("../url");
|
|
18
|
+
const worker_pool_1 = require("../worker-pool");
|
|
19
|
+
const models_1 = require("./models");
|
|
20
|
+
async function prerenderPages(workspaceRoot, baseHref, appShellOptions, prerenderOptions, outputFiles, assets, outputMode, sourcemap = false, maxThreads = 1) {
|
|
20
21
|
const outputFilesForWorker = {};
|
|
21
22
|
const serverBundlesSourceMaps = new Map();
|
|
22
23
|
const warnings = [];
|
|
23
24
|
const errors = [];
|
|
24
25
|
for (const { text, path, type } of outputFiles) {
|
|
25
|
-
|
|
26
|
-
|
|
26
|
+
if (type !== bundler_context_1.BuildOutputFileType.ServerApplication && type !== bundler_context_1.BuildOutputFileType.ServerRoot) {
|
|
27
|
+
continue;
|
|
28
|
+
}
|
|
29
|
+
// Contains the server runnable application code
|
|
30
|
+
if ((0, node_path_1.extname)(path) === '.map') {
|
|
27
31
|
serverBundlesSourceMaps.set(path.slice(0, -4), text);
|
|
28
32
|
}
|
|
29
|
-
else
|
|
30
|
-
(type === bundler_context_1.BuildOutputFileType.Browser && fileExt === '.css') // Global styles for critical CSS inlining.
|
|
31
|
-
) {
|
|
33
|
+
else {
|
|
32
34
|
outputFilesForWorker[path] = text;
|
|
33
35
|
}
|
|
34
36
|
}
|
|
@@ -49,37 +51,58 @@ async function prerenderPages(workspaceRoot, appShellOptions = {}, prerenderOpti
|
|
|
49
51
|
assetsReversed[addLeadingSlash(destination.replace(/\\/g, node_path_1.posix.sep))] = source;
|
|
50
52
|
}
|
|
51
53
|
// Get routes to prerender
|
|
52
|
-
const {
|
|
53
|
-
|
|
54
|
-
|
|
54
|
+
const { errors: extractionErrors, serializedRouteTree: serializableRouteTreeNode } = await getAllRoutes(workspaceRoot, baseHref, outputFilesForWorker, assetsReversed, appShellOptions, prerenderOptions, sourcemap, outputMode).catch((err) => {
|
|
55
|
+
return {
|
|
56
|
+
errors: [
|
|
57
|
+
`An error occurred while extracting routes.\n\n${err.stack ?? err.message ?? err}`,
|
|
58
|
+
],
|
|
59
|
+
serializedRouteTree: [],
|
|
60
|
+
};
|
|
61
|
+
});
|
|
62
|
+
errors.push(...extractionErrors);
|
|
63
|
+
const serializableRouteTreeNodeForPrerender = [];
|
|
64
|
+
for (const metadata of serializableRouteTreeNode) {
|
|
65
|
+
if (outputMode !== schema_1.OutputMode.Static && metadata.redirectTo) {
|
|
66
|
+
// Skip redirects if output mode is not static.
|
|
67
|
+
continue;
|
|
68
|
+
}
|
|
69
|
+
if (metadata.route.includes('*')) {
|
|
70
|
+
// Skip catch all routes from prerender.
|
|
71
|
+
continue;
|
|
72
|
+
}
|
|
73
|
+
switch (metadata.renderMode) {
|
|
74
|
+
case undefined: /* Legacy building mode */
|
|
75
|
+
case models_1.RouteRenderMode.Prerender:
|
|
76
|
+
case models_1.RouteRenderMode.AppShell:
|
|
77
|
+
serializableRouteTreeNodeForPrerender.push(metadata);
|
|
78
|
+
break;
|
|
79
|
+
case models_1.RouteRenderMode.Server:
|
|
80
|
+
if (outputMode === schema_1.OutputMode.Static) {
|
|
81
|
+
errors.push(`Route '${metadata.route}' is configured with server render mode, but the build 'outputMode' is set to 'static'.`);
|
|
82
|
+
}
|
|
83
|
+
break;
|
|
84
|
+
}
|
|
55
85
|
}
|
|
56
|
-
if (
|
|
86
|
+
if (!serializableRouteTreeNodeForPrerender.length || errors.length > 0) {
|
|
57
87
|
return {
|
|
58
88
|
errors,
|
|
59
89
|
warnings,
|
|
60
90
|
output: {},
|
|
61
|
-
|
|
91
|
+
serializableRouteTreeNode,
|
|
62
92
|
};
|
|
63
93
|
}
|
|
64
94
|
// Render routes
|
|
65
|
-
const {
|
|
95
|
+
const { errors: renderingErrors, output } = await renderPages(baseHref, sourcemap, serializableRouteTreeNodeForPrerender, maxThreads, workspaceRoot, outputFilesForWorker, assetsReversed, appShellOptions, outputMode);
|
|
66
96
|
errors.push(...renderingErrors);
|
|
67
|
-
warnings.push(...renderingWarnings);
|
|
68
97
|
return {
|
|
69
98
|
errors,
|
|
70
99
|
warnings,
|
|
71
100
|
output,
|
|
72
|
-
|
|
101
|
+
serializableRouteTreeNode,
|
|
73
102
|
};
|
|
74
103
|
}
|
|
75
|
-
|
|
76
|
-
add(value) {
|
|
77
|
-
return super.add(addLeadingSlash(value));
|
|
78
|
-
}
|
|
79
|
-
}
|
|
80
|
-
async function renderPages(sourcemap, allRoutes, maxThreads, workspaceRoot, outputFilesForWorker, assetFilesForWorker, inlineCriticalCss, document, appShellOptions) {
|
|
104
|
+
async function renderPages(baseHref, sourcemap, serializableRouteTreeNode, maxThreads, workspaceRoot, outputFilesForWorker, assetFilesForWorker, appShellOptions, outputMode) {
|
|
81
105
|
const output = {};
|
|
82
|
-
const warnings = [];
|
|
83
106
|
const errors = [];
|
|
84
107
|
const workerExecArgv = [
|
|
85
108
|
'--import',
|
|
@@ -89,39 +112,43 @@ async function renderPages(sourcemap, allRoutes, maxThreads, workspaceRoot, outp
|
|
|
89
112
|
if (sourcemap) {
|
|
90
113
|
workerExecArgv.push('--enable-source-maps');
|
|
91
114
|
}
|
|
92
|
-
const renderWorker = new
|
|
115
|
+
const renderWorker = new worker_pool_1.WorkerPool({
|
|
93
116
|
filename: require.resolve('./render-worker'),
|
|
94
|
-
maxThreads: Math.min(
|
|
117
|
+
maxThreads: Math.min(serializableRouteTreeNode.length, maxThreads),
|
|
95
118
|
workerData: {
|
|
96
119
|
workspaceRoot,
|
|
97
120
|
outputFiles: outputFilesForWorker,
|
|
98
121
|
assetFiles: assetFilesForWorker,
|
|
99
|
-
|
|
100
|
-
|
|
122
|
+
outputMode,
|
|
123
|
+
hasSsrEntry: !!outputFilesForWorker['server.mjs'],
|
|
101
124
|
},
|
|
102
125
|
execArgv: workerExecArgv,
|
|
103
|
-
recordTiming: false,
|
|
104
126
|
});
|
|
105
127
|
try {
|
|
106
128
|
const renderingPromises = [];
|
|
107
|
-
const appShellRoute = appShellOptions
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
const
|
|
112
|
-
const
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
129
|
+
const appShellRoute = appShellOptions && addLeadingSlash(appShellOptions.route);
|
|
130
|
+
const baseHrefWithLeadingSlash = addLeadingSlash(baseHref);
|
|
131
|
+
for (const { route, redirectTo, renderMode } of serializableRouteTreeNode) {
|
|
132
|
+
// Remove base href from file output path.
|
|
133
|
+
const routeWithoutBaseHref = addLeadingSlash(route.slice(baseHrefWithLeadingSlash.length - 1));
|
|
134
|
+
const outPath = node_path_1.posix.join(removeLeadingSlash(routeWithoutBaseHref), 'index.html');
|
|
135
|
+
if (typeof redirectTo === 'string') {
|
|
136
|
+
output[outPath] = { content: generateRedirectStaticPage(redirectTo), appShellRoute: false };
|
|
137
|
+
continue;
|
|
138
|
+
}
|
|
139
|
+
const isAppShellRoute = renderMode === models_1.RouteRenderMode.AppShell ||
|
|
140
|
+
// Legacy handling
|
|
141
|
+
(renderMode === undefined && appShellRoute === routeWithoutBaseHref);
|
|
142
|
+
const render = renderWorker.run({ url: route, isAppShellRoute });
|
|
143
|
+
const renderResult = render
|
|
144
|
+
.then((content) => {
|
|
145
|
+
if (content !== null) {
|
|
146
|
+
output[outPath] = { content, appShellRoute: isAppShellRoute };
|
|
124
147
|
}
|
|
148
|
+
})
|
|
149
|
+
.catch((err) => {
|
|
150
|
+
errors.push(`An error occurred while prerendering route '${route}'.\n\n${err.stack ?? err.message ?? err.code ?? err}`);
|
|
151
|
+
void renderWorker.destroy();
|
|
125
152
|
});
|
|
126
153
|
renderingPromises.push(renderResult);
|
|
127
154
|
}
|
|
@@ -132,25 +159,27 @@ async function renderPages(sourcemap, allRoutes, maxThreads, workspaceRoot, outp
|
|
|
132
159
|
}
|
|
133
160
|
return {
|
|
134
161
|
errors,
|
|
135
|
-
warnings,
|
|
136
162
|
output,
|
|
137
163
|
};
|
|
138
164
|
}
|
|
139
|
-
async function getAllRoutes(workspaceRoot, outputFilesForWorker, assetFilesForWorker,
|
|
140
|
-
const { routesFile, discoverRoutes } = prerenderOptions;
|
|
141
|
-
const routes =
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
165
|
+
async function getAllRoutes(workspaceRoot, baseHref, outputFilesForWorker, assetFilesForWorker, appShellOptions, prerenderOptions, sourcemap, outputMode) {
|
|
166
|
+
const { routesFile, discoverRoutes } = prerenderOptions ?? {};
|
|
167
|
+
const routes = [];
|
|
168
|
+
if (appShellOptions) {
|
|
169
|
+
routes.push({
|
|
170
|
+
route: (0, url_1.urlJoin)(baseHref, appShellOptions.route),
|
|
171
|
+
});
|
|
145
172
|
}
|
|
146
173
|
if (routesFile) {
|
|
147
174
|
const routesFromFile = (await (0, promises_1.readFile)(routesFile, 'utf8')).split(/\r?\n/);
|
|
148
175
|
for (const route of routesFromFile) {
|
|
149
|
-
routes.
|
|
176
|
+
routes.push({
|
|
177
|
+
route: (0, url_1.urlJoin)(baseHref, route.trim()),
|
|
178
|
+
});
|
|
150
179
|
}
|
|
151
180
|
}
|
|
152
181
|
if (!discoverRoutes) {
|
|
153
|
-
return { routes };
|
|
182
|
+
return { errors: [], serializedRouteTree: routes };
|
|
154
183
|
}
|
|
155
184
|
const workerExecArgv = [
|
|
156
185
|
'--import',
|
|
@@ -160,28 +189,34 @@ async function getAllRoutes(workspaceRoot, outputFilesForWorker, assetFilesForWo
|
|
|
160
189
|
if (sourcemap) {
|
|
161
190
|
workerExecArgv.push('--enable-source-maps');
|
|
162
191
|
}
|
|
163
|
-
const renderWorker = new
|
|
192
|
+
const renderWorker = new worker_pool_1.WorkerPool({
|
|
164
193
|
filename: require.resolve('./routes-extractor-worker'),
|
|
165
194
|
maxThreads: 1,
|
|
166
195
|
workerData: {
|
|
167
196
|
workspaceRoot,
|
|
168
197
|
outputFiles: outputFilesForWorker,
|
|
169
198
|
assetFiles: assetFilesForWorker,
|
|
170
|
-
|
|
171
|
-
|
|
199
|
+
outputMode,
|
|
200
|
+
hasSsrEntry: !!outputFilesForWorker['server.mjs'],
|
|
172
201
|
},
|
|
173
202
|
execArgv: workerExecArgv,
|
|
174
|
-
recordTiming: false,
|
|
175
203
|
});
|
|
176
|
-
|
|
177
|
-
.run({})
|
|
178
|
-
|
|
204
|
+
try {
|
|
205
|
+
const { serializedRouteTree, errors } = await renderWorker.run({});
|
|
206
|
+
return { errors, serializedRouteTree: [...routes, ...serializedRouteTree] };
|
|
207
|
+
}
|
|
208
|
+
catch (err) {
|
|
209
|
+
(0, error_1.assertIsError)(err);
|
|
210
|
+
return {
|
|
211
|
+
errors: [
|
|
212
|
+
`An error occurred while extracting routes.\n\n${err.stack ?? err.message ?? err.code ?? err}`,
|
|
213
|
+
],
|
|
214
|
+
serializedRouteTree: [],
|
|
215
|
+
};
|
|
216
|
+
}
|
|
217
|
+
finally {
|
|
179
218
|
void renderWorker.destroy();
|
|
180
|
-
});
|
|
181
|
-
for (const route of extractedRoutes) {
|
|
182
|
-
routes.add(route);
|
|
183
219
|
}
|
|
184
|
-
return { routes, warnings };
|
|
185
220
|
}
|
|
186
221
|
function addLeadingSlash(value) {
|
|
187
222
|
return value.charAt(0) === '/' ? value : '/' + value;
|
|
@@ -189,3 +224,27 @@ function addLeadingSlash(value) {
|
|
|
189
224
|
function removeLeadingSlash(value) {
|
|
190
225
|
return value.charAt(0) === '/' ? value.slice(1) : value;
|
|
191
226
|
}
|
|
227
|
+
/**
|
|
228
|
+
* Generates a static HTML page with a meta refresh tag to redirect the user to a specified URL.
|
|
229
|
+
*
|
|
230
|
+
* This function creates a simple HTML page that performs a redirect using a meta tag.
|
|
231
|
+
* It includes a fallback link in case the meta-refresh doesn't work.
|
|
232
|
+
*
|
|
233
|
+
* @param url - The URL to which the page should redirect.
|
|
234
|
+
* @returns The HTML content of the static redirect page.
|
|
235
|
+
*/
|
|
236
|
+
function generateRedirectStaticPage(url) {
|
|
237
|
+
return `
|
|
238
|
+
<!DOCTYPE html>
|
|
239
|
+
<html>
|
|
240
|
+
<head>
|
|
241
|
+
<meta charset="utf-8">
|
|
242
|
+
<title>Redirecting</title>
|
|
243
|
+
<meta http-equiv="refresh" content="0; url=${url}">
|
|
244
|
+
</head>
|
|
245
|
+
<body>
|
|
246
|
+
<pre>Redirecting to <a href="${url}">${url}</a></pre>
|
|
247
|
+
</body>
|
|
248
|
+
</html>
|
|
249
|
+
`.trim();
|
|
250
|
+
}
|
|
@@ -5,18 +5,19 @@
|
|
|
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 { OutputMode } from '../../builders/application/schema';
|
|
8
9
|
import type { ESMInMemoryFileLoaderWorkerData } from './esm-in-memory-loader/loader-hooks';
|
|
9
|
-
import { RenderResult, ServerContext } from './render-page';
|
|
10
10
|
export interface RenderWorkerData extends ESMInMemoryFileLoaderWorkerData {
|
|
11
|
-
document: string;
|
|
12
|
-
inlineCriticalCss?: boolean;
|
|
13
11
|
assetFiles: Record</** Destination */ string, /** Source */ string>;
|
|
12
|
+
outputMode: OutputMode | undefined;
|
|
13
|
+
hasSsrEntry: boolean;
|
|
14
14
|
}
|
|
15
15
|
export interface RenderOptions {
|
|
16
|
-
|
|
17
|
-
serverContext: ServerContext;
|
|
16
|
+
url: string;
|
|
18
17
|
}
|
|
19
|
-
/**
|
|
20
|
-
|
|
21
|
-
|
|
18
|
+
/**
|
|
19
|
+
* Renders each route in routes and writes them to <outputPath>/<route>/index.html.
|
|
20
|
+
*/
|
|
21
|
+
declare function renderPage({ url }: RenderOptions): Promise<string | null>;
|
|
22
|
+
declare const _default: Promise<typeof renderPage>;
|
|
22
23
|
export default _default;
|
|
@@ -7,24 +7,29 @@
|
|
|
7
7
|
* found in the LICENSE file at https://angular.dev/license
|
|
8
8
|
*/
|
|
9
9
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
10
|
-
const
|
|
10
|
+
const worker_threads_1 = require("worker_threads");
|
|
11
11
|
const fetch_patch_1 = require("./fetch-patch");
|
|
12
|
-
const
|
|
12
|
+
const launch_server_1 = require("./launch-server");
|
|
13
|
+
const load_esm_from_memory_1 = require("./load-esm-from-memory");
|
|
13
14
|
/**
|
|
14
15
|
* This is passed as workerData when setting up the worker via the `piscina` package.
|
|
15
16
|
*/
|
|
16
|
-
const {
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
17
|
+
const { outputMode, hasSsrEntry } = worker_threads_1.workerData;
|
|
18
|
+
let serverURL = launch_server_1.DEFAULT_URL;
|
|
19
|
+
/**
|
|
20
|
+
* Renders each route in routes and writes them to <outputPath>/<route>/index.html.
|
|
21
|
+
*/
|
|
22
|
+
async function renderPage({ url }) {
|
|
23
|
+
const { ɵgetOrCreateAngularServerApp: getOrCreateAngularServerApp } = await (0, load_esm_from_memory_1.loadEsmModuleFromMemory)('./main.server.mjs');
|
|
24
|
+
const angularServerApp = getOrCreateAngularServerApp();
|
|
25
|
+
const response = await angularServerApp.renderStatic(new URL(url, serverURL), AbortSignal.timeout(30_000));
|
|
26
|
+
return response ? response.text() : null;
|
|
25
27
|
}
|
|
26
|
-
function initialize() {
|
|
27
|
-
(
|
|
28
|
-
|
|
28
|
+
async function initialize() {
|
|
29
|
+
if (outputMode !== undefined && hasSsrEntry) {
|
|
30
|
+
serverURL = await (0, launch_server_1.launchServer)();
|
|
31
|
+
}
|
|
32
|
+
(0, fetch_patch_1.patchFetchToLoadInMemoryAssets)(serverURL);
|
|
33
|
+
return renderPage;
|
|
29
34
|
}
|
|
30
35
|
exports.default = initialize();
|
|
@@ -5,17 +5,13 @@
|
|
|
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
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
}
|
|
14
|
-
export interface RoutersExtractorWorkerResult {
|
|
15
|
-
routes: string[];
|
|
16
|
-
warnings?: string[];
|
|
8
|
+
import { OutputMode } from '../../builders/application/schema';
|
|
9
|
+
import { ESMInMemoryFileLoaderWorkerData } from './esm-in-memory-loader/loader-hooks';
|
|
10
|
+
import { RoutersExtractorWorkerResult } from './models';
|
|
11
|
+
export interface ExtractRoutesWorkerData extends ESMInMemoryFileLoaderWorkerData {
|
|
12
|
+
outputMode: OutputMode | undefined;
|
|
17
13
|
}
|
|
18
14
|
/** Renders an application based on a provided options. */
|
|
19
15
|
declare function extractRoutes(): Promise<RoutersExtractorWorkerResult>;
|
|
20
|
-
declare const _default: typeof extractRoutes
|
|
16
|
+
declare const _default: Promise<typeof extractRoutes>;
|
|
21
17
|
export default _default;
|
|
@@ -7,47 +7,30 @@
|
|
|
7
7
|
* found in the LICENSE file at https://angular.dev/license
|
|
8
8
|
*/
|
|
9
9
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
10
|
-
const
|
|
10
|
+
const worker_threads_1 = require("worker_threads");
|
|
11
|
+
const schema_1 = require("../../builders/application/schema");
|
|
11
12
|
const fetch_patch_1 = require("./fetch-patch");
|
|
13
|
+
const launch_server_1 = require("./launch-server");
|
|
12
14
|
const load_esm_from_memory_1 = require("./load-esm-from-memory");
|
|
13
15
|
/**
|
|
14
16
|
* This is passed as workerData when setting up the worker via the `piscina` package.
|
|
15
17
|
*/
|
|
16
|
-
const {
|
|
18
|
+
const { outputMode, hasSsrEntry } = worker_threads_1.workerData;
|
|
19
|
+
let serverURL = launch_server_1.DEFAULT_URL;
|
|
17
20
|
/** Renders an application based on a provided options. */
|
|
18
21
|
async function extractRoutes() {
|
|
19
|
-
const {
|
|
20
|
-
const {
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
for (const { route, redirectTo } of extractRoutes) {
|
|
26
|
-
if (redirectTo !== undefined) {
|
|
27
|
-
skippedRedirects.push(route);
|
|
28
|
-
}
|
|
29
|
-
else if (/[:*]/.test(route)) {
|
|
30
|
-
skippedOthers.push(route);
|
|
31
|
-
}
|
|
32
|
-
else {
|
|
33
|
-
routes.push(route);
|
|
34
|
-
}
|
|
35
|
-
}
|
|
36
|
-
if (!verbose) {
|
|
37
|
-
return { routes };
|
|
38
|
-
}
|
|
39
|
-
let warnings;
|
|
40
|
-
if (skippedOthers.length) {
|
|
41
|
-
(warnings ??= []).push('The following routes were skipped from prerendering because they contain routes with dynamic parameters:\n' +
|
|
42
|
-
skippedOthers.join('\n'));
|
|
43
|
-
}
|
|
44
|
-
if (skippedRedirects.length) {
|
|
45
|
-
(warnings ??= []).push('The following routes were skipped from prerendering because they contain redirects:\n', skippedRedirects.join('\n'));
|
|
46
|
-
}
|
|
47
|
-
return { routes, warnings };
|
|
22
|
+
const { ɵextractRoutesAndCreateRouteTree: extractRoutesAndCreateRouteTree } = await (0, load_esm_from_memory_1.loadEsmModuleFromMemory)('./main.server.mjs');
|
|
23
|
+
const { routeTree, errors } = await extractRoutesAndCreateRouteTree(serverURL, undefined /** manifest */, true /** invokeGetPrerenderParams */, outputMode === schema_1.OutputMode.Server /** includePrerenderFallbackRoutes */);
|
|
24
|
+
return {
|
|
25
|
+
errors,
|
|
26
|
+
serializedRouteTree: routeTree.toObject(),
|
|
27
|
+
};
|
|
48
28
|
}
|
|
49
|
-
function initialize() {
|
|
50
|
-
(
|
|
29
|
+
async function initialize() {
|
|
30
|
+
if (outputMode !== undefined && hasSsrEntry) {
|
|
31
|
+
serverURL = await (0, launch_server_1.launchServer)();
|
|
32
|
+
}
|
|
33
|
+
(0, fetch_patch_1.patchFetchToLoadInMemoryAssets)(serverURL);
|
|
51
34
|
return extractRoutes;
|
|
52
35
|
}
|
|
53
36
|
exports.default = initialize();
|
|
@@ -0,0 +1,11 @@
|
|
|
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 { createRequestHandler } from '@angular/ssr';
|
|
9
|
+
import type { createNodeRequestHandler } from '@angular/ssr/node';
|
|
10
|
+
export declare function isSsrNodeRequestHandler(value: unknown): value is ReturnType<typeof createNodeRequestHandler>;
|
|
11
|
+
export declare function isSsrRequestHandler(value: unknown): value is ReturnType<typeof createRequestHandler>;
|
|
@@ -0,0 +1,17 @@
|
|
|
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.isSsrNodeRequestHandler = isSsrNodeRequestHandler;
|
|
11
|
+
exports.isSsrRequestHandler = isSsrRequestHandler;
|
|
12
|
+
function isSsrNodeRequestHandler(value) {
|
|
13
|
+
return typeof value === 'function' && '__ng_node_request_handler__' in value;
|
|
14
|
+
}
|
|
15
|
+
function isSsrRequestHandler(value) {
|
|
16
|
+
return typeof value === 'function' && '__ng_request_handler__' in value;
|
|
17
|
+
}
|
|
@@ -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;
|
|
@@ -1,21 +0,0 @@
|
|
|
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, Plugin } from 'vite';
|
|
9
|
-
import { AngularMemoryOutputFiles } from './utils';
|
|
10
|
-
export interface AngularMemoryPluginOptions {
|
|
11
|
-
workspaceRoot: string;
|
|
12
|
-
virtualProjectRoot: string;
|
|
13
|
-
outputFiles: AngularMemoryOutputFiles;
|
|
14
|
-
assets: Map<string, string>;
|
|
15
|
-
ssr: boolean;
|
|
16
|
-
external?: string[];
|
|
17
|
-
extensionMiddleware?: Connect.NextHandleFunction[];
|
|
18
|
-
indexHtmlTransformer?: (content: string) => Promise<string>;
|
|
19
|
-
normalizePath: (path: string) => string;
|
|
20
|
-
}
|
|
21
|
-
export declare function createAngularMemoryPlugin(options: AngularMemoryPluginOptions): Plugin;
|
|
@@ -1,27 +0,0 @@
|
|
|
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 { ApplicationRef, Type, ɵConsole } from '@angular/core';
|
|
9
|
-
import type { renderApplication, renderModule, ɵSERVER_CONTEXT } from '@angular/platform-server';
|
|
10
|
-
import type { ɵgetRoutesFromAngularRouterConfig } from '@angular/ssr';
|
|
11
|
-
export interface MainServerBundleExports {
|
|
12
|
-
/** Standalone application bootstrapping function. */
|
|
13
|
-
default: (() => Promise<ApplicationRef>) | Type<unknown>;
|
|
14
|
-
}
|
|
15
|
-
export interface RenderUtilsServerBundleExports {
|
|
16
|
-
/** An internal token that allows providing extra information about the server context. */
|
|
17
|
-
ɵSERVER_CONTEXT: typeof ɵSERVER_CONTEXT;
|
|
18
|
-
/** Render an NgModule application. */
|
|
19
|
-
renderModule: typeof renderModule;
|
|
20
|
-
/** Method to render a standalone application. */
|
|
21
|
-
renderApplication: typeof renderApplication;
|
|
22
|
-
/** Method to extract routes from the router config. */
|
|
23
|
-
ɵgetRoutesFromAngularRouterConfig: typeof ɵgetRoutesFromAngularRouterConfig;
|
|
24
|
-
ɵresetCompiledComponents?: () => void;
|
|
25
|
-
/** Angular Console token/class. */
|
|
26
|
-
ɵConsole: typeof ɵConsole;
|
|
27
|
-
}
|
|
@@ -1,26 +0,0 @@
|
|
|
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 { MainServerBundleExports, RenderUtilsServerBundleExports } from './main-bundle-exports';
|
|
9
|
-
export interface RenderOptions {
|
|
10
|
-
route: string;
|
|
11
|
-
serverContext: ServerContext;
|
|
12
|
-
outputFiles: Record<string, string>;
|
|
13
|
-
document: string;
|
|
14
|
-
inlineCriticalCss?: boolean;
|
|
15
|
-
loadBundle?: ((path: './main.server.mjs') => Promise<MainServerBundleExports>) & ((path: './render-utils.server.mjs') => Promise<RenderUtilsServerBundleExports>);
|
|
16
|
-
}
|
|
17
|
-
export interface RenderResult {
|
|
18
|
-
errors?: string[];
|
|
19
|
-
warnings?: string[];
|
|
20
|
-
content?: string;
|
|
21
|
-
}
|
|
22
|
-
export type ServerContext = 'app-shell' | 'ssg' | 'ssr';
|
|
23
|
-
/**
|
|
24
|
-
* Renders each route in routes and writes them to <outputPath>/<route>/index.html.
|
|
25
|
-
*/
|
|
26
|
-
export declare function renderPage({ route, serverContext, document, inlineCriticalCss, outputFiles, loadBundle, }: RenderOptions): Promise<RenderResult>;
|