@angular/build 19.0.0-next.7 → 19.0.0-next.8
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/package.json +9 -9
- 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 +30 -11
- package/src/builders/application/i18n.d.ts +2 -2
- package/src/builders/application/i18n.js +4 -5
- package/src/builders/application/index.js +8 -5
- package/src/builders/application/options.d.ts +18 -1
- package/src/builders/application/options.js +30 -2
- 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 +6 -3
- package/src/builders/dev-server/vite-server.d.ts +2 -1
- package/src/builders/dev-server/vite-server.js +64 -47
- package/src/builders/extract-i18n/application-extraction.js +3 -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/parallel-compilation.d.ts +1 -0
- package/src/tools/angular/compilation/parallel-worker.d.ts +1 -0
- package/src/tools/angular/compilation/parallel-worker.js +2 -1
- package/src/tools/esbuild/angular/compiler-plugin.d.ts +1 -0
- package/src/tools/esbuild/angular/compiler-plugin.js +42 -3
- 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/application-code-bundle.d.ts +1 -0
- package/src/tools/esbuild/application-code-bundle.js +109 -2
- 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 +8 -4
- 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 +5 -0
- package/src/tools/esbuild/cache.js +7 -0
- package/src/tools/esbuild/compiler-plugin-options.js +2 -1
- package/src/tools/esbuild/i18n-inliner.js +2 -1
- package/src/tools/esbuild/utils.js +7 -3
- package/src/tools/vite/middlewares/assets-middleware.js +2 -5
- package/src/tools/vite/middlewares/html-fallback-middleware.js +22 -6
- package/src/tools/vite/middlewares/index.d.ts +1 -1
- package/src/tools/vite/middlewares/index.js +3 -2
- package/src/tools/vite/middlewares/ssr-middleware.d.ts +2 -1
- package/src/tools/vite/middlewares/ssr-middleware.js +61 -15
- 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 -41
- 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/tools/vite/plugins/ssr-transform-plugin.d.ts +9 -0
- package/src/tools/vite/plugins/ssr-transform-plugin.js +38 -0
- package/src/utils/environment-options.d.ts +2 -0
- package/src/utils/environment-options.js +5 -1
- package/src/utils/index-file/valid-self-closing-tags.js +1 -0
- package/src/utils/normalize-cache.js +1 -1
- package/src/utils/server-rendering/manifest.d.ts +8 -2
- package/src/utils/server-rendering/manifest.js +61 -12
- 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 +6 -10
- package/src/utils/server-rendering/prerender.js +100 -63
- package/src/utils/server-rendering/routes-extractor-worker.d.ts +5 -10
- package/src/utils/server-rendering/routes-extractor-worker.js +3 -4
- package/src/tools/vite/angular-memory-plugin.d.ts +0 -22
- /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
|
@@ -11,16 +11,19 @@ exports.prerenderPages = prerenderPages;
|
|
|
11
11
|
const promises_1 = require("node:fs/promises");
|
|
12
12
|
const node_path_1 = require("node:path");
|
|
13
13
|
const node_url_1 = require("node:url");
|
|
14
|
+
const schema_1 = require("../../builders/application/schema");
|
|
14
15
|
const bundler_context_1 = require("../../tools/esbuild/bundler-context");
|
|
16
|
+
const error_1 = require("../error");
|
|
15
17
|
const url_1 = require("../url");
|
|
16
18
|
const worker_pool_1 = require("../worker-pool");
|
|
17
|
-
|
|
19
|
+
const models_1 = require("./models");
|
|
20
|
+
async function prerenderPages(workspaceRoot, baseHref, appShellOptions, prerenderOptions, outputFiles, assets, outputMode, sourcemap = false, maxThreads = 1) {
|
|
18
21
|
const outputFilesForWorker = {};
|
|
19
22
|
const serverBundlesSourceMaps = new Map();
|
|
20
23
|
const warnings = [];
|
|
21
24
|
const errors = [];
|
|
22
25
|
for (const { text, path, type } of outputFiles) {
|
|
23
|
-
if (type !== bundler_context_1.BuildOutputFileType.
|
|
26
|
+
if (type !== bundler_context_1.BuildOutputFileType.ServerApplication && type !== bundler_context_1.BuildOutputFileType.ServerRoot) {
|
|
24
27
|
continue;
|
|
25
28
|
}
|
|
26
29
|
// Contains the server runnable application code
|
|
@@ -48,39 +51,57 @@ async function prerenderPages(workspaceRoot, baseHref, appShellOptions = {}, pre
|
|
|
48
51
|
assetsReversed[addLeadingSlash(destination.replace(/\\/g, node_path_1.posix.sep))] = source;
|
|
49
52
|
}
|
|
50
53
|
// Get routes to prerender
|
|
51
|
-
const {
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
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
|
+
}
|
|
57
85
|
}
|
|
58
|
-
if (
|
|
86
|
+
if (!serializableRouteTreeNodeForPrerender.length || errors.length > 0) {
|
|
59
87
|
return {
|
|
60
88
|
errors,
|
|
61
89
|
warnings,
|
|
62
90
|
output: {},
|
|
63
91
|
serializableRouteTreeNode,
|
|
64
|
-
prerenderedRoutes: allRoutes,
|
|
65
92
|
};
|
|
66
93
|
}
|
|
67
94
|
// Render routes
|
|
68
|
-
const { errors: renderingErrors, output } = await renderPages(baseHref, sourcemap,
|
|
95
|
+
const { errors: renderingErrors, output } = await renderPages(baseHref, sourcemap, serializableRouteTreeNodeForPrerender, maxThreads, workspaceRoot, outputFilesForWorker, assetsReversed, appShellOptions);
|
|
69
96
|
errors.push(...renderingErrors);
|
|
70
97
|
return {
|
|
71
98
|
errors,
|
|
72
99
|
warnings,
|
|
73
100
|
output,
|
|
74
101
|
serializableRouteTreeNode,
|
|
75
|
-
prerenderedRoutes: allRoutes,
|
|
76
102
|
};
|
|
77
103
|
}
|
|
78
|
-
|
|
79
|
-
add(value) {
|
|
80
|
-
return super.add(addLeadingSlash(value));
|
|
81
|
-
}
|
|
82
|
-
}
|
|
83
|
-
async function renderPages(baseHref, sourcemap, allRoutes, maxThreads, workspaceRoot, outputFilesForWorker, assetFilesForWorker, appShellOptions) {
|
|
104
|
+
async function renderPages(baseHref, sourcemap, serializableRouteTreeNode, maxThreads, workspaceRoot, outputFilesForWorker, assetFilesForWorker, appShellOptions) {
|
|
84
105
|
const output = {};
|
|
85
106
|
const errors = [];
|
|
86
107
|
const workerExecArgv = [
|
|
@@ -93,7 +114,7 @@ async function renderPages(baseHref, sourcemap, allRoutes, maxThreads, workspace
|
|
|
93
114
|
}
|
|
94
115
|
const renderWorker = new worker_pool_1.WorkerPool({
|
|
95
116
|
filename: require.resolve('./render-worker'),
|
|
96
|
-
maxThreads: Math.min(
|
|
117
|
+
maxThreads: Math.min(serializableRouteTreeNode.length, maxThreads),
|
|
97
118
|
workerData: {
|
|
98
119
|
workspaceRoot,
|
|
99
120
|
outputFiles: outputFilesForWorker,
|
|
@@ -103,17 +124,23 @@ async function renderPages(baseHref, sourcemap, allRoutes, maxThreads, workspace
|
|
|
103
124
|
});
|
|
104
125
|
try {
|
|
105
126
|
const renderingPromises = [];
|
|
106
|
-
const appShellRoute = appShellOptions
|
|
127
|
+
const appShellRoute = appShellOptions && addLeadingSlash(appShellOptions.route);
|
|
107
128
|
const baseHrefWithLeadingSlash = addLeadingSlash(baseHref);
|
|
108
|
-
for (const route of
|
|
129
|
+
for (const { route, redirectTo, renderMode } of serializableRouteTreeNode) {
|
|
109
130
|
// Remove base href from file output path.
|
|
110
131
|
const routeWithoutBaseHref = addLeadingSlash(route.slice(baseHrefWithLeadingSlash.length - 1));
|
|
111
|
-
const
|
|
132
|
+
const outPath = node_path_1.posix.join(removeLeadingSlash(routeWithoutBaseHref), 'index.html');
|
|
133
|
+
if (typeof redirectTo === 'string') {
|
|
134
|
+
output[outPath] = { content: generateRedirectStaticPage(redirectTo), appShellRoute: false };
|
|
135
|
+
continue;
|
|
136
|
+
}
|
|
137
|
+
const isAppShellRoute = renderMode === models_1.RouteRenderMode.AppShell ||
|
|
138
|
+
// Legacy handling
|
|
139
|
+
(renderMode === undefined && appShellRoute === routeWithoutBaseHref);
|
|
140
|
+
const render = renderWorker.run({ url: route, isAppShellRoute });
|
|
112
141
|
const renderResult = render
|
|
113
142
|
.then((content) => {
|
|
114
143
|
if (content !== null) {
|
|
115
|
-
const outPath = node_path_1.posix.join(removeLeadingSlash(routeWithoutBaseHref), 'index.html');
|
|
116
|
-
const isAppShellRoute = appShellRoute === routeWithoutBaseHref;
|
|
117
144
|
output[outPath] = { content, appShellRoute: isAppShellRoute };
|
|
118
145
|
}
|
|
119
146
|
})
|
|
@@ -133,21 +160,24 @@ async function renderPages(baseHref, sourcemap, allRoutes, maxThreads, workspace
|
|
|
133
160
|
output,
|
|
134
161
|
};
|
|
135
162
|
}
|
|
136
|
-
async function getAllRoutes(workspaceRoot, baseHref, outputFilesForWorker, assetFilesForWorker, appShellOptions, prerenderOptions, sourcemap,
|
|
137
|
-
const { routesFile, discoverRoutes } = prerenderOptions;
|
|
138
|
-
const routes =
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
163
|
+
async function getAllRoutes(workspaceRoot, baseHref, outputFilesForWorker, assetFilesForWorker, appShellOptions, prerenderOptions, sourcemap, outputMode) {
|
|
164
|
+
const { routesFile, discoverRoutes } = prerenderOptions ?? {};
|
|
165
|
+
const routes = [];
|
|
166
|
+
if (appShellOptions) {
|
|
167
|
+
routes.push({
|
|
168
|
+
route: (0, url_1.urlJoin)(baseHref, appShellOptions.route),
|
|
169
|
+
});
|
|
142
170
|
}
|
|
143
171
|
if (routesFile) {
|
|
144
172
|
const routesFromFile = (await (0, promises_1.readFile)(routesFile, 'utf8')).split(/\r?\n/);
|
|
145
173
|
for (const route of routesFromFile) {
|
|
146
|
-
routes.
|
|
174
|
+
routes.push({
|
|
175
|
+
route: (0, url_1.urlJoin)(baseHref, route.trim()),
|
|
176
|
+
});
|
|
147
177
|
}
|
|
148
178
|
}
|
|
149
179
|
if (!discoverRoutes) {
|
|
150
|
-
return {
|
|
180
|
+
return { errors: [], serializedRouteTree: routes };
|
|
151
181
|
}
|
|
152
182
|
const workerExecArgv = [
|
|
153
183
|
'--import',
|
|
@@ -167,39 +197,22 @@ async function getAllRoutes(workspaceRoot, baseHref, outputFilesForWorker, asset
|
|
|
167
197
|
},
|
|
168
198
|
execArgv: workerExecArgv,
|
|
169
199
|
});
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
errors
|
|
175
|
-
})
|
|
176
|
-
.finally(() => {
|
|
177
|
-
void renderWorker.destroy();
|
|
178
|
-
});
|
|
179
|
-
const skippedRedirects = [];
|
|
180
|
-
const skippedOthers = [];
|
|
181
|
-
for (const { route, redirectTo } of serializableRouteTreeNode) {
|
|
182
|
-
if (redirectTo) {
|
|
183
|
-
skippedRedirects.push(route);
|
|
184
|
-
}
|
|
185
|
-
else if (route.includes('*')) {
|
|
186
|
-
skippedOthers.push(route);
|
|
187
|
-
}
|
|
188
|
-
else {
|
|
189
|
-
routes.add(route);
|
|
190
|
-
}
|
|
200
|
+
try {
|
|
201
|
+
const { serializedRouteTree, errors } = await renderWorker.run({
|
|
202
|
+
outputMode,
|
|
203
|
+
});
|
|
204
|
+
return { errors, serializedRouteTree: [...routes, ...serializedRouteTree] };
|
|
191
205
|
}
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
}
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
206
|
+
catch (err) {
|
|
207
|
+
(0, error_1.assertIsError)(err);
|
|
208
|
+
return {
|
|
209
|
+
errors: [`An error occurred while extracting routes.\n\n${err.stack}`],
|
|
210
|
+
serializedRouteTree: [],
|
|
211
|
+
};
|
|
212
|
+
}
|
|
213
|
+
finally {
|
|
214
|
+
void renderWorker.destroy();
|
|
201
215
|
}
|
|
202
|
-
return { routes, serializableRouteTreeNode, warnings };
|
|
203
216
|
}
|
|
204
217
|
function addLeadingSlash(value) {
|
|
205
218
|
return value.charAt(0) === '/' ? value : '/' + value;
|
|
@@ -207,3 +220,27 @@ function addLeadingSlash(value) {
|
|
|
207
220
|
function removeLeadingSlash(value) {
|
|
208
221
|
return value.charAt(0) === '/' ? value.slice(1) : value;
|
|
209
222
|
}
|
|
223
|
+
/**
|
|
224
|
+
* Generates a static HTML page with a meta refresh tag to redirect the user to a specified URL.
|
|
225
|
+
*
|
|
226
|
+
* This function creates a simple HTML page that performs a redirect using a meta tag.
|
|
227
|
+
* It includes a fallback link in case the meta-refresh doesn't work.
|
|
228
|
+
*
|
|
229
|
+
* @param url - The URL to which the page should redirect.
|
|
230
|
+
* @returns The HTML content of the static redirect page.
|
|
231
|
+
*/
|
|
232
|
+
function generateRedirectStaticPage(url) {
|
|
233
|
+
return `
|
|
234
|
+
<!DOCTYPE html>
|
|
235
|
+
<html>
|
|
236
|
+
<head>
|
|
237
|
+
<meta charset="utf-8">
|
|
238
|
+
<title>Redirecting</title>
|
|
239
|
+
<meta http-equiv="refresh" content="0; url=${url}">
|
|
240
|
+
</head>
|
|
241
|
+
<body>
|
|
242
|
+
<pre>Redirecting to <a href="${url}">${url}</a></pre>
|
|
243
|
+
</body>
|
|
244
|
+
</html>
|
|
245
|
+
`.trim();
|
|
246
|
+
}
|
|
@@ -5,17 +5,12 @@
|
|
|
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
|
-
import
|
|
10
|
-
export interface
|
|
11
|
-
|
|
12
|
-
}
|
|
13
|
-
export type SerializableRouteTreeNode = ReturnType<Awaited<ReturnType<typeof ɵextractRoutesAndCreateRouteTree>>['routeTree']['toObject']>;
|
|
14
|
-
export interface RoutersExtractorWorkerResult {
|
|
15
|
-
serializedRouteTree: SerializableRouteTreeNode;
|
|
16
|
-
errors: string[];
|
|
8
|
+
import { OutputMode } from '../../builders/application/schema';
|
|
9
|
+
import { RoutersExtractorWorkerResult } from './models';
|
|
10
|
+
export interface ExtractRoutesOptions {
|
|
11
|
+
outputMode?: OutputMode;
|
|
17
12
|
}
|
|
18
13
|
/** Renders an application based on a provided options. */
|
|
19
|
-
declare function extractRoutes(): Promise<RoutersExtractorWorkerResult>;
|
|
14
|
+
declare function extractRoutes({ outputMode, }: ExtractRoutesOptions): Promise<RoutersExtractorWorkerResult>;
|
|
20
15
|
declare const _default: typeof extractRoutes;
|
|
21
16
|
export default _default;
|
|
@@ -7,14 +7,13 @@
|
|
|
7
7
|
* found in the LICENSE file at https://angular.dev/license
|
|
8
8
|
*/
|
|
9
9
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
10
|
+
const schema_1 = require("../../builders/application/schema");
|
|
10
11
|
const fetch_patch_1 = require("./fetch-patch");
|
|
11
12
|
const load_esm_from_memory_1 = require("./load-esm-from-memory");
|
|
12
13
|
/** Renders an application based on a provided options. */
|
|
13
|
-
async function extractRoutes() {
|
|
14
|
+
async function extractRoutes({ outputMode, }) {
|
|
14
15
|
const { ɵextractRoutesAndCreateRouteTree: extractRoutesAndCreateRouteTree } = await (0, load_esm_from_memory_1.loadEsmModuleFromMemory)('./main.server.mjs');
|
|
15
|
-
const { routeTree, errors } = await extractRoutesAndCreateRouteTree(new URL('http://local-angular-prerender/'),
|
|
16
|
-
/** manifest */ undefined,
|
|
17
|
-
/** invokeGetPrerenderParams */ true);
|
|
16
|
+
const { routeTree, errors } = await extractRoutesAndCreateRouteTree(new URL('http://local-angular-prerender/'), undefined /** manifest */, true /** invokeGetPrerenderParams */, outputMode === schema_1.OutputMode.Server /** includePrerenderFallbackRoutes */);
|
|
18
17
|
return {
|
|
19
18
|
errors,
|
|
20
19
|
serializedRouteTree: routeTree.toObject(),
|
|
@@ -1,22 +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
|
-
usedComponentStyles: Map<string, string[]>;
|
|
21
|
-
}
|
|
22
|
-
export declare function createAngularMemoryPlugin(options: AngularMemoryPluginOptions): Plugin;
|
|
File without changes
|
|
File without changes
|