@angular/build 19.0.0-next.8 → 19.0.0-next.9
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 +6 -5
- package/src/builders/application/options.d.ts +7 -0
- package/src/builders/application/options.js +2 -1
- package/src/builders/dev-server/vite-server.js +7 -6
- 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 +1 -0
- package/src/tools/esbuild/angular/compiler-plugin.js +2 -1
- package/src/tools/esbuild/compiler-plugin-options.js +2 -1
- 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 +5 -3
- package/src/tools/vite/middlewares/ssr-middleware.js +9 -8
- package/src/utils/index-file/index-html-generator.js +5 -0
- 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 +27 -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 +2 -2
- 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 +7 -0
- package/src/utils/server-rendering/manifest.js +4 -13
- package/src/utils/server-rendering/prerender.js +7 -5
- package/src/utils/server-rendering/render-worker.d.ts +4 -1
- package/src/utils/server-rendering/render-worker.js +13 -3
- package/src/utils/server-rendering/routes-extractor-worker.d.ts +5 -4
- package/src/utils/server-rendering/routes-extractor-worker.js +14 -4
- package/src/utils/server-rendering/utils.d.ts +11 -0
- package/src/utils/server-rendering/utils.js +17 -0
package/LICENSE
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
The MIT License
|
|
2
2
|
|
|
3
|
-
Copyright (c)
|
|
3
|
+
Copyright (c) 2010-2024 Google LLC. https://angular.dev/license
|
|
4
4
|
|
|
5
5
|
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
6
|
of this software and associated documentation files (the "Software"), to deal
|
|
@@ -9,13 +9,13 @@ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
|
9
9
|
copies of the Software, and to permit persons to whom the Software is
|
|
10
10
|
furnished to do so, subject to the following conditions:
|
|
11
11
|
|
|
12
|
-
The above copyright notice and this permission notice shall be included in
|
|
13
|
-
copies or substantial portions of the Software.
|
|
12
|
+
The above copyright notice and this permission notice shall be included in
|
|
13
|
+
all copies or substantial portions of the Software.
|
|
14
14
|
|
|
15
15
|
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
16
|
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
17
|
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
18
|
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
19
|
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
-
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
|
21
|
-
SOFTWARE.
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
|
21
|
+
THE SOFTWARE.
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@angular/build",
|
|
3
|
-
"version": "19.0.0-next.
|
|
3
|
+
"version": "19.0.0-next.9",
|
|
4
4
|
"description": "Official build system for Angular",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"Angular CLI",
|
|
@@ -23,7 +23,7 @@
|
|
|
23
23
|
"builders": "builders.json",
|
|
24
24
|
"dependencies": {
|
|
25
25
|
"@ampproject/remapping": "2.3.0",
|
|
26
|
-
"@angular-devkit/architect": "0.1900.0-next.
|
|
26
|
+
"@angular-devkit/architect": "0.1900.0-next.9",
|
|
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",
|
|
@@ -35,6 +35,7 @@
|
|
|
35
35
|
"esbuild": "0.24.0",
|
|
36
36
|
"fast-glob": "3.3.2",
|
|
37
37
|
"https-proxy-agent": "7.0.5",
|
|
38
|
+
"istanbul-lib-instrument": "6.0.3",
|
|
38
39
|
"listr2": "8.2.4",
|
|
39
40
|
"lmdb": "3.1.3",
|
|
40
41
|
"magic-string": "0.30.11",
|
|
@@ -42,8 +43,8 @@
|
|
|
42
43
|
"parse5-html-rewriting-stream": "7.0.0",
|
|
43
44
|
"picomatch": "4.0.2",
|
|
44
45
|
"piscina": "4.7.0",
|
|
45
|
-
"rollup": "4.22.
|
|
46
|
-
"sass": "1.79.
|
|
46
|
+
"rollup": "4.22.5",
|
|
47
|
+
"sass": "1.79.4",
|
|
47
48
|
"semver": "7.6.3",
|
|
48
49
|
"vite": "5.4.8",
|
|
49
50
|
"watchpack": "2.4.2"
|
|
@@ -54,7 +55,7 @@
|
|
|
54
55
|
"@angular/localize": "^19.0.0-next.0",
|
|
55
56
|
"@angular/platform-server": "^19.0.0-next.0",
|
|
56
57
|
"@angular/service-worker": "^19.0.0-next.0",
|
|
57
|
-
"@angular/ssr": "^19.0.0-next.
|
|
58
|
+
"@angular/ssr": "^19.0.0-next.9",
|
|
58
59
|
"less": "^4.2.0",
|
|
59
60
|
"postcss": "^8.4.0",
|
|
60
61
|
"tailwindcss": "^2.0.0 || ^3.0.0",
|
|
@@ -66,6 +66,12 @@ interface InternalOptions {
|
|
|
66
66
|
* styles.
|
|
67
67
|
*/
|
|
68
68
|
externalRuntimeStyles?: boolean;
|
|
69
|
+
/**
|
|
70
|
+
* Enables instrumentation to collect code coverage data for specific files.
|
|
71
|
+
*
|
|
72
|
+
* Used exclusively for tests and shouldn't be used for other kinds of builds.
|
|
73
|
+
*/
|
|
74
|
+
instrumentForCoverage?: (filename: string) => boolean;
|
|
69
75
|
}
|
|
70
76
|
/** Full set of options for `application` builder. */
|
|
71
77
|
export type ApplicationBuilderInternalOptions = Omit<ApplicationBuilderOptions & InternalOptions, 'browser'> & {
|
|
@@ -174,6 +180,7 @@ export declare function normalizeOptions(context: BuilderContext, projectName: s
|
|
|
174
180
|
} | undefined;
|
|
175
181
|
partialSSRBuild: boolean;
|
|
176
182
|
externalRuntimeStyles: boolean | undefined;
|
|
183
|
+
instrumentForCoverage: ((filename: string) => boolean) | undefined;
|
|
177
184
|
}>;
|
|
178
185
|
export declare function getLocaleBaseHref(baseHref: string | undefined, i18n: NormalizedApplicationBuildOptions['i18nOptions'], locale: string): string | undefined;
|
|
179
186
|
export {};
|
|
@@ -231,7 +231,7 @@ async function normalizeOptions(context, projectName, options, extensions) {
|
|
|
231
231
|
}
|
|
232
232
|
}
|
|
233
233
|
// Initial options to keep
|
|
234
|
-
const { allowedCommonJsDependencies, aot, baseHref, crossOrigin, externalDependencies, extractLicenses, inlineStyleLanguage = 'css', outExtension, serviceWorker, poll, polyfills, statsJson, outputMode, stylePreprocessorOptions, subresourceIntegrity, verbose, watch, progress = true, externalPackages, namedChunks, budgets, deployUrl, clearScreen, define, partialSSRBuild = false, externalRuntimeStyles, } = options;
|
|
234
|
+
const { allowedCommonJsDependencies, aot, baseHref, crossOrigin, externalDependencies, extractLicenses, inlineStyleLanguage = 'css', outExtension, serviceWorker, poll, polyfills, statsJson, outputMode, stylePreprocessorOptions, subresourceIntegrity, verbose, watch, progress = true, externalPackages, namedChunks, budgets, deployUrl, clearScreen, define, partialSSRBuild = false, externalRuntimeStyles, instrumentForCoverage, } = options;
|
|
235
235
|
// Return all the normalized options
|
|
236
236
|
return {
|
|
237
237
|
advancedOptimizations: !!aot && optimizationOptions.scripts,
|
|
@@ -289,6 +289,7 @@ async function normalizeOptions(context, projectName, options, extensions) {
|
|
|
289
289
|
define,
|
|
290
290
|
partialSSRBuild: environment_options_1.usePartialSsrBuild || partialSSRBuild,
|
|
291
291
|
externalRuntimeStyles,
|
|
292
|
+
instrumentForCoverage,
|
|
292
293
|
};
|
|
293
294
|
}
|
|
294
295
|
async function getTailwindConfig(searchDirectories, workspaceRoot, context) {
|
|
@@ -69,6 +69,7 @@ async function* serveWithVite(serverOptions, builderName, builderAction, context
|
|
|
69
69
|
// Disable prerendering if enabled and force SSR.
|
|
70
70
|
// This is so instead of prerendering all the routes for every change, the page is "prerendered" when it is requested.
|
|
71
71
|
browserOptions.prerender = false;
|
|
72
|
+
browserOptions.ssr ||= true;
|
|
72
73
|
}
|
|
73
74
|
// Set all packages as external to support Vite's prebundle caching
|
|
74
75
|
browserOptions.externalPackages = serverOptions.prebundle;
|
|
@@ -128,7 +129,7 @@ async function* serveWithVite(serverOptions, builderName, builderAction, context
|
|
|
128
129
|
case results_1.ResultKind.Failure:
|
|
129
130
|
if (result.errors.length && server) {
|
|
130
131
|
hadError = true;
|
|
131
|
-
server.
|
|
132
|
+
server.ws.send({
|
|
132
133
|
type: 'error',
|
|
133
134
|
err: {
|
|
134
135
|
message: result.errors[0].text,
|
|
@@ -175,7 +176,7 @@ async function* serveWithVite(serverOptions, builderName, builderAction, context
|
|
|
175
176
|
if (hadError && server) {
|
|
176
177
|
hadError = false;
|
|
177
178
|
// Send an empty update to clear the error overlay
|
|
178
|
-
server.
|
|
179
|
+
server.ws.send({
|
|
179
180
|
'type': 'update',
|
|
180
181
|
updates: [],
|
|
181
182
|
});
|
|
@@ -268,7 +269,7 @@ async function* serveWithVite(serverOptions, builderName, builderAction, context
|
|
|
268
269
|
key: 'r',
|
|
269
270
|
description: 'force reload browser',
|
|
270
271
|
action(server) {
|
|
271
|
-
server.
|
|
272
|
+
server.ws.send({
|
|
272
273
|
type: 'full-reload',
|
|
273
274
|
path: '*',
|
|
274
275
|
});
|
|
@@ -311,7 +312,7 @@ async function handleUpdate(normalizePath, generatedFiles, server, serverOptions
|
|
|
311
312
|
if (serverOptions.liveReload || serverOptions.hmr) {
|
|
312
313
|
if (updatedFiles.every((f) => f.endsWith('.css'))) {
|
|
313
314
|
const timestamp = Date.now();
|
|
314
|
-
server.
|
|
315
|
+
server.ws.send({
|
|
315
316
|
type: 'update',
|
|
316
317
|
updates: updatedFiles.flatMap((filePath) => {
|
|
317
318
|
// For component styles, an HMR update must be sent for each one with the corresponding
|
|
@@ -342,7 +343,7 @@ async function handleUpdate(normalizePath, generatedFiles, server, serverOptions
|
|
|
342
343
|
}
|
|
343
344
|
// Send reload command to clients
|
|
344
345
|
if (serverOptions.liveReload) {
|
|
345
|
-
server.
|
|
346
|
+
server.ws.send({
|
|
346
347
|
type: 'full-reload',
|
|
347
348
|
path: '*',
|
|
348
349
|
});
|
|
@@ -408,7 +409,7 @@ async function setupServer(serverOptions, outputFiles, assets, preserveSymlinks,
|
|
|
408
409
|
const { normalizePath } = await (0, load_esm_1.loadEsmModule)('vite');
|
|
409
410
|
// Path will not exist on disk and only used to provide separate path for Vite requests
|
|
410
411
|
const virtualProjectRoot = normalizePath((0, node_path_1.join)(serverOptions.workspaceRoot, `.angular/vite-root`, serverOptions.buildTarget.project));
|
|
411
|
-
const cacheDir = (0, node_path_1.join)(serverOptions.cacheOptions.path, 'vite');
|
|
412
|
+
const cacheDir = (0, node_path_1.join)(serverOptions.cacheOptions.path, serverOptions.buildTarget.project, 'vite');
|
|
412
413
|
const configuration = {
|
|
413
414
|
configFile: false,
|
|
414
415
|
envFile: false,
|
|
@@ -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
|
+
import { PluginObj } from '@babel/core';
|
|
9
|
+
/**
|
|
10
|
+
* A babel plugin factory function for adding istanbul instrumentation.
|
|
11
|
+
*
|
|
12
|
+
* @returns A babel plugin object instance.
|
|
13
|
+
*/
|
|
14
|
+
export default function (): PluginObj;
|
|
@@ -0,0 +1,44 @@
|
|
|
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 = default_1;
|
|
14
|
+
const core_1 = require("@babel/core");
|
|
15
|
+
const istanbul_lib_instrument_1 = require("istanbul-lib-instrument");
|
|
16
|
+
const node_assert_1 = __importDefault(require("node:assert"));
|
|
17
|
+
/**
|
|
18
|
+
* A babel plugin factory function for adding istanbul instrumentation.
|
|
19
|
+
*
|
|
20
|
+
* @returns A babel plugin object instance.
|
|
21
|
+
*/
|
|
22
|
+
function default_1() {
|
|
23
|
+
const visitors = new WeakMap();
|
|
24
|
+
return {
|
|
25
|
+
visitor: {
|
|
26
|
+
Program: {
|
|
27
|
+
enter(path, state) {
|
|
28
|
+
const visitor = (0, istanbul_lib_instrument_1.programVisitor)(core_1.types, state.filename, {
|
|
29
|
+
// Babel returns a Converter object from the `convert-source-map` package
|
|
30
|
+
inputSourceMap: state.file.inputMap?.toObject(),
|
|
31
|
+
});
|
|
32
|
+
visitors.set(path, visitor);
|
|
33
|
+
visitor.enter(path);
|
|
34
|
+
},
|
|
35
|
+
exit(path) {
|
|
36
|
+
const visitor = visitors.get(path);
|
|
37
|
+
(0, node_assert_1.default)(visitor, 'Instrumentation visitor should always be present for program path.');
|
|
38
|
+
visitor.exit(path);
|
|
39
|
+
visitors.delete(path);
|
|
40
|
+
},
|
|
41
|
+
},
|
|
42
|
+
},
|
|
43
|
+
};
|
|
44
|
+
}
|
|
@@ -0,0 +1,20 @@
|
|
|
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
|
+
declare module 'istanbul-lib-instrument' {
|
|
10
|
+
export interface Visitor {
|
|
11
|
+
enter(path: import('@babel/core').NodePath<types.Program>): void;
|
|
12
|
+
exit(path: import('@babel/core').NodePath<types.Program>): void;
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
export function programVisitor(
|
|
16
|
+
types: typeof import('@babel/core').types,
|
|
17
|
+
filePath?: string,
|
|
18
|
+
options?: { inputSourceMap?: object | null },
|
|
19
|
+
): Visitor;
|
|
20
|
+
}
|
|
@@ -22,6 +22,7 @@ export interface CompilerPluginOptions {
|
|
|
22
22
|
loadResultCache?: LoadResultCache;
|
|
23
23
|
incremental: boolean;
|
|
24
24
|
externalRuntimeStyles?: boolean;
|
|
25
|
+
instrumentForCoverage?: (request: string) => boolean;
|
|
25
26
|
}
|
|
26
27
|
export declare function createCompilerPlugin(pluginOptions: CompilerPluginOptions, styleOptions: BundleStylesheetOptions & {
|
|
27
28
|
inlineStyleLanguage: string;
|
|
@@ -339,7 +339,8 @@ function createCompilerPlugin(pluginOptions, styleOptions) {
|
|
|
339
339
|
// A string indicates untransformed output from the TS/NG compiler.
|
|
340
340
|
// This step is unneeded when using esbuild transpilation.
|
|
341
341
|
const sideEffects = await hasSideEffects(request);
|
|
342
|
-
|
|
342
|
+
const instrumentForCoverage = pluginOptions.instrumentForCoverage?.(request);
|
|
343
|
+
contents = await javascriptTransformer.transformData(request, contents, true /* skipLinker */, sideEffects, instrumentForCoverage);
|
|
343
344
|
// Store as the returned Uint8Array to allow caching the fully transformed code
|
|
344
345
|
typeScriptFileCache.set(request, contents);
|
|
345
346
|
}
|
|
@@ -9,7 +9,7 @@
|
|
|
9
9
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
10
10
|
exports.createCompilerPluginOptions = createCompilerPluginOptions;
|
|
11
11
|
function createCompilerPluginOptions(options, target, sourceFileCache) {
|
|
12
|
-
const { workspaceRoot, optimizationOptions, sourcemapOptions, tsconfig, outputNames, fileReplacements, externalDependencies, preserveSymlinks, stylePreprocessorOptions, advancedOptimizations, inlineStyleLanguage, jit, cacheOptions, tailwindConfiguration, postcssConfiguration, publicPath, externalRuntimeStyles, } = options;
|
|
12
|
+
const { workspaceRoot, optimizationOptions, sourcemapOptions, tsconfig, outputNames, fileReplacements, externalDependencies, preserveSymlinks, stylePreprocessorOptions, advancedOptimizations, inlineStyleLanguage, jit, cacheOptions, tailwindConfiguration, postcssConfiguration, publicPath, externalRuntimeStyles, instrumentForCoverage, } = options;
|
|
13
13
|
return {
|
|
14
14
|
// JS/TS options
|
|
15
15
|
pluginOptions: {
|
|
@@ -23,6 +23,7 @@ function createCompilerPluginOptions(options, target, sourceFileCache) {
|
|
|
23
23
|
loadResultCache: sourceFileCache?.loadResultCache,
|
|
24
24
|
incremental: !!options.watch,
|
|
25
25
|
externalRuntimeStyles,
|
|
26
|
+
instrumentForCoverage,
|
|
26
27
|
},
|
|
27
28
|
// Component stylesheet options
|
|
28
29
|
styleOptions: {
|
|
@@ -14,6 +14,7 @@ interface JavaScriptTransformRequest {
|
|
|
14
14
|
skipLinker?: boolean;
|
|
15
15
|
sideEffects?: boolean;
|
|
16
16
|
jit: boolean;
|
|
17
|
+
instrumentForCoverage?: boolean;
|
|
17
18
|
}
|
|
18
19
|
export default function transformJavaScript(request: JavaScriptTransformRequest): Promise<unknown>;
|
|
19
20
|
export {};
|
|
@@ -63,8 +63,12 @@ async function transformWithBabel(filename, data, options) {
|
|
|
63
63
|
// @ts-expect-error Import attribute syntax plugin does not currently have type definitions
|
|
64
64
|
const { default: importAttributePlugin } = await Promise.resolve().then(() => __importStar(require('@babel/plugin-syntax-import-attributes')));
|
|
65
65
|
const plugins = [importAttributePlugin];
|
|
66
|
-
|
|
66
|
+
if (options.instrumentForCoverage) {
|
|
67
|
+
const { default: coveragePlugin } = await Promise.resolve().then(() => __importStar(require('../babel/plugins/add-code-coverage.js')));
|
|
68
|
+
plugins.push(coveragePlugin);
|
|
69
|
+
}
|
|
67
70
|
if (shouldLink) {
|
|
71
|
+
// Lazy load the linker plugin only when linking is required
|
|
68
72
|
const linkerPlugin = await createLinkerPlugin(options);
|
|
69
73
|
plugins.push(linkerPlugin);
|
|
70
74
|
}
|
|
@@ -35,7 +35,7 @@ export declare class JavaScriptTransformer {
|
|
|
35
35
|
* @param sideEffects If false, and `advancedOptimizations` is enabled tslib decorators are wrapped.
|
|
36
36
|
* @returns A promise that resolves to a UTF-8 encoded Uint8Array containing the result.
|
|
37
37
|
*/
|
|
38
|
-
transformFile(filename: string, skipLinker?: boolean, sideEffects?: boolean): Promise<Uint8Array>;
|
|
38
|
+
transformFile(filename: string, skipLinker?: boolean, sideEffects?: boolean, instrumentForCoverage?: boolean): Promise<Uint8Array>;
|
|
39
39
|
/**
|
|
40
40
|
* Performs JavaScript transformations on the provided data of a file. The file does not need
|
|
41
41
|
* to exist on the filesystem.
|
|
@@ -45,7 +45,7 @@ export declare class JavaScriptTransformer {
|
|
|
45
45
|
* @param sideEffects If false, and `advancedOptimizations` is enabled tslib decorators are wrapped.
|
|
46
46
|
* @returns A promise that resolves to a UTF-8 encoded Uint8Array containing the result.
|
|
47
47
|
*/
|
|
48
|
-
transformData(filename: string, data: string, skipLinker: boolean, sideEffects?: boolean): Promise<Uint8Array>;
|
|
48
|
+
transformData(filename: string, data: string, skipLinker: boolean, sideEffects?: boolean, instrumentForCoverage?: boolean): Promise<Uint8Array>;
|
|
49
49
|
/**
|
|
50
50
|
* Stops all active transformation tasks and shuts down all workers.
|
|
51
51
|
* @returns A void promise that resolves when closing is complete.
|
|
@@ -52,7 +52,7 @@ class JavaScriptTransformer {
|
|
|
52
52
|
* @param sideEffects If false, and `advancedOptimizations` is enabled tslib decorators are wrapped.
|
|
53
53
|
* @returns A promise that resolves to a UTF-8 encoded Uint8Array containing the result.
|
|
54
54
|
*/
|
|
55
|
-
async transformFile(filename, skipLinker, sideEffects) {
|
|
55
|
+
async transformFile(filename, skipLinker, sideEffects, instrumentForCoverage) {
|
|
56
56
|
const data = await (0, promises_1.readFile)(filename);
|
|
57
57
|
let result;
|
|
58
58
|
let cacheKey;
|
|
@@ -79,6 +79,7 @@ class JavaScriptTransformer {
|
|
|
79
79
|
data,
|
|
80
80
|
skipLinker,
|
|
81
81
|
sideEffects,
|
|
82
|
+
instrumentForCoverage,
|
|
82
83
|
...this.#commonOptions,
|
|
83
84
|
}, {
|
|
84
85
|
// The below is disable as with Yarn PNP this causes build failures with the below message
|
|
@@ -106,10 +107,10 @@ class JavaScriptTransformer {
|
|
|
106
107
|
* @param sideEffects If false, and `advancedOptimizations` is enabled tslib decorators are wrapped.
|
|
107
108
|
* @returns A promise that resolves to a UTF-8 encoded Uint8Array containing the result.
|
|
108
109
|
*/
|
|
109
|
-
async transformData(filename, data, skipLinker, sideEffects) {
|
|
110
|
+
async transformData(filename, data, skipLinker, sideEffects, instrumentForCoverage) {
|
|
110
111
|
// Perform a quick test to determine if the data needs any transformations.
|
|
111
112
|
// This allows directly returning the data without the worker communication overhead.
|
|
112
|
-
if (skipLinker && !this.#commonOptions.advancedOptimizations) {
|
|
113
|
+
if (skipLinker && !this.#commonOptions.advancedOptimizations && !instrumentForCoverage) {
|
|
113
114
|
const keepSourcemap = this.#commonOptions.sourcemap &&
|
|
114
115
|
(!!this.#commonOptions.thirdPartySourcemaps || !/[\\/]node_modules[\\/]/.test(filename));
|
|
115
116
|
return Buffer.from(keepSourcemap ? data : data.replace(/^\/\/# sourceMappingURL=[^\r\n]*/gm, ''), 'utf-8');
|
|
@@ -119,6 +120,7 @@ class JavaScriptTransformer {
|
|
|
119
120
|
data,
|
|
120
121
|
skipLinker,
|
|
121
122
|
sideEffects,
|
|
123
|
+
instrumentForCoverage,
|
|
122
124
|
...this.#commonOptions,
|
|
123
125
|
});
|
|
124
126
|
}
|
|
@@ -10,6 +10,7 @@ Object.defineProperty(exports, "__esModule", { value: true });
|
|
|
10
10
|
exports.createAngularSsrInternalMiddleware = createAngularSsrInternalMiddleware;
|
|
11
11
|
exports.createAngularSsrExternalMiddleware = createAngularSsrExternalMiddleware;
|
|
12
12
|
const load_esm_1 = require("../../../utils/load-esm");
|
|
13
|
+
const utils_1 = require("../../../utils/server-rendering/utils");
|
|
13
14
|
function createAngularSsrInternalMiddleware(server, indexHtmlTransformer) {
|
|
14
15
|
let cachedAngularServerApp;
|
|
15
16
|
return function angularSsrMiddleware(req, res, next) {
|
|
@@ -17,6 +18,9 @@ function createAngularSsrInternalMiddleware(server, indexHtmlTransformer) {
|
|
|
17
18
|
return next();
|
|
18
19
|
}
|
|
19
20
|
(async () => {
|
|
21
|
+
// Load the compiler because `@angular/ssr/node` depends on `@angular/` packages,
|
|
22
|
+
// which must be processed by the runtime linker, even if they are not used.
|
|
23
|
+
await (0, load_esm_1.loadEsmModule)('@angular/compiler');
|
|
20
24
|
const { writeResponseToNodeResponse, createWebRequestFromNodeRequest } = await (0, load_esm_1.loadEsmModule)('@angular/ssr/node');
|
|
21
25
|
const { ɵgetOrCreateAngularServerApp } = (await server.ssrLoadModule('/main.server.mjs'));
|
|
22
26
|
const angularServerApp = ɵgetOrCreateAngularServerApp();
|
|
@@ -43,11 +47,14 @@ async function createAngularSsrExternalMiddleware(server, indexHtmlTransformer)
|
|
|
43
47
|
let fallbackWarningShown = false;
|
|
44
48
|
let cachedAngularAppEngine;
|
|
45
49
|
let angularSsrInternalMiddleware;
|
|
50
|
+
// Load the compiler because `@angular/ssr/node` depends on `@angular/` packages,
|
|
51
|
+
// which must be processed by the runtime linker, even if they are not used.
|
|
52
|
+
await (0, load_esm_1.loadEsmModule)('@angular/compiler');
|
|
46
53
|
const { createWebRequestFromNodeRequest, writeResponseToNodeResponse } = await (0, load_esm_1.loadEsmModule)('@angular/ssr/node');
|
|
47
54
|
return function angularSsrExternalMiddleware(req, res, next) {
|
|
48
55
|
(async () => {
|
|
49
56
|
const { default: handler, AngularAppEngine } = (await server.ssrLoadModule('./server.mjs'));
|
|
50
|
-
if (!isSsrNodeRequestHandler(handler) && !isSsrRequestHandler(handler)) {
|
|
57
|
+
if (!(0, utils_1.isSsrNodeRequestHandler)(handler) && !(0, utils_1.isSsrRequestHandler)(handler)) {
|
|
51
58
|
if (!fallbackWarningShown) {
|
|
52
59
|
// eslint-disable-next-line no-console
|
|
53
60
|
console.warn(`The default export in 'server.ts' does not provide a Node.js request handler. ` +
|
|
@@ -66,7 +73,7 @@ async function createAngularSsrExternalMiddleware(server, indexHtmlTransformer)
|
|
|
66
73
|
cachedAngularAppEngine = AngularAppEngine;
|
|
67
74
|
}
|
|
68
75
|
// Forward the request to the middleware in server.ts
|
|
69
|
-
if (isSsrNodeRequestHandler(handler)) {
|
|
76
|
+
if ((0, utils_1.isSsrNodeRequestHandler)(handler)) {
|
|
70
77
|
await handler(req, res, next);
|
|
71
78
|
}
|
|
72
79
|
else {
|
|
@@ -80,9 +87,3 @@ async function createAngularSsrExternalMiddleware(server, indexHtmlTransformer)
|
|
|
80
87
|
})().catch(next);
|
|
81
88
|
};
|
|
82
89
|
}
|
|
83
|
-
function isSsrNodeRequestHandler(value) {
|
|
84
|
-
return typeof value === 'function' && '__ng_node_request_handler__' in value;
|
|
85
|
-
}
|
|
86
|
-
function isSsrRequestHandler(value) {
|
|
87
|
-
return typeof value === 'function' && '__ng_request_handler__' in value;
|
|
88
|
-
}
|
|
@@ -14,6 +14,7 @@ const add_event_dispatch_contract_1 = require("./add-event-dispatch-contract");
|
|
|
14
14
|
const augment_index_html_1 = require("./augment-index-html");
|
|
15
15
|
const inline_critical_css_1 = require("./inline-critical-css");
|
|
16
16
|
const inline_fonts_1 = require("./inline-fonts");
|
|
17
|
+
const ngcm_attribute_1 = require("./ngcm-attribute");
|
|
17
18
|
const nonce_1 = require("./nonce");
|
|
18
19
|
class IndexHtmlGenerator {
|
|
19
20
|
options;
|
|
@@ -35,6 +36,7 @@ class IndexHtmlGenerator {
|
|
|
35
36
|
this.csrPlugins.push(addNoncePlugin());
|
|
36
37
|
// SSR plugins
|
|
37
38
|
if (options.generateDedicatedSSRContent) {
|
|
39
|
+
this.csrPlugins.push(addNgcmAttributePlugin());
|
|
38
40
|
this.ssrPlugins.push(addEventDispatchContractPlugin(), addNoncePlugin());
|
|
39
41
|
}
|
|
40
42
|
}
|
|
@@ -134,3 +136,6 @@ function postTransformPlugin({ options }) {
|
|
|
134
136
|
function addEventDispatchContractPlugin() {
|
|
135
137
|
return (html) => (0, add_event_dispatch_contract_1.addEventDispatchContract)(html);
|
|
136
138
|
}
|
|
139
|
+
function addNgcmAttributePlugin() {
|
|
140
|
+
return (html) => (0, ngcm_attribute_1.addNgcmAttribute)(html);
|
|
141
|
+
}
|
|
@@ -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
|
+
}
|
|
@@ -26,8 +26,35 @@ exports.VALID_SELF_CLOSING_TAGS = new Set([
|
|
|
26
26
|
'wbr',
|
|
27
27
|
/** SVG tags */
|
|
28
28
|
'animate',
|
|
29
|
+
'animateMotion',
|
|
30
|
+
'animateTransform',
|
|
29
31
|
'circle',
|
|
30
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',
|
|
31
58
|
'line',
|
|
32
59
|
'path',
|
|
33
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.
|
|
13
|
+
const VERSION = '19.0.0-next.9';
|
|
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,7 +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
|
-
function patchFetchToLoadInMemoryAssets() {
|
|
20
|
+
function patchFetchToLoadInMemoryAssets(baseURL) {
|
|
21
21
|
const originalFetch = globalThis.fetch;
|
|
22
22
|
const patchedFetch = async (input, init) => {
|
|
23
23
|
let url;
|
|
@@ -35,7 +35,7 @@ function patchFetchToLoadInMemoryAssets() {
|
|
|
35
35
|
}
|
|
36
36
|
const { hostname } = url;
|
|
37
37
|
const pathname = decodeURIComponent(url.pathname);
|
|
38
|
-
if (hostname !==
|
|
38
|
+
if (hostname !== baseURL.hostname || !assetFiles[pathname]) {
|
|
39
39
|
// Only handle relative requests or files that are in assets.
|
|
40
40
|
return originalFetch(input, init);
|
|
41
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
|
+
}
|
|
@@ -15,5 +15,12 @@ interface MainServerBundleExports {
|
|
|
15
15
|
ɵextractRoutesAndCreateRouteTree: typeof ɵextractRoutesAndCreateRouteTree;
|
|
16
16
|
ɵgetOrCreateAngularServerApp: typeof ɵgetOrCreateAngularServerApp;
|
|
17
17
|
}
|
|
18
|
+
/**
|
|
19
|
+
* Represents the exports available from the server bundle.
|
|
20
|
+
*/
|
|
21
|
+
interface ServerBundleExports {
|
|
22
|
+
default: unknown;
|
|
23
|
+
}
|
|
18
24
|
export declare function loadEsmModuleFromMemory(path: './main.server.mjs'): Promise<MainServerBundleExports>;
|
|
25
|
+
export declare function loadEsmModuleFromMemory(path: './server.mjs'): Promise<ServerBundleExports>;
|
|
19
26
|
export {};
|
|
@@ -18,18 +18,9 @@ const MAIN_SERVER_OUTPUT_FILENAME = 'main.server.mjs';
|
|
|
18
18
|
* A mapping of unsafe characters to their escaped Unicode equivalents.
|
|
19
19
|
*/
|
|
20
20
|
const UNSAFE_CHAR_MAP = {
|
|
21
|
-
'
|
|
22
|
-
'
|
|
23
|
-
'/': '\\u002F',
|
|
21
|
+
'`': '\\`',
|
|
22
|
+
'$': '\\$',
|
|
24
23
|
'\\': '\\\\',
|
|
25
|
-
'\b': '\\b',
|
|
26
|
-
'\f': '\\f',
|
|
27
|
-
'\n': '\\n',
|
|
28
|
-
'\r': '\\r',
|
|
29
|
-
'\t': '\\t',
|
|
30
|
-
'\0': '\\0',
|
|
31
|
-
'\u2028': '\\u2028',
|
|
32
|
-
'\u2029': '\\u2029',
|
|
33
24
|
};
|
|
34
25
|
/**
|
|
35
26
|
* Escapes unsafe characters in a given string by replacing them with
|
|
@@ -39,7 +30,7 @@ const UNSAFE_CHAR_MAP = {
|
|
|
39
30
|
* @returns The escaped string where unsafe characters are replaced.
|
|
40
31
|
*/
|
|
41
32
|
function escapeUnsafeChars(str) {
|
|
42
|
-
return str.replace(/[
|
|
33
|
+
return str.replace(/[$`\\]/g, (c) => UNSAFE_CHAR_MAP[c]);
|
|
43
34
|
}
|
|
44
35
|
/**
|
|
45
36
|
* Generates the server manifest for the App Engine environment.
|
|
@@ -119,7 +110,7 @@ function generateAngularServerAppManifest(additionalHtmlOutputFiles, outputFiles
|
|
|
119
110
|
if (file.path === options_1.INDEX_HTML_SERVER ||
|
|
120
111
|
file.path === options_1.INDEX_HTML_CSR ||
|
|
121
112
|
(inlineCriticalCss && file.path.endsWith('.css'))) {
|
|
122
|
-
serverAssetsContent.push(`['${file.path}', async () =>
|
|
113
|
+
serverAssetsContent.push(`['${file.path}', async () => \`${escapeUnsafeChars(file.text)}\`]`);
|
|
123
114
|
}
|
|
124
115
|
}
|
|
125
116
|
const manifestContent = `
|
|
@@ -92,7 +92,7 @@ async function prerenderPages(workspaceRoot, baseHref, appShellOptions, prerende
|
|
|
92
92
|
};
|
|
93
93
|
}
|
|
94
94
|
// Render routes
|
|
95
|
-
const { errors: renderingErrors, output } = await renderPages(baseHref, sourcemap, serializableRouteTreeNodeForPrerender, maxThreads, workspaceRoot, outputFilesForWorker, assetsReversed, appShellOptions);
|
|
95
|
+
const { errors: renderingErrors, output } = await renderPages(baseHref, sourcemap, serializableRouteTreeNodeForPrerender, maxThreads, workspaceRoot, outputFilesForWorker, assetsReversed, appShellOptions, outputMode);
|
|
96
96
|
errors.push(...renderingErrors);
|
|
97
97
|
return {
|
|
98
98
|
errors,
|
|
@@ -101,7 +101,7 @@ async function prerenderPages(workspaceRoot, baseHref, appShellOptions, prerende
|
|
|
101
101
|
serializableRouteTreeNode,
|
|
102
102
|
};
|
|
103
103
|
}
|
|
104
|
-
async function renderPages(baseHref, sourcemap, serializableRouteTreeNode, maxThreads, workspaceRoot, outputFilesForWorker, assetFilesForWorker, appShellOptions) {
|
|
104
|
+
async function renderPages(baseHref, sourcemap, serializableRouteTreeNode, maxThreads, workspaceRoot, outputFilesForWorker, assetFilesForWorker, appShellOptions, outputMode) {
|
|
105
105
|
const output = {};
|
|
106
106
|
const errors = [];
|
|
107
107
|
const workerExecArgv = [
|
|
@@ -119,6 +119,8 @@ async function renderPages(baseHref, sourcemap, serializableRouteTreeNode, maxTh
|
|
|
119
119
|
workspaceRoot,
|
|
120
120
|
outputFiles: outputFilesForWorker,
|
|
121
121
|
assetFiles: assetFilesForWorker,
|
|
122
|
+
outputMode,
|
|
123
|
+
hasSsrEntry: !!outputFilesForWorker['/server.mjs'],
|
|
122
124
|
},
|
|
123
125
|
execArgv: workerExecArgv,
|
|
124
126
|
});
|
|
@@ -194,13 +196,13 @@ async function getAllRoutes(workspaceRoot, baseHref, outputFilesForWorker, asset
|
|
|
194
196
|
workspaceRoot,
|
|
195
197
|
outputFiles: outputFilesForWorker,
|
|
196
198
|
assetFiles: assetFilesForWorker,
|
|
199
|
+
outputMode,
|
|
200
|
+
hasSsrEntry: !!outputFilesForWorker['/server.mjs'],
|
|
197
201
|
},
|
|
198
202
|
execArgv: workerExecArgv,
|
|
199
203
|
});
|
|
200
204
|
try {
|
|
201
|
-
const { serializedRouteTree, errors } = await renderWorker.run({
|
|
202
|
-
outputMode,
|
|
203
|
-
});
|
|
205
|
+
const { serializedRouteTree, errors } = await renderWorker.run({});
|
|
204
206
|
return { errors, serializedRouteTree: [...routes, ...serializedRouteTree] };
|
|
205
207
|
}
|
|
206
208
|
catch (err) {
|
|
@@ -5,9 +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 type { OutputMode } from '../../builders/application/schema';
|
|
8
9
|
import type { ESMInMemoryFileLoaderWorkerData } from './esm-in-memory-loader/loader-hooks';
|
|
9
10
|
export interface RenderWorkerData extends ESMInMemoryFileLoaderWorkerData {
|
|
10
11
|
assetFiles: Record</** Destination */ string, /** Source */ string>;
|
|
12
|
+
outputMode: OutputMode | undefined;
|
|
13
|
+
hasSsrEntry: boolean;
|
|
11
14
|
}
|
|
12
15
|
export interface RenderOptions {
|
|
13
16
|
url: string;
|
|
@@ -16,5 +19,5 @@ export interface RenderOptions {
|
|
|
16
19
|
* Renders each route in routes and writes them to <outputPath>/<route>/index.html.
|
|
17
20
|
*/
|
|
18
21
|
declare function renderPage({ url }: RenderOptions): Promise<string | null>;
|
|
19
|
-
declare const _default: typeof renderPage
|
|
22
|
+
declare const _default: Promise<typeof renderPage>;
|
|
20
23
|
export default _default;
|
|
@@ -7,19 +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 worker_threads_1 = require("worker_threads");
|
|
10
11
|
const fetch_patch_1 = require("./fetch-patch");
|
|
12
|
+
const launch_server_1 = require("./launch-server");
|
|
11
13
|
const load_esm_from_memory_1 = require("./load-esm-from-memory");
|
|
14
|
+
/**
|
|
15
|
+
* This is passed as workerData when setting up the worker via the `piscina` package.
|
|
16
|
+
*/
|
|
17
|
+
const { outputMode, hasSsrEntry } = worker_threads_1.workerData;
|
|
18
|
+
let serverURL = launch_server_1.DEFAULT_URL;
|
|
12
19
|
/**
|
|
13
20
|
* Renders each route in routes and writes them to <outputPath>/<route>/index.html.
|
|
14
21
|
*/
|
|
15
22
|
async function renderPage({ url }) {
|
|
16
23
|
const { ɵgetOrCreateAngularServerApp: getOrCreateAngularServerApp } = await (0, load_esm_from_memory_1.loadEsmModuleFromMemory)('./main.server.mjs');
|
|
17
24
|
const angularServerApp = getOrCreateAngularServerApp();
|
|
18
|
-
const response = await angularServerApp.renderStatic(new URL(url,
|
|
25
|
+
const response = await angularServerApp.renderStatic(new URL(url, serverURL), AbortSignal.timeout(30_000));
|
|
19
26
|
return response ? response.text() : null;
|
|
20
27
|
}
|
|
21
|
-
function initialize() {
|
|
22
|
-
(
|
|
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);
|
|
23
33
|
return renderPage;
|
|
24
34
|
}
|
|
25
35
|
exports.default = initialize();
|
|
@@ -6,11 +6,12 @@
|
|
|
6
6
|
* found in the LICENSE file at https://angular.dev/license
|
|
7
7
|
*/
|
|
8
8
|
import { OutputMode } from '../../builders/application/schema';
|
|
9
|
+
import { ESMInMemoryFileLoaderWorkerData } from './esm-in-memory-loader/loader-hooks';
|
|
9
10
|
import { RoutersExtractorWorkerResult } from './models';
|
|
10
|
-
export interface
|
|
11
|
-
outputMode
|
|
11
|
+
export interface ExtractRoutesWorkerData extends ESMInMemoryFileLoaderWorkerData {
|
|
12
|
+
outputMode: OutputMode | undefined;
|
|
12
13
|
}
|
|
13
14
|
/** Renders an application based on a provided options. */
|
|
14
|
-
declare function extractRoutes(
|
|
15
|
-
declare const _default: typeof extractRoutes
|
|
15
|
+
declare function extractRoutes(): Promise<RoutersExtractorWorkerResult>;
|
|
16
|
+
declare const _default: Promise<typeof extractRoutes>;
|
|
16
17
|
export default _default;
|
|
@@ -7,20 +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 worker_threads_1 = require("worker_threads");
|
|
10
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");
|
|
15
|
+
/**
|
|
16
|
+
* This is passed as workerData when setting up the worker via the `piscina` package.
|
|
17
|
+
*/
|
|
18
|
+
const { outputMode, hasSsrEntry } = worker_threads_1.workerData;
|
|
19
|
+
let serverURL = launch_server_1.DEFAULT_URL;
|
|
13
20
|
/** Renders an application based on a provided options. */
|
|
14
|
-
async function extractRoutes(
|
|
21
|
+
async function extractRoutes() {
|
|
15
22
|
const { ɵextractRoutesAndCreateRouteTree: extractRoutesAndCreateRouteTree } = await (0, load_esm_from_memory_1.loadEsmModuleFromMemory)('./main.server.mjs');
|
|
16
|
-
const { routeTree, errors } = await extractRoutesAndCreateRouteTree(
|
|
23
|
+
const { routeTree, errors } = await extractRoutesAndCreateRouteTree(serverURL, undefined /** manifest */, true /** invokeGetPrerenderParams */, outputMode === schema_1.OutputMode.Server /** includePrerenderFallbackRoutes */);
|
|
17
24
|
return {
|
|
18
25
|
errors,
|
|
19
26
|
serializedRouteTree: routeTree.toObject(),
|
|
20
27
|
};
|
|
21
28
|
}
|
|
22
|
-
function initialize() {
|
|
23
|
-
(
|
|
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);
|
|
24
34
|
return extractRoutes;
|
|
25
35
|
}
|
|
26
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
|
+
}
|