@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
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.10",
|
|
4
4
|
"description": "Official build system for Angular",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"Angular CLI",
|
|
@@ -23,41 +23,45 @@
|
|
|
23
23
|
"builders": "builders.json",
|
|
24
24
|
"dependencies": {
|
|
25
25
|
"@ampproject/remapping": "2.3.0",
|
|
26
|
-
"@angular-devkit/architect": "0.1900.0-next.
|
|
27
|
-
"@babel/core": "7.25.
|
|
28
|
-
"@babel/helper-annotate-as-pure": "7.
|
|
26
|
+
"@angular-devkit/architect": "0.1900.0-next.10",
|
|
27
|
+
"@babel/core": "7.25.7",
|
|
28
|
+
"@babel/helper-annotate-as-pure": "7.25.7",
|
|
29
29
|
"@babel/helper-split-export-declaration": "7.24.7",
|
|
30
|
-
"@babel/plugin-syntax-import-attributes": "7.
|
|
31
|
-
"@inquirer/confirm": "
|
|
30
|
+
"@babel/plugin-syntax-import-attributes": "7.25.7",
|
|
31
|
+
"@inquirer/confirm": "5.0.0",
|
|
32
32
|
"@vitejs/plugin-basic-ssl": "1.1.0",
|
|
33
33
|
"browserslist": "^4.23.0",
|
|
34
34
|
"critters": "0.0.24",
|
|
35
|
-
"esbuild": "0.
|
|
35
|
+
"esbuild": "0.24.0",
|
|
36
36
|
"fast-glob": "3.3.2",
|
|
37
37
|
"https-proxy-agent": "7.0.5",
|
|
38
|
-
"
|
|
39
|
-
"
|
|
38
|
+
"istanbul-lib-instrument": "6.0.3",
|
|
39
|
+
"listr2": "8.2.5",
|
|
40
40
|
"magic-string": "0.30.11",
|
|
41
41
|
"mrmime": "2.0.0",
|
|
42
42
|
"parse5-html-rewriting-stream": "7.0.0",
|
|
43
43
|
"picomatch": "4.0.2",
|
|
44
|
-
"piscina": "4.
|
|
45
|
-
"rollup": "4.
|
|
46
|
-
"sass": "1.
|
|
44
|
+
"piscina": "4.7.0",
|
|
45
|
+
"rollup": "4.24.0",
|
|
46
|
+
"sass": "1.79.4",
|
|
47
47
|
"semver": "7.6.3",
|
|
48
|
-
"vite": "5.4.
|
|
48
|
+
"vite": "5.4.8",
|
|
49
49
|
"watchpack": "2.4.2"
|
|
50
50
|
},
|
|
51
|
+
"optionalDependencies": {
|
|
52
|
+
"lmdb": "3.1.3"
|
|
53
|
+
},
|
|
51
54
|
"peerDependencies": {
|
|
55
|
+
"@angular/compiler": "^19.0.0-next.0",
|
|
52
56
|
"@angular/compiler-cli": "^19.0.0-next.0",
|
|
53
57
|
"@angular/localize": "^19.0.0-next.0",
|
|
54
58
|
"@angular/platform-server": "^19.0.0-next.0",
|
|
55
59
|
"@angular/service-worker": "^19.0.0-next.0",
|
|
56
|
-
"@angular/ssr": "^19.0.0-next.
|
|
60
|
+
"@angular/ssr": "^19.0.0-next.10",
|
|
57
61
|
"less": "^4.2.0",
|
|
58
62
|
"postcss": "^8.4.0",
|
|
59
63
|
"tailwindcss": "^2.0.0 || ^3.0.0",
|
|
60
|
-
"typescript": ">=5.
|
|
64
|
+
"typescript": ">=5.5 <5.7"
|
|
61
65
|
},
|
|
62
66
|
"peerDependenciesMeta": {
|
|
63
67
|
"@angular/localize": {
|
|
@@ -82,7 +86,7 @@
|
|
|
82
86
|
"optional": true
|
|
83
87
|
}
|
|
84
88
|
},
|
|
85
|
-
"packageManager": "yarn@4.
|
|
89
|
+
"packageManager": "yarn@4.5.0",
|
|
86
90
|
"repository": {
|
|
87
91
|
"type": "git",
|
|
88
92
|
"url": "https://github.com/angular/angular-cli.git"
|
|
@@ -83,12 +83,6 @@ async function* runEsBuildBuildAction(action, options) {
|
|
|
83
83
|
cacheOptions.basePath,
|
|
84
84
|
`${workspaceRoot.replace(/\\/g, '/')}/**/.*/**`,
|
|
85
85
|
];
|
|
86
|
-
if (!preserveSymlinks) {
|
|
87
|
-
// Ignore all node modules directories to avoid excessive file watchers.
|
|
88
|
-
// Package changes are handled below by watching manifest and lock files.
|
|
89
|
-
// NOTE: this is not enable when preserveSymlinks is true as this would break `npm link` usages.
|
|
90
|
-
ignored.push('**/node_modules/**');
|
|
91
|
-
}
|
|
92
86
|
// Setup a watcher
|
|
93
87
|
const { createWatcher } = await Promise.resolve().then(() => __importStar(require('../../tools/esbuild/watcher')));
|
|
94
88
|
watcher = createWatcher({
|
|
@@ -101,11 +95,17 @@ async function* runEsBuildBuildAction(action, options) {
|
|
|
101
95
|
options.signal?.addEventListener('abort', () => void watcher?.close());
|
|
102
96
|
// Watch the entire project root if 'NG_BUILD_WATCH_ROOT' environment variable is set
|
|
103
97
|
if (environment_options_1.shouldWatchRoot) {
|
|
98
|
+
if (!preserveSymlinks) {
|
|
99
|
+
// Ignore all node modules directories to avoid excessive file watchers.
|
|
100
|
+
// Package changes are handled below by watching manifest and lock files.
|
|
101
|
+
// NOTE: this is not enable when preserveSymlinks is true as this would break `npm link` usages.
|
|
102
|
+
ignored.push('**/node_modules/**');
|
|
103
|
+
watcher.add(packageWatchFiles
|
|
104
|
+
.map((file) => node_path_1.default.join(workspaceRoot, file))
|
|
105
|
+
.filter((file) => (0, node_fs_1.existsSync)(file)));
|
|
106
|
+
}
|
|
104
107
|
watcher.add(projectRoot);
|
|
105
108
|
}
|
|
106
|
-
watcher.add(packageWatchFiles
|
|
107
|
-
.map((file) => node_path_1.default.join(workspaceRoot, file))
|
|
108
|
-
.filter((file) => (0, node_fs_1.existsSync)(file)));
|
|
109
109
|
// Watch locations provided by the initial build result
|
|
110
110
|
watcher.add(result.watchFiles);
|
|
111
111
|
}
|
|
@@ -83,10 +83,7 @@ async function optimizeChunks(original, sourcemap) {
|
|
|
83
83
|
const result = await bundle.generate({
|
|
84
84
|
compact: true,
|
|
85
85
|
sourcemap,
|
|
86
|
-
chunkFileNames(chunkInfo) {
|
|
87
|
-
// Do not add hash to file name if already present
|
|
88
|
-
return /-[a-zA-Z0-9]{8}$/.test(chunkInfo.name) ? '[name].js' : '[name]-[hash].js';
|
|
89
|
-
},
|
|
86
|
+
chunkFileNames: (chunkInfo) => `${chunkInfo.name.replace(/-[a-zA-Z0-9]{8}$/, '')}-[hash].js`,
|
|
90
87
|
});
|
|
91
88
|
optimizedOutput = result.output;
|
|
92
89
|
}
|
|
@@ -6,8 +6,12 @@
|
|
|
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
|
+
};
|
|
9
12
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
10
13
|
exports.executeBuild = executeBuild;
|
|
14
|
+
const node_assert_1 = __importDefault(require("node:assert"));
|
|
11
15
|
const source_file_cache_1 = require("../../tools/esbuild/angular/source-file-cache");
|
|
12
16
|
const budget_stats_1 = require("../../tools/esbuild/budget-stats");
|
|
13
17
|
const bundler_context_1 = require("../../tools/esbuild/bundler-context");
|
|
@@ -19,13 +23,16 @@ const utils_1 = require("../../tools/esbuild/utils");
|
|
|
19
23
|
const bundle_calculator_1 = require("../../utils/bundle-calculator");
|
|
20
24
|
const environment_options_1 = require("../../utils/environment-options");
|
|
21
25
|
const resolve_assets_1 = require("../../utils/resolve-assets");
|
|
26
|
+
const manifest_1 = require("../../utils/server-rendering/manifest");
|
|
22
27
|
const supported_browsers_1 = require("../../utils/supported-browsers");
|
|
23
28
|
const chunk_optimizer_1 = require("./chunk-optimizer");
|
|
24
29
|
const execute_post_bundle_1 = require("./execute-post-bundle");
|
|
25
30
|
const i18n_1 = require("./i18n");
|
|
31
|
+
const schema_1 = require("./schema");
|
|
26
32
|
const setup_bundling_1 = require("./setup-bundling");
|
|
33
|
+
// eslint-disable-next-line max-lines-per-function
|
|
27
34
|
async function executeBuild(options, context, rebuildState) {
|
|
28
|
-
const { projectRoot, workspaceRoot, i18nOptions, optimizationOptions, assets, cacheOptions,
|
|
35
|
+
const { projectRoot, workspaceRoot, i18nOptions, optimizationOptions, assets, outputMode, cacheOptions, serverEntryPoint, baseHref, ssrOptions, verbose, colors, jsonLogs, } = options;
|
|
29
36
|
// TODO: Consider integrating into watch mode. Would require full rebuild on target changes.
|
|
30
37
|
const browsers = (0, supported_browsers_1.getSupportedBrowsers)(projectRoot, context.logger);
|
|
31
38
|
// Load active translations if inlining
|
|
@@ -104,6 +111,10 @@ async function executeBuild(options, context, rebuildState) {
|
|
|
104
111
|
executionResult.htmlIndexPath = options.indexHtmlOptions.output;
|
|
105
112
|
executionResult.htmlBaseHref = options.baseHref;
|
|
106
113
|
}
|
|
114
|
+
// Create server app engine manifest
|
|
115
|
+
if (serverEntryPoint) {
|
|
116
|
+
executionResult.addOutputFile(manifest_1.SERVER_APP_ENGINE_MANIFEST_FILENAME, (0, manifest_1.generateAngularServerAppEngineManifest)(i18nOptions, baseHref, undefined), bundler_context_1.BuildOutputFileType.ServerRoot);
|
|
117
|
+
}
|
|
107
118
|
// Perform i18n translation inlining if enabled
|
|
108
119
|
if (i18nOptions.shouldInline) {
|
|
109
120
|
const result = await (0, i18n_1.inlineI18n)(options, executionResult, initialFiles);
|
|
@@ -121,8 +132,14 @@ async function executeBuild(options, context, rebuildState) {
|
|
|
121
132
|
executionResult.outputFiles.push(...result.additionalOutputFiles);
|
|
122
133
|
executionResult.assetFiles.push(...result.additionalAssets);
|
|
123
134
|
}
|
|
124
|
-
if (
|
|
135
|
+
if (serverEntryPoint) {
|
|
125
136
|
const prerenderedRoutes = executionResult.prerenderedRoutes;
|
|
137
|
+
// Regenerate the manifest to append prerendered routes data. This is only needed if SSR is enabled.
|
|
138
|
+
if (outputMode === schema_1.OutputMode.Server && Object.keys(prerenderedRoutes).length) {
|
|
139
|
+
const manifest = executionResult.outputFiles.find((f) => f.path === manifest_1.SERVER_APP_ENGINE_MANIFEST_FILENAME);
|
|
140
|
+
(0, node_assert_1.default)(manifest, `${manifest_1.SERVER_APP_ENGINE_MANIFEST_FILENAME} was not found in output files.`);
|
|
141
|
+
manifest.contents = new TextEncoder().encode((0, manifest_1.generateAngularServerAppEngineManifest)(i18nOptions, baseHref, prerenderedRoutes));
|
|
142
|
+
}
|
|
126
143
|
executionResult.addOutputFile('prerendered-routes.json', JSON.stringify({ routes: prerenderedRoutes }, null, 2), bundler_context_1.BuildOutputFileType.Root);
|
|
127
144
|
}
|
|
128
145
|
// Write metafile if stats option is enabled
|
|
@@ -6,7 +6,7 @@
|
|
|
6
6
|
* found in the LICENSE file at https://angular.dev/license
|
|
7
7
|
*/
|
|
8
8
|
import { BuildOutputFile, InitialFileRecord } from '../../tools/esbuild/bundler-context';
|
|
9
|
-
import { BuildOutputAsset } from '../../tools/esbuild/bundler-execution-result';
|
|
9
|
+
import { BuildOutputAsset, PrerenderedRoutesRecord } from '../../tools/esbuild/bundler-execution-result';
|
|
10
10
|
import { NormalizedApplicationBuildOptions } from './options';
|
|
11
11
|
/**
|
|
12
12
|
* Run additional builds steps including SSG, AppShell, Index HTML file and Service worker generation.
|
|
@@ -21,5 +21,5 @@ export declare function executePostBundleSteps(options: NormalizedApplicationBui
|
|
|
21
21
|
warnings: string[];
|
|
22
22
|
additionalOutputFiles: BuildOutputFile[];
|
|
23
23
|
additionalAssets: BuildOutputAsset[];
|
|
24
|
-
prerenderedRoutes:
|
|
24
|
+
prerenderedRoutes: PrerenderedRoutesRecord;
|
|
25
25
|
}>;
|
|
@@ -16,8 +16,12 @@ const bundler_context_1 = require("../../tools/esbuild/bundler-context");
|
|
|
16
16
|
const index_html_generator_1 = require("../../tools/esbuild/index-html-generator");
|
|
17
17
|
const utils_1 = require("../../tools/esbuild/utils");
|
|
18
18
|
const environment_options_1 = require("../../utils/environment-options");
|
|
19
|
+
const manifest_1 = require("../../utils/server-rendering/manifest");
|
|
20
|
+
const models_1 = require("../../utils/server-rendering/models");
|
|
19
21
|
const prerender_1 = require("../../utils/server-rendering/prerender");
|
|
20
22
|
const service_worker_1 = require("../../utils/service-worker");
|
|
23
|
+
const options_1 = require("./options");
|
|
24
|
+
const schema_1 = require("./schema");
|
|
21
25
|
/**
|
|
22
26
|
* Run additional builds steps including SSG, AppShell, Index HTML file and Service worker generation.
|
|
23
27
|
* @param options The normalized application builder options used to create the build.
|
|
@@ -31,16 +35,12 @@ async function executePostBundleSteps(options, outputFiles, assetFiles, initialF
|
|
|
31
35
|
const additionalOutputFiles = [];
|
|
32
36
|
const allErrors = [];
|
|
33
37
|
const allWarnings = [];
|
|
34
|
-
const prerenderedRoutes =
|
|
35
|
-
const { serviceWorker, indexHtmlOptions, optimizationOptions, sourcemapOptions, prerenderOptions, appShellOptions, workspaceRoot,
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
*/
|
|
41
|
-
let ssrIndexContent;
|
|
42
|
-
// When using prerender/app-shell the index HTML file can be regenerated.
|
|
43
|
-
// Thus, we use a Map so that we do not generate 2 files with the same filename.
|
|
38
|
+
const prerenderedRoutes = {};
|
|
39
|
+
const { baseHref = '/', serviceWorker, indexHtmlOptions, optimizationOptions, sourcemapOptions, outputMode, serverEntryPoint, prerenderOptions, appShellOptions, workspaceRoot, partialSSRBuild, } = options;
|
|
40
|
+
// Index HTML content without CSS inlining to be used for server rendering (AppShell, SSG and SSR).
|
|
41
|
+
// NOTE: Critical CSS inlining is deliberately omitted here, as it will be handled during server rendering.
|
|
42
|
+
// Additionally, when using prerendering or AppShell, the index HTML file may be regenerated.
|
|
43
|
+
// To prevent generating duplicate files with the same filename, a `Map` is used to store and manage the files.
|
|
44
44
|
const additionalHtmlOutputFiles = new Map();
|
|
45
45
|
// Generate index HTML file
|
|
46
46
|
// If localization is enabled, index generation is handled in the inlining process.
|
|
@@ -50,21 +50,59 @@ async function executePostBundleSteps(options, outputFiles, assetFiles, initialF
|
|
|
50
50
|
allWarnings.push(...warnings);
|
|
51
51
|
additionalHtmlOutputFiles.set(indexHtmlOptions.output, (0, utils_1.createOutputFile)(indexHtmlOptions.output, csrContent, bundler_context_1.BuildOutputFileType.Browser));
|
|
52
52
|
if (ssrContent) {
|
|
53
|
-
|
|
54
|
-
additionalHtmlOutputFiles.set(serverIndexHtmlFilename, (0, utils_1.createOutputFile)(serverIndexHtmlFilename, ssrContent, bundler_context_1.BuildOutputFileType.Server));
|
|
55
|
-
ssrIndexContent = ssrContent;
|
|
53
|
+
additionalHtmlOutputFiles.set(options_1.INDEX_HTML_SERVER, (0, utils_1.createOutputFile)(options_1.INDEX_HTML_SERVER, ssrContent, bundler_context_1.BuildOutputFileType.ServerApplication));
|
|
56
54
|
}
|
|
57
55
|
}
|
|
56
|
+
// Create server manifest
|
|
57
|
+
if (serverEntryPoint) {
|
|
58
|
+
additionalOutputFiles.push((0, utils_1.createOutputFile)(manifest_1.SERVER_APP_MANIFEST_FILENAME, (0, manifest_1.generateAngularServerAppManifest)(additionalHtmlOutputFiles, outputFiles, optimizationOptions.styles.inlineCritical ?? false, undefined, locale), bundler_context_1.BuildOutputFileType.ServerApplication));
|
|
59
|
+
}
|
|
58
60
|
// Pre-render (SSG) and App-shell
|
|
59
61
|
// If localization is enabled, prerendering is handled in the inlining process.
|
|
60
|
-
if (
|
|
61
|
-
(
|
|
62
|
-
|
|
62
|
+
if (!partialSSRBuild &&
|
|
63
|
+
(prerenderOptions || appShellOptions || (outputMode && serverEntryPoint)) &&
|
|
64
|
+
!allErrors.length) {
|
|
65
|
+
(0, node_assert_1.default)(indexHtmlOptions, 'The "index" option is required when using the "ssg" or "appShell" options.');
|
|
66
|
+
const { output, warnings, errors, serializableRouteTreeNode } = await (0, prerender_1.prerenderPages)(workspaceRoot, baseHref, appShellOptions, prerenderOptions, [...outputFiles, ...additionalOutputFiles], assetFiles, outputMode, sourcemapOptions.scripts, environment_options_1.maxWorkers);
|
|
63
67
|
allErrors.push(...errors);
|
|
64
68
|
allWarnings.push(...warnings);
|
|
65
|
-
|
|
66
|
-
for (const [path, content] of Object.entries(output)) {
|
|
67
|
-
|
|
69
|
+
const indexHasBeenPrerendered = output[indexHtmlOptions.output];
|
|
70
|
+
for (const [path, { content, appShellRoute }] of Object.entries(output)) {
|
|
71
|
+
// Update the index contents with the app shell under these conditions:
|
|
72
|
+
// - Replace 'index.html' with the app shell only if it hasn't been prerendered yet.
|
|
73
|
+
// - Always replace 'index.csr.html' with the app shell.
|
|
74
|
+
let filePath = path;
|
|
75
|
+
if (appShellRoute && !indexHasBeenPrerendered) {
|
|
76
|
+
if (outputMode !== schema_1.OutputMode.Server && indexHtmlOptions.output === options_1.INDEX_HTML_CSR) {
|
|
77
|
+
filePath = 'index.html';
|
|
78
|
+
}
|
|
79
|
+
else {
|
|
80
|
+
filePath = indexHtmlOptions.output;
|
|
81
|
+
}
|
|
82
|
+
}
|
|
83
|
+
additionalHtmlOutputFiles.set(filePath, (0, utils_1.createOutputFile)(filePath, content, bundler_context_1.BuildOutputFileType.Browser));
|
|
84
|
+
}
|
|
85
|
+
const serializableRouteTreeNodeForManifest = [];
|
|
86
|
+
for (const metadata of serializableRouteTreeNode) {
|
|
87
|
+
switch (metadata.renderMode) {
|
|
88
|
+
case models_1.RouteRenderMode.Prerender:
|
|
89
|
+
case /* Legacy building mode */ undefined: {
|
|
90
|
+
if (!metadata.redirectTo || outputMode === schema_1.OutputMode.Static) {
|
|
91
|
+
prerenderedRoutes[metadata.route] = { headers: metadata.headers };
|
|
92
|
+
}
|
|
93
|
+
break;
|
|
94
|
+
}
|
|
95
|
+
case models_1.RouteRenderMode.Server:
|
|
96
|
+
case models_1.RouteRenderMode.Client:
|
|
97
|
+
serializableRouteTreeNodeForManifest.push(metadata);
|
|
98
|
+
break;
|
|
99
|
+
}
|
|
100
|
+
}
|
|
101
|
+
if (outputMode === schema_1.OutputMode.Server) {
|
|
102
|
+
// Regenerate the manifest to append route tree. This is only needed if SSR is enabled.
|
|
103
|
+
const manifest = additionalOutputFiles.find((f) => f.path === manifest_1.SERVER_APP_MANIFEST_FILENAME);
|
|
104
|
+
(0, node_assert_1.default)(manifest, `${manifest_1.SERVER_APP_MANIFEST_FILENAME} was not found in output files.`);
|
|
105
|
+
manifest.contents = new TextEncoder().encode((0, manifest_1.generateAngularServerAppManifest)(additionalHtmlOutputFiles, outputFiles, optimizationOptions.styles.inlineCritical ?? false, serializableRouteTreeNodeForManifest, locale));
|
|
68
106
|
}
|
|
69
107
|
}
|
|
70
108
|
additionalOutputFiles.push(...additionalHtmlOutputFiles.values());
|
|
@@ -72,7 +110,7 @@ async function executePostBundleSteps(options, outputFiles, assetFiles, initialF
|
|
|
72
110
|
// If localization is enabled, service worker is handled in the inlining process.
|
|
73
111
|
if (serviceWorker) {
|
|
74
112
|
try {
|
|
75
|
-
const serviceWorkerResult = await (0, service_worker_1.augmentAppWithServiceWorkerEsbuild)(workspaceRoot, serviceWorker,
|
|
113
|
+
const serviceWorkerResult = await (0, service_worker_1.augmentAppWithServiceWorkerEsbuild)(workspaceRoot, serviceWorker, baseHref, options.indexHtmlOptions?.output,
|
|
76
114
|
// Ensure additional files recently added are used
|
|
77
115
|
[...outputFiles, ...additionalOutputFiles], assetFiles);
|
|
78
116
|
additionalOutputFiles.push((0, utils_1.createOutputFile)('ngsw.json', serviceWorkerResult.manifest, bundler_context_1.BuildOutputFileType.Browser));
|
|
@@ -7,7 +7,7 @@
|
|
|
7
7
|
*/
|
|
8
8
|
import { BuilderContext } from '@angular-devkit/architect';
|
|
9
9
|
import { InitialFileRecord } from '../../tools/esbuild/bundler-context';
|
|
10
|
-
import { ExecutionResult } from '../../tools/esbuild/bundler-execution-result';
|
|
10
|
+
import { ExecutionResult, PrerenderedRoutesRecord } from '../../tools/esbuild/bundler-execution-result';
|
|
11
11
|
import { NormalizedApplicationBuildOptions } from './options';
|
|
12
12
|
/**
|
|
13
13
|
* Inlines all active locales as specified by the application build options into all
|
|
@@ -19,7 +19,7 @@ import { NormalizedApplicationBuildOptions } from './options';
|
|
|
19
19
|
export declare function inlineI18n(options: NormalizedApplicationBuildOptions, executionResult: ExecutionResult, initialFiles: Map<string, InitialFileRecord>): Promise<{
|
|
20
20
|
errors: string[];
|
|
21
21
|
warnings: string[];
|
|
22
|
-
prerenderedRoutes:
|
|
22
|
+
prerenderedRoutes: PrerenderedRoutesRecord;
|
|
23
23
|
}>;
|
|
24
24
|
/**
|
|
25
25
|
* Loads all active translations using the translation loaders from the `@angular/localize` package.
|
|
@@ -15,8 +15,8 @@ const i18n_inliner_1 = require("../../tools/esbuild/i18n-inliner");
|
|
|
15
15
|
const environment_options_1 = require("../../utils/environment-options");
|
|
16
16
|
const i18n_options_1 = require("../../utils/i18n-options");
|
|
17
17
|
const load_translations_1 = require("../../utils/load-translations");
|
|
18
|
-
const url_1 = require("../../utils/url");
|
|
19
18
|
const execute_post_bundle_1 = require("./execute-post-bundle");
|
|
19
|
+
const options_1 = require("./options");
|
|
20
20
|
/**
|
|
21
21
|
* Inlines all active locales as specified by the application build options into all
|
|
22
22
|
* application JavaScript files created during the build.
|
|
@@ -34,7 +34,7 @@ async function inlineI18n(options, executionResult, initialFiles) {
|
|
|
34
34
|
const inlineResult = {
|
|
35
35
|
errors: [],
|
|
36
36
|
warnings: [],
|
|
37
|
-
prerenderedRoutes:
|
|
37
|
+
prerenderedRoutes: {},
|
|
38
38
|
};
|
|
39
39
|
// For each active locale, use the inliner to process the output files of the build.
|
|
40
40
|
const updatedOutputFiles = [];
|
|
@@ -46,7 +46,7 @@ async function inlineI18n(options, executionResult, initialFiles) {
|
|
|
46
46
|
const localeOutputFiles = localeInlineResult.outputFiles;
|
|
47
47
|
inlineResult.errors.push(...localeInlineResult.errors);
|
|
48
48
|
inlineResult.warnings.push(...localeInlineResult.warnings);
|
|
49
|
-
const baseHref = getLocaleBaseHref(options.baseHref, options.i18nOptions, locale) ?? options.baseHref;
|
|
49
|
+
const baseHref = (0, options_1.getLocaleBaseHref)(options.baseHref, options.i18nOptions, locale) ?? options.baseHref;
|
|
50
50
|
const { errors, warnings, additionalAssets, additionalOutputFiles, prerenderedRoutes: generatedRoutes, } = await (0, execute_post_bundle_1.executePostBundleSteps)({
|
|
51
51
|
...options,
|
|
52
52
|
baseHref,
|
|
@@ -65,12 +65,11 @@ async function inlineI18n(options, executionResult, initialFiles) {
|
|
|
65
65
|
destination: (0, node_path_1.join)(locale, assetFile.destination),
|
|
66
66
|
});
|
|
67
67
|
}
|
|
68
|
-
inlineResult.prerenderedRoutes.push(...generatedRoutes.map((route) => node_path_1.posix.join('/', locale, route)));
|
|
69
68
|
}
|
|
70
69
|
else {
|
|
71
|
-
inlineResult.prerenderedRoutes.push(...generatedRoutes);
|
|
72
70
|
executionResult.assetFiles.push(...additionalAssets);
|
|
73
71
|
}
|
|
72
|
+
inlineResult.prerenderedRoutes = { ...inlineResult.prerenderedRoutes, ...generatedRoutes };
|
|
74
73
|
updatedOutputFiles.push(...localeOutputFiles);
|
|
75
74
|
}
|
|
76
75
|
}
|
|
@@ -79,8 +78,8 @@ async function inlineI18n(options, executionResult, initialFiles) {
|
|
|
79
78
|
}
|
|
80
79
|
// Update the result with all localized files.
|
|
81
80
|
executionResult.outputFiles = [
|
|
82
|
-
// Root files are not modified.
|
|
83
|
-
...executionResult.outputFiles.filter(({ type }) => type === bundler_context_1.BuildOutputFileType.Root),
|
|
81
|
+
// Root and SSR entry files are not modified.
|
|
82
|
+
...executionResult.outputFiles.filter(({ type }) => type === bundler_context_1.BuildOutputFileType.Root || type === bundler_context_1.BuildOutputFileType.ServerRoot),
|
|
84
83
|
// Updated files for each locale.
|
|
85
84
|
...updatedOutputFiles,
|
|
86
85
|
];
|
|
@@ -90,15 +89,6 @@ async function inlineI18n(options, executionResult, initialFiles) {
|
|
|
90
89
|
}
|
|
91
90
|
return inlineResult;
|
|
92
91
|
}
|
|
93
|
-
function getLocaleBaseHref(baseHref, i18n, locale) {
|
|
94
|
-
if (i18n.flatOutput) {
|
|
95
|
-
return undefined;
|
|
96
|
-
}
|
|
97
|
-
if (i18n.locales[locale] && i18n.locales[locale].baseHref !== '') {
|
|
98
|
-
return (0, url_1.urlJoin)(baseHref || '', i18n.locales[locale].baseHref ?? `/${locale}/`);
|
|
99
|
-
}
|
|
100
|
-
return undefined;
|
|
101
|
-
}
|
|
102
92
|
/**
|
|
103
93
|
* Loads all active translations using the translation loaders from the `@angular/localize` package.
|
|
104
94
|
* @param context The architect builder context for the current build.
|
|
@@ -65,15 +65,15 @@ context, extensions) {
|
|
|
65
65
|
context.addTeardown(() => controller.abort('builder-teardown'));
|
|
66
66
|
}
|
|
67
67
|
yield* (0, build_action_1.runEsBuildBuildAction)(async (rebuildState) => {
|
|
68
|
-
const {
|
|
68
|
+
const { serverEntryPoint, jsonLogs, partialSSRBuild } = normalizedOptions;
|
|
69
69
|
const startTime = process.hrtime.bigint();
|
|
70
70
|
const result = await (0, execute_build_1.executeBuild)(normalizedOptions, context, rebuildState);
|
|
71
71
|
if (jsonLogs) {
|
|
72
72
|
result.addLog(await (0, utils_1.createJsonBuildManifest)(result, normalizedOptions));
|
|
73
73
|
}
|
|
74
74
|
else {
|
|
75
|
-
if (
|
|
76
|
-
const prerenderedRoutesLength = result.prerenderedRoutes.length;
|
|
75
|
+
if (serverEntryPoint && !partialSSRBuild) {
|
|
76
|
+
const prerenderedRoutesLength = Object.keys(result.prerenderedRoutes).length;
|
|
77
77
|
let prerenderMsg = `Prerendered ${prerenderedRoutesLength} static route`;
|
|
78
78
|
prerenderMsg += prerenderedRoutesLength !== 1 ? 's.' : '.';
|
|
79
79
|
result.addLog(color_1.colors.magenta(prerenderMsg));
|
|
@@ -137,7 +137,9 @@ async function* buildApplication(options, context, pluginsOrExtensions) {
|
|
|
137
137
|
// Writes the output files to disk and ensures the containing directories are present
|
|
138
138
|
const directoryExists = new Set();
|
|
139
139
|
await (0, utils_1.emitFilesToDisk)(Object.entries(result.files), async ([filePath, file]) => {
|
|
140
|
-
if (outputOptions.ignoreServer &&
|
|
140
|
+
if (outputOptions.ignoreServer &&
|
|
141
|
+
(file.type === bundler_context_1.BuildOutputFileType.ServerApplication ||
|
|
142
|
+
file.type === bundler_context_1.BuildOutputFileType.ServerRoot)) {
|
|
141
143
|
return;
|
|
142
144
|
}
|
|
143
145
|
let typeDirectory;
|
|
@@ -146,7 +148,8 @@ async function* buildApplication(options, context, pluginsOrExtensions) {
|
|
|
146
148
|
case bundler_context_1.BuildOutputFileType.Media:
|
|
147
149
|
typeDirectory = outputOptions.browser;
|
|
148
150
|
break;
|
|
149
|
-
case bundler_context_1.BuildOutputFileType.
|
|
151
|
+
case bundler_context_1.BuildOutputFileType.ServerApplication:
|
|
152
|
+
case bundler_context_1.BuildOutputFileType.ServerRoot:
|
|
150
153
|
typeDirectory = outputOptions.server;
|
|
151
154
|
break;
|
|
152
155
|
case bundler_context_1.BuildOutputFileType.Root:
|
|
@@ -9,7 +9,17 @@ import type { BuilderContext } from '@angular-devkit/architect';
|
|
|
9
9
|
import type { Plugin } from 'esbuild';
|
|
10
10
|
import { I18nOptions } from '../../utils/i18n-options';
|
|
11
11
|
import { IndexHtmlTransform } from '../../utils/index-file/index-html-generator';
|
|
12
|
-
import { Schema as ApplicationBuilderOptions, I18NTranslation, OutputPathClass } from './schema';
|
|
12
|
+
import { Schema as ApplicationBuilderOptions, I18NTranslation, OutputMode, OutputPathClass } from './schema';
|
|
13
|
+
/**
|
|
14
|
+
* The filename for the client-side rendered HTML template.
|
|
15
|
+
* This template is used for client-side rendering (CSR) in a web application.
|
|
16
|
+
*/
|
|
17
|
+
export declare const INDEX_HTML_CSR = "index.csr.html";
|
|
18
|
+
/**
|
|
19
|
+
* The filename for the server-side rendered HTML template.
|
|
20
|
+
* This template is used for server-side rendering (SSR) in a web application.
|
|
21
|
+
*/
|
|
22
|
+
export declare const INDEX_HTML_SERVER = "index.server.html";
|
|
13
23
|
export type NormalizedOutputOptions = Required<OutputPathClass> & {
|
|
14
24
|
clean: boolean;
|
|
15
25
|
ignoreServer: boolean;
|
|
@@ -42,6 +52,26 @@ interface InternalOptions {
|
|
|
42
52
|
* This is only used by the development server which currently only supports a single locale per build.
|
|
43
53
|
*/
|
|
44
54
|
forceI18nFlatOutput?: boolean;
|
|
55
|
+
/**
|
|
56
|
+
* When set to `true`, enables fast SSR in development mode by disabling the full manifest generation and prerendering.
|
|
57
|
+
*
|
|
58
|
+
* This option is intended to optimize performance during development by skipping prerendering and route extraction when not required.
|
|
59
|
+
* @default false
|
|
60
|
+
*/
|
|
61
|
+
partialSSRBuild?: boolean;
|
|
62
|
+
/**
|
|
63
|
+
* Enables the use of AOT compiler emitted external runtime styles.
|
|
64
|
+
* External runtime styles use `link` elements instead of embedded style content in the output JavaScript.
|
|
65
|
+
* This option is only intended to be used with a development server that can process and serve component
|
|
66
|
+
* styles.
|
|
67
|
+
*/
|
|
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;
|
|
45
75
|
}
|
|
46
76
|
/** Full set of options for `application` builder. */
|
|
47
77
|
export type ApplicationBuilderInternalOptions = Omit<ApplicationBuilderOptions & InternalOptions, 'browser'> & {
|
|
@@ -86,6 +116,7 @@ export declare function normalizeOptions(context: BuilderContext, projectName: s
|
|
|
86
116
|
appShellOptions: {
|
|
87
117
|
route: string;
|
|
88
118
|
} | undefined;
|
|
119
|
+
outputMode: OutputMode | undefined;
|
|
89
120
|
ssrOptions: {
|
|
90
121
|
entry?: undefined;
|
|
91
122
|
} | {
|
|
@@ -147,5 +178,9 @@ export declare function normalizeOptions(context: BuilderContext, projectName: s
|
|
|
147
178
|
define: {
|
|
148
179
|
[key: string]: string;
|
|
149
180
|
} | undefined;
|
|
181
|
+
partialSSRBuild: boolean;
|
|
182
|
+
externalRuntimeStyles: boolean | undefined;
|
|
183
|
+
instrumentForCoverage: ((filename: string) => boolean) | undefined;
|
|
150
184
|
}>;
|
|
185
|
+
export declare function getLocaleBaseHref(baseHref: string | undefined, i18n: NormalizedApplicationBuildOptions['i18nOptions'], locale: string): string | undefined;
|
|
151
186
|
export {};
|