@angular/build 19.0.0-next.9 → 19.0.0-rc.1
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 +21 -19
- package/src/builders/application/build-action.js +22 -10
- package/src/builders/application/chunk-optimizer.js +1 -4
- package/src/builders/application/execute-build.js +59 -24
- package/src/builders/application/execute-post-bundle.js +28 -5
- package/src/builders/application/index.d.ts +0 -16
- package/src/builders/application/index.js +15 -10
- package/src/builders/application/options.d.ts +14 -2
- package/src/builders/application/options.js +25 -10
- package/src/builders/application/results.d.ts +5 -3
- package/src/builders/application/schema.d.ts +86 -0
- package/src/builders/application/schema.js +19 -1
- package/src/builders/application/schema.json +73 -4
- package/src/builders/application/setup-bundling.d.ts +6 -1
- package/src/builders/application/setup-bundling.js +47 -13
- package/src/builders/dev-server/options.d.ts +2 -2
- package/src/builders/dev-server/options.js +2 -2
- package/src/builders/dev-server/schema.d.ts +2 -1
- package/src/builders/dev-server/schema.json +1 -2
- package/src/builders/dev-server/vite-server.d.ts +3 -2
- package/src/builders/dev-server/vite-server.js +123 -61
- package/src/index.d.ts +1 -0
- package/src/tools/angular/angular-host.d.ts +1 -1
- package/src/tools/angular/angular-host.js +14 -6
- 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 +39 -0
- package/src/tools/angular/compilation/parallel-compilation.js +2 -2
- package/src/tools/angular/compilation/parallel-worker.d.ts +1 -0
- package/src/tools/angular/compilation/parallel-worker.js +5 -2
- package/src/tools/esbuild/angular/compiler-plugin.d.ts +3 -4
- package/src/tools/esbuild/angular/compiler-plugin.js +58 -33
- package/src/tools/esbuild/angular/component-stylesheets.d.ts +18 -18
- package/src/tools/esbuild/angular/component-stylesheets.js +66 -38
- package/src/tools/esbuild/angular/jit-plugin-callbacks.d.ts +1 -1
- package/src/tools/esbuild/angular/jit-plugin-callbacks.js +11 -3
- package/src/tools/esbuild/angular/source-file-cache.d.ts +1 -1
- package/src/tools/esbuild/angular/source-file-cache.js +6 -2
- package/src/tools/esbuild/application-code-bundle.d.ts +7 -5
- package/src/tools/esbuild/application-code-bundle.js +280 -249
- package/src/tools/esbuild/bundler-context.d.ts +2 -1
- package/src/tools/esbuild/bundler-context.js +10 -12
- package/src/tools/esbuild/bundler-execution-result.d.ts +14 -3
- package/src/tools/esbuild/bundler-execution-result.js +15 -8
- package/src/tools/esbuild/commonjs-checker.js +2 -2
- package/src/tools/esbuild/compiler-plugin-options.d.ts +2 -4
- package/src/tools/esbuild/compiler-plugin-options.js +15 -37
- package/src/tools/esbuild/global-scripts.js +1 -1
- package/src/tools/esbuild/global-styles.js +4 -1
- package/src/tools/esbuild/index-html-generator.js +8 -0
- package/src/tools/esbuild/javascript-transformer.js +3 -0
- package/src/tools/esbuild/server-bundle-metadata-plugin.d.ts +22 -0
- package/src/tools/esbuild/server-bundle-metadata-plugin.js +36 -0
- package/src/tools/esbuild/stylesheets/bundle-options.d.ts +2 -0
- package/src/tools/esbuild/stylesheets/bundle-options.js +2 -1
- package/src/tools/esbuild/stylesheets/sass-language.js +4 -0
- package/src/tools/esbuild/stylesheets/stylesheet-plugin-factory.d.ts +9 -0
- package/src/tools/esbuild/utils.js +13 -31
- package/src/tools/sass/worker.js +19 -0
- package/src/tools/vite/middlewares/assets-middleware.d.ts +6 -1
- package/src/tools/vite/middlewares/assets-middleware.js +42 -22
- package/src/tools/vite/middlewares/component-middleware.d.ts +9 -0
- package/src/tools/vite/middlewares/component-middleware.js +33 -0
- package/src/tools/vite/middlewares/index.d.ts +2 -1
- package/src/tools/vite/middlewares/index.js +3 -1
- package/src/tools/vite/middlewares/ssr-middleware.js +11 -8
- package/src/tools/vite/plugins/angular-memory-plugin.d.ts +1 -0
- package/src/tools/vite/plugins/angular-memory-plugin.js +5 -13
- package/src/tools/vite/plugins/setup-middlewares-plugin.d.ts +3 -1
- package/src/tools/vite/plugins/setup-middlewares-plugin.js +12 -3
- package/src/tools/vite/utils.d.ts +1 -0
- package/src/typings.d.ts +1 -1
- package/src/utils/environment-options.d.ts +1 -0
- package/src/utils/environment-options.js +4 -2
- package/src/utils/index-file/auto-csp.d.ts +23 -0
- package/src/utils/index-file/auto-csp.js +283 -0
- package/src/utils/index-file/html-rewriting-stream.d.ts +5 -1
- package/src/utils/index-file/index-html-generator.d.ts +4 -0
- package/src/utils/index-file/index-html-generator.js +11 -0
- package/src/utils/index-file/inline-critical-css.js +17 -18
- package/src/utils/normalize-cache.js +1 -1
- package/src/utils/server-rendering/esm-in-memory-loader/utils.d.ts +8 -0
- package/src/utils/server-rendering/esm-in-memory-loader/utils.js +13 -0
- package/src/utils/server-rendering/launch-server.js +5 -5
- package/src/utils/server-rendering/load-esm-from-memory.d.ts +1 -1
- package/src/utils/server-rendering/manifest.d.ts +9 -8
- package/src/utils/server-rendering/manifest.js +17 -23
- package/src/utils/server-rendering/prerender.js +30 -19
- package/src/utils/server-rendering/render-worker.js +4 -2
- package/src/utils/supported-browsers.js +1 -0
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@angular/build",
|
|
3
|
-
"version": "19.0.0-
|
|
3
|
+
"version": "19.0.0-rc.1",
|
|
4
4
|
"description": "Official build system for Angular",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"Angular CLI",
|
|
@@ -23,39 +23,41 @@
|
|
|
23
23
|
"builders": "builders.json",
|
|
24
24
|
"dependencies": {
|
|
25
25
|
"@ampproject/remapping": "2.3.0",
|
|
26
|
-
"@angular-devkit/architect": "0.1900.0-
|
|
27
|
-
"@babel/core": "7.
|
|
28
|
-
"@babel/helper-annotate-as-pure": "7.
|
|
26
|
+
"@angular-devkit/architect": "0.1900.0-rc.1",
|
|
27
|
+
"@babel/core": "7.26.0",
|
|
28
|
+
"@babel/helper-annotate-as-pure": "7.25.9",
|
|
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.26.0",
|
|
31
|
+
"@inquirer/confirm": "5.0.1",
|
|
32
32
|
"@vitejs/plugin-basic-ssl": "1.1.0",
|
|
33
|
+
"beasties": "0.1.0",
|
|
33
34
|
"browserslist": "^4.23.0",
|
|
34
|
-
"critters": "0.0.24",
|
|
35
35
|
"esbuild": "0.24.0",
|
|
36
36
|
"fast-glob": "3.3.2",
|
|
37
37
|
"https-proxy-agent": "7.0.5",
|
|
38
38
|
"istanbul-lib-instrument": "6.0.3",
|
|
39
|
-
"listr2": "8.2.
|
|
40
|
-
"
|
|
41
|
-
"magic-string": "0.30.11",
|
|
39
|
+
"listr2": "8.2.5",
|
|
40
|
+
"magic-string": "0.30.12",
|
|
42
41
|
"mrmime": "2.0.0",
|
|
43
42
|
"parse5-html-rewriting-stream": "7.0.0",
|
|
44
43
|
"picomatch": "4.0.2",
|
|
45
44
|
"piscina": "4.7.0",
|
|
46
|
-
"rollup": "4.
|
|
47
|
-
"sass": "1.
|
|
45
|
+
"rollup": "4.24.4",
|
|
46
|
+
"sass": "1.80.6",
|
|
48
47
|
"semver": "7.6.3",
|
|
49
|
-
"vite": "5.4.
|
|
48
|
+
"vite": "5.4.10",
|
|
50
49
|
"watchpack": "2.4.2"
|
|
51
50
|
},
|
|
51
|
+
"optionalDependencies": {
|
|
52
|
+
"lmdb": "3.1.4"
|
|
53
|
+
},
|
|
52
54
|
"peerDependencies": {
|
|
53
|
-
"@angular/compiler": "^19.0.0-next.
|
|
54
|
-
"@angular/compiler-cli": "^19.0.0-next.
|
|
55
|
-
"@angular/localize": "^19.0.0-next.
|
|
56
|
-
"@angular/platform-server": "^19.0.0-next.
|
|
57
|
-
"@angular/service-worker": "^19.0.0-next.
|
|
58
|
-
"@angular/ssr": "^19.0.0-
|
|
55
|
+
"@angular/compiler": "^19.0.0-next.9",
|
|
56
|
+
"@angular/compiler-cli": "^19.0.0-next.9",
|
|
57
|
+
"@angular/localize": "^19.0.0-next.9",
|
|
58
|
+
"@angular/platform-server": "^19.0.0-next.9",
|
|
59
|
+
"@angular/service-worker": "^19.0.0-next.9",
|
|
60
|
+
"@angular/ssr": "^19.0.0-rc.1",
|
|
59
61
|
"less": "^4.2.0",
|
|
60
62
|
"postcss": "^8.4.0",
|
|
61
63
|
"tailwindcss": "^2.0.0 || ^3.0.0",
|
|
@@ -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
|
}
|
|
@@ -162,7 +162,7 @@ async function* runEsBuildBuildAction(action, options) {
|
|
|
162
162
|
(0, sass_language_1.shutdownSassWorkerPool)();
|
|
163
163
|
}
|
|
164
164
|
}
|
|
165
|
-
async function emitOutputResult({ outputFiles, assetFiles, errors, warnings, externalMetadata, htmlIndexPath, htmlBaseHref, }, outputOptions) {
|
|
165
|
+
async function emitOutputResult({ outputFiles, assetFiles, errors, warnings, externalMetadata, htmlIndexPath, htmlBaseHref, templateUpdates, }, outputOptions) {
|
|
166
166
|
if (errors.length > 0) {
|
|
167
167
|
return {
|
|
168
168
|
kind: results_1.ResultKind.Failure,
|
|
@@ -173,6 +173,18 @@ async function emitOutputResult({ outputFiles, assetFiles, errors, warnings, ext
|
|
|
173
173
|
},
|
|
174
174
|
};
|
|
175
175
|
}
|
|
176
|
+
// Template updates only exist if no other changes have occurred
|
|
177
|
+
if (templateUpdates?.size) {
|
|
178
|
+
const updateResult = {
|
|
179
|
+
kind: results_1.ResultKind.ComponentUpdate,
|
|
180
|
+
updates: Array.from(templateUpdates).map(([id, content]) => ({
|
|
181
|
+
type: 'template',
|
|
182
|
+
id,
|
|
183
|
+
content,
|
|
184
|
+
})),
|
|
185
|
+
};
|
|
186
|
+
return updateResult;
|
|
187
|
+
}
|
|
176
188
|
const result = {
|
|
177
189
|
kind: results_1.ResultKind.Full,
|
|
178
190
|
warnings: warnings,
|
|
@@ -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,12 +6,8 @@
|
|
|
6
6
|
* Use of this source code is governed by an MIT-style license that can be
|
|
7
7
|
* found in the LICENSE file at https://angular.dev/license
|
|
8
8
|
*/
|
|
9
|
-
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
10
|
-
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
11
|
-
};
|
|
12
9
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
13
10
|
exports.executeBuild = executeBuild;
|
|
14
|
-
const node_assert_1 = __importDefault(require("node:assert"));
|
|
15
11
|
const source_file_cache_1 = require("../../tools/esbuild/angular/source-file-cache");
|
|
16
12
|
const budget_stats_1 = require("../../tools/esbuild/budget-stats");
|
|
17
13
|
const bundler_context_1 = require("../../tools/esbuild/bundler-context");
|
|
@@ -28,11 +24,10 @@ const supported_browsers_1 = require("../../utils/supported-browsers");
|
|
|
28
24
|
const chunk_optimizer_1 = require("./chunk-optimizer");
|
|
29
25
|
const execute_post_bundle_1 = require("./execute-post-bundle");
|
|
30
26
|
const i18n_1 = require("./i18n");
|
|
31
|
-
const schema_1 = require("./schema");
|
|
32
27
|
const setup_bundling_1 = require("./setup-bundling");
|
|
33
28
|
// eslint-disable-next-line max-lines-per-function
|
|
34
29
|
async function executeBuild(options, context, rebuildState) {
|
|
35
|
-
const { projectRoot, workspaceRoot, i18nOptions, optimizationOptions, assets,
|
|
30
|
+
const { projectRoot, workspaceRoot, i18nOptions, optimizationOptions, assets, cacheOptions, serverEntryPoint, baseHref, ssrOptions, verbose, colors, jsonLogs, } = options;
|
|
36
31
|
// TODO: Consider integrating into watch mode. Would require full rebuild on target changes.
|
|
37
32
|
const browsers = (0, supported_browsers_1.getSupportedBrowsers)(projectRoot, context.logger);
|
|
38
33
|
// Load active translations if inlining
|
|
@@ -41,18 +36,63 @@ async function executeBuild(options, context, rebuildState) {
|
|
|
41
36
|
await (0, i18n_1.loadActiveTranslations)(context, i18nOptions);
|
|
42
37
|
}
|
|
43
38
|
// Reuse rebuild state or create new bundle contexts for code and global stylesheets
|
|
44
|
-
let bundlerContexts
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
39
|
+
let bundlerContexts;
|
|
40
|
+
let componentStyleBundler;
|
|
41
|
+
let codeBundleCache;
|
|
42
|
+
let bundlingResult;
|
|
43
|
+
let templateUpdates;
|
|
44
|
+
if (rebuildState) {
|
|
45
|
+
bundlerContexts = rebuildState.rebuildContexts;
|
|
46
|
+
componentStyleBundler = rebuildState.componentStyleBundler;
|
|
47
|
+
codeBundleCache = rebuildState.codeBundleCache;
|
|
48
|
+
templateUpdates = rebuildState.templateUpdates;
|
|
49
|
+
// Reset template updates for new rebuild
|
|
50
|
+
templateUpdates?.clear();
|
|
51
|
+
const allFileChanges = rebuildState.fileChanges.all;
|
|
52
|
+
// Bundle all contexts that do not require TypeScript changed file checks.
|
|
53
|
+
// These will automatically use cached results based on the changed files.
|
|
54
|
+
bundlingResult = await bundler_context_1.BundlerContext.bundleAll(bundlerContexts.otherContexts, allFileChanges);
|
|
55
|
+
// Check the TypeScript code bundling cache for changes. If invalid, force a rebundle of
|
|
56
|
+
// all TypeScript related contexts.
|
|
57
|
+
const forceTypeScriptRebuild = codeBundleCache?.invalidate(allFileChanges);
|
|
58
|
+
const typescriptResults = [];
|
|
59
|
+
for (const typescriptContext of bundlerContexts.typescriptContexts) {
|
|
60
|
+
typescriptContext.invalidate(allFileChanges);
|
|
61
|
+
const result = await typescriptContext.bundle(forceTypeScriptRebuild);
|
|
62
|
+
typescriptResults.push(result);
|
|
63
|
+
}
|
|
64
|
+
bundlingResult = bundler_context_1.BundlerContext.mergeResults([bundlingResult, ...typescriptResults]);
|
|
65
|
+
}
|
|
66
|
+
else {
|
|
67
|
+
const target = (0, utils_1.transformSupportedBrowsersToTargets)(browsers);
|
|
68
|
+
codeBundleCache = new source_file_cache_1.SourceFileCache(cacheOptions.enabled ? cacheOptions.path : undefined);
|
|
69
|
+
componentStyleBundler = (0, setup_bundling_1.createComponentStyleBundler)(options, target);
|
|
70
|
+
if (options.templateUpdates) {
|
|
71
|
+
templateUpdates = new Map();
|
|
72
|
+
}
|
|
73
|
+
bundlerContexts = (0, setup_bundling_1.setupBundlerContexts)(options, target, codeBundleCache, componentStyleBundler, templateUpdates);
|
|
74
|
+
// Bundle everything on initial build
|
|
75
|
+
bundlingResult = await bundler_context_1.BundlerContext.bundleAll([
|
|
76
|
+
...bundlerContexts.typescriptContexts,
|
|
77
|
+
...bundlerContexts.otherContexts,
|
|
78
|
+
]);
|
|
79
|
+
}
|
|
80
|
+
// Update any external component styles if enabled and rebuilding.
|
|
81
|
+
// TODO: Only attempt rebundling of invalidated styles once incremental build results are supported.
|
|
82
|
+
if (rebuildState && options.externalRuntimeStyles) {
|
|
83
|
+
componentStyleBundler.invalidate(rebuildState.fileChanges.all);
|
|
84
|
+
const componentResults = await componentStyleBundler.bundleAllFiles(true, true);
|
|
85
|
+
bundlingResult = bundler_context_1.BundlerContext.mergeResults([bundlingResult, ...componentResults]);
|
|
49
86
|
}
|
|
50
|
-
let bundlingResult = await bundler_context_1.BundlerContext.bundleAll(bundlerContexts, rebuildState?.fileChanges.all);
|
|
51
87
|
if (options.optimizationOptions.scripts && environment_options_1.shouldOptimizeChunks) {
|
|
52
88
|
bundlingResult = await (0, profiling_1.profileAsync)('OPTIMIZE_CHUNKS', () => (0, chunk_optimizer_1.optimizeChunks)(bundlingResult, options.sourcemapOptions.scripts ? !options.sourcemapOptions.hidden || 'hidden' : false));
|
|
53
89
|
}
|
|
54
|
-
const executionResult = new bundler_execution_result_1.ExecutionResult(bundlerContexts, codeBundleCache);
|
|
90
|
+
const executionResult = new bundler_execution_result_1.ExecutionResult(bundlerContexts, componentStyleBundler, codeBundleCache, templateUpdates);
|
|
55
91
|
executionResult.addWarnings(bundlingResult.warnings);
|
|
92
|
+
// Add used external component style referenced files to be watched
|
|
93
|
+
if (options.externalRuntimeStyles) {
|
|
94
|
+
executionResult.extraWatchFiles.push(...componentStyleBundler.collectReferencedFiles());
|
|
95
|
+
}
|
|
56
96
|
// Return if the bundling has errors
|
|
57
97
|
if (bundlingResult.errors) {
|
|
58
98
|
executionResult.addErrors(bundlingResult.errors);
|
|
@@ -113,7 +153,11 @@ async function executeBuild(options, context, rebuildState) {
|
|
|
113
153
|
}
|
|
114
154
|
// Create server app engine manifest
|
|
115
155
|
if (serverEntryPoint) {
|
|
116
|
-
executionResult.addOutputFile(manifest_1.SERVER_APP_ENGINE_MANIFEST_FILENAME, (0, manifest_1.generateAngularServerAppEngineManifest)(i18nOptions, baseHref
|
|
156
|
+
executionResult.addOutputFile(manifest_1.SERVER_APP_ENGINE_MANIFEST_FILENAME, (0, manifest_1.generateAngularServerAppEngineManifest)(i18nOptions, baseHref), bundler_context_1.BuildOutputFileType.ServerRoot);
|
|
157
|
+
}
|
|
158
|
+
// Override auto-CSP settings if we are serving through Vite middleware.
|
|
159
|
+
if (context.builder.builderName === 'dev-server' && options.security) {
|
|
160
|
+
options.security.autoCsp = false;
|
|
117
161
|
}
|
|
118
162
|
// Perform i18n translation inlining if enabled
|
|
119
163
|
if (i18nOptions.shouldInline) {
|
|
@@ -132,16 +176,7 @@ async function executeBuild(options, context, rebuildState) {
|
|
|
132
176
|
executionResult.outputFiles.push(...result.additionalOutputFiles);
|
|
133
177
|
executionResult.assetFiles.push(...result.additionalAssets);
|
|
134
178
|
}
|
|
135
|
-
|
|
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
|
-
}
|
|
143
|
-
executionResult.addOutputFile('prerendered-routes.json', JSON.stringify({ routes: prerenderedRoutes }, null, 2), bundler_context_1.BuildOutputFileType.Root);
|
|
144
|
-
}
|
|
179
|
+
executionResult.addOutputFile('prerendered-routes.json', JSON.stringify({ routes: executionResult.prerenderedRoutes }, null, 2), bundler_context_1.BuildOutputFileType.Root);
|
|
145
180
|
// Write metafile if stats option is enabled
|
|
146
181
|
if (options.stats) {
|
|
147
182
|
executionResult.addOutputFile('stats.json', JSON.stringify(metafile, null, 2), bundler_context_1.BuildOutputFileType.Root);
|
|
@@ -30,6 +30,7 @@ const schema_1 = require("./schema");
|
|
|
30
30
|
* @param initialFiles A map containing initial file information for the executed build.
|
|
31
31
|
* @param locale A language locale to insert in the index.html.
|
|
32
32
|
*/
|
|
33
|
+
// eslint-disable-next-line max-lines-per-function
|
|
33
34
|
async function executePostBundleSteps(options, outputFiles, assetFiles, initialFiles, locale) {
|
|
34
35
|
const additionalAssets = [];
|
|
35
36
|
const additionalOutputFiles = [];
|
|
@@ -55,7 +56,8 @@ async function executePostBundleSteps(options, outputFiles, assetFiles, initialF
|
|
|
55
56
|
}
|
|
56
57
|
// Create server manifest
|
|
57
58
|
if (serverEntryPoint) {
|
|
58
|
-
|
|
59
|
+
const { manifestContent, serverAssetsChunks } = (0, manifest_1.generateAngularServerAppManifest)(additionalHtmlOutputFiles, outputFiles, optimizationOptions.styles.inlineCritical ?? false, undefined, locale);
|
|
60
|
+
additionalOutputFiles.push(...serverAssetsChunks, (0, utils_1.createOutputFile)(manifest_1.SERVER_APP_MANIFEST_FILENAME, manifestContent, bundler_context_1.BuildOutputFileType.ServerApplication));
|
|
59
61
|
}
|
|
60
62
|
// Pre-render (SSG) and App-shell
|
|
61
63
|
// If localization is enabled, prerendering is handled in the inlining process.
|
|
@@ -71,7 +73,15 @@ async function executePostBundleSteps(options, outputFiles, assetFiles, initialF
|
|
|
71
73
|
// Update the index contents with the app shell under these conditions:
|
|
72
74
|
// - Replace 'index.html' with the app shell only if it hasn't been prerendered yet.
|
|
73
75
|
// - Always replace 'index.csr.html' with the app shell.
|
|
74
|
-
|
|
76
|
+
let filePath = path;
|
|
77
|
+
if (appShellRoute && !indexHasBeenPrerendered) {
|
|
78
|
+
if (outputMode !== schema_1.OutputMode.Server && indexHtmlOptions.output === options_1.INDEX_HTML_CSR) {
|
|
79
|
+
filePath = 'index.html';
|
|
80
|
+
}
|
|
81
|
+
else {
|
|
82
|
+
filePath = indexHtmlOptions.output;
|
|
83
|
+
}
|
|
84
|
+
}
|
|
75
85
|
additionalHtmlOutputFiles.set(filePath, (0, utils_1.createOutputFile)(filePath, content, bundler_context_1.BuildOutputFileType.Browser));
|
|
76
86
|
}
|
|
77
87
|
const serializableRouteTreeNodeForManifest = [];
|
|
@@ -79,8 +89,11 @@ async function executePostBundleSteps(options, outputFiles, assetFiles, initialF
|
|
|
79
89
|
switch (metadata.renderMode) {
|
|
80
90
|
case models_1.RouteRenderMode.Prerender:
|
|
81
91
|
case /* Legacy building mode */ undefined: {
|
|
82
|
-
if (!metadata.redirectTo
|
|
83
|
-
|
|
92
|
+
if (!metadata.redirectTo) {
|
|
93
|
+
serializableRouteTreeNodeForManifest.push(metadata);
|
|
94
|
+
if (!metadata.route.includes('*')) {
|
|
95
|
+
prerenderedRoutes[metadata.route] = { headers: metadata.headers };
|
|
96
|
+
}
|
|
84
97
|
}
|
|
85
98
|
break;
|
|
86
99
|
}
|
|
@@ -94,7 +107,17 @@ async function executePostBundleSteps(options, outputFiles, assetFiles, initialF
|
|
|
94
107
|
// Regenerate the manifest to append route tree. This is only needed if SSR is enabled.
|
|
95
108
|
const manifest = additionalOutputFiles.find((f) => f.path === manifest_1.SERVER_APP_MANIFEST_FILENAME);
|
|
96
109
|
(0, node_assert_1.default)(manifest, `${manifest_1.SERVER_APP_MANIFEST_FILENAME} was not found in output files.`);
|
|
97
|
-
|
|
110
|
+
const { manifestContent, serverAssetsChunks } = (0, manifest_1.generateAngularServerAppManifest)(additionalHtmlOutputFiles, outputFiles, optimizationOptions.styles.inlineCritical ?? false, serializableRouteTreeNodeForManifest, locale);
|
|
111
|
+
for (const chunk of serverAssetsChunks) {
|
|
112
|
+
const idx = additionalOutputFiles.findIndex(({ path }) => path === chunk.path);
|
|
113
|
+
if (idx === -1) {
|
|
114
|
+
additionalOutputFiles.push(chunk);
|
|
115
|
+
}
|
|
116
|
+
else {
|
|
117
|
+
additionalOutputFiles[idx] = chunk;
|
|
118
|
+
}
|
|
119
|
+
}
|
|
120
|
+
manifest.contents = new TextEncoder().encode(manifestContent);
|
|
98
121
|
}
|
|
99
122
|
}
|
|
100
123
|
additionalOutputFiles.push(...additionalHtmlOutputFiles.values());
|
|
@@ -6,7 +6,6 @@
|
|
|
6
6
|
* found in the LICENSE file at https://angular.dev/license
|
|
7
7
|
*/
|
|
8
8
|
import { BuilderContext, BuilderOutput } from '@angular-devkit/architect';
|
|
9
|
-
import type { Plugin } from 'esbuild';
|
|
10
9
|
import { BuildOutputFile } from '../../tools/esbuild/bundler-context';
|
|
11
10
|
import { ApplicationBuilderExtensions, ApplicationBuilderInternalOptions } from './options';
|
|
12
11
|
import { Result } from './results';
|
|
@@ -22,21 +21,6 @@ export interface ApplicationBuilderOutput extends BuilderOutput {
|
|
|
22
21
|
destination: string;
|
|
23
22
|
}[];
|
|
24
23
|
}
|
|
25
|
-
/**
|
|
26
|
-
* Builds an application using the `application` builder with the provided
|
|
27
|
-
* options.
|
|
28
|
-
*
|
|
29
|
-
* Usage of the `plugins` parameter is NOT supported and may cause unexpected
|
|
30
|
-
* build output or build failures.
|
|
31
|
-
*
|
|
32
|
-
* @experimental Direct usage of this function is considered experimental.
|
|
33
|
-
*
|
|
34
|
-
* @param options The options defined by the builder's schema to use.
|
|
35
|
-
* @param context An Architect builder context instance.
|
|
36
|
-
* @param plugins An array of plugins to apply to the main code bundling.
|
|
37
|
-
* @returns The build output results of the build.
|
|
38
|
-
*/
|
|
39
|
-
export declare function buildApplication(options: ApplicationBuilderOptions, context: BuilderContext, plugins?: Plugin[]): AsyncIterable<ApplicationBuilderOutput>;
|
|
40
24
|
/**
|
|
41
25
|
* Builds an application using the `application` builder with the provided
|
|
42
26
|
* options.
|
|
@@ -100,16 +100,21 @@ context, extensions) {
|
|
|
100
100
|
signal,
|
|
101
101
|
});
|
|
102
102
|
}
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
103
|
+
/**
|
|
104
|
+
* Builds an application using the `application` builder with the provided
|
|
105
|
+
* options.
|
|
106
|
+
*
|
|
107
|
+
* Usage of the `extensions` parameter is NOT supported and may cause unexpected
|
|
108
|
+
* build output or build failures.
|
|
109
|
+
*
|
|
110
|
+
* @experimental Direct usage of this function is considered experimental.
|
|
111
|
+
*
|
|
112
|
+
* @param options The options defined by the builder's schema to use.
|
|
113
|
+
* @param context An Architect builder context instance.
|
|
114
|
+
* @param extensions An object contain extension points for the build.
|
|
115
|
+
* @returns The build output results of the build.
|
|
116
|
+
*/
|
|
117
|
+
async function* buildApplication(options, context, extensions) {
|
|
113
118
|
let initial = true;
|
|
114
119
|
for await (const result of buildApplicationInternal(options, context, extensions)) {
|
|
115
120
|
const outputOptions = result.detail?.['outputOptions'];
|
|
@@ -9,7 +9,7 @@ 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, OutputMode, OutputPathClass } from './schema';
|
|
12
|
+
import { Schema as ApplicationBuilderOptions, ExperimentalPlatform, I18NTranslation, OutputMode, OutputPathClass } from './schema';
|
|
13
13
|
/**
|
|
14
14
|
* The filename for the client-side rendered HTML template.
|
|
15
15
|
* This template is used for client-side rendering (CSR) in a web application.
|
|
@@ -36,8 +36,10 @@ interface InternalOptions {
|
|
|
36
36
|
* If given a relative path, it is resolved relative to the current workspace and will generate an output at the same relative location
|
|
37
37
|
* in the output directory. If given an absolute path, the output will be generated in the root of the output directory with the same base
|
|
38
38
|
* name.
|
|
39
|
+
*
|
|
40
|
+
* If provided a Map, the key is the name of the output bundle and the value is the entry point file.
|
|
39
41
|
*/
|
|
40
|
-
entryPoints?: Set<string>;
|
|
42
|
+
entryPoints?: Set<string> | Map<string, string>;
|
|
41
43
|
/** File extension to use for the generated output files. */
|
|
42
44
|
outExtension?: 'js' | 'mjs';
|
|
43
45
|
/**
|
|
@@ -66,6 +68,12 @@ interface InternalOptions {
|
|
|
66
68
|
* styles.
|
|
67
69
|
*/
|
|
68
70
|
externalRuntimeStyles?: boolean;
|
|
71
|
+
/**
|
|
72
|
+
* Enables the AOT compiler to generate template component update functions.
|
|
73
|
+
* This option is only intended to be used with a development server that can process and serve component
|
|
74
|
+
* template updates.
|
|
75
|
+
*/
|
|
76
|
+
templateUpdates?: boolean;
|
|
69
77
|
/**
|
|
70
78
|
* Enables instrumentation to collect code coverage data for specific files.
|
|
71
79
|
*
|
|
@@ -119,8 +127,10 @@ export declare function normalizeOptions(context: BuilderContext, projectName: s
|
|
|
119
127
|
outputMode: OutputMode | undefined;
|
|
120
128
|
ssrOptions: {
|
|
121
129
|
entry?: undefined;
|
|
130
|
+
platform?: undefined;
|
|
122
131
|
} | {
|
|
123
132
|
entry: string | undefined;
|
|
133
|
+
platform: ExperimentalPlatform;
|
|
124
134
|
} | undefined;
|
|
125
135
|
verbose: boolean | undefined;
|
|
126
136
|
watch: boolean | undefined;
|
|
@@ -181,6 +191,8 @@ export declare function normalizeOptions(context: BuilderContext, projectName: s
|
|
|
181
191
|
partialSSRBuild: boolean;
|
|
182
192
|
externalRuntimeStyles: boolean | undefined;
|
|
183
193
|
instrumentForCoverage: ((filename: string) => boolean) | undefined;
|
|
194
|
+
security: import("./schema").Security | undefined;
|
|
195
|
+
templateUpdates: boolean;
|
|
184
196
|
}>;
|
|
185
197
|
export declare function getLocaleBaseHref(baseHref: string | undefined, i18n: NormalizedApplicationBuildOptions['i18nOptions'], locale: string): string | undefined;
|
|
186
198
|
export {};
|
|
@@ -116,14 +116,12 @@ async function normalizeOptions(context, projectName, options, extensions) {
|
|
|
116
116
|
if (!options.server) {
|
|
117
117
|
options.ssr = false;
|
|
118
118
|
}
|
|
119
|
-
if (options.prerender) {
|
|
120
|
-
context.logger.warn('The "prerender" option is
|
|
119
|
+
if (options.prerender !== undefined) {
|
|
120
|
+
context.logger.warn('The "prerender" option is not considered when "outputMode" is specified.');
|
|
121
121
|
}
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
if (options.appShell) {
|
|
126
|
-
context.logger.warn('The "appShell" option is no longer needed when "outputMode" is specified.');
|
|
122
|
+
options.prerender = !!options.server;
|
|
123
|
+
if (options.appShell !== undefined) {
|
|
124
|
+
context.logger.warn('The "appShell" option is not considered when "outputMode" is specified.');
|
|
127
125
|
}
|
|
128
126
|
}
|
|
129
127
|
// A configuration file can exist in the project or workspace root
|
|
@@ -153,9 +151,10 @@ async function normalizeOptions(context, projectName, options, extensions) {
|
|
|
153
151
|
ssrOptions = {};
|
|
154
152
|
}
|
|
155
153
|
else if (typeof options.ssr === 'object') {
|
|
156
|
-
const { entry } = options.ssr;
|
|
154
|
+
const { entry, experimentalPlatform = schema_1.ExperimentalPlatform.Node } = options.ssr;
|
|
157
155
|
ssrOptions = {
|
|
158
156
|
entry: entry && node_path_1.default.join(workspaceRoot, entry),
|
|
157
|
+
platform: experimentalPlatform,
|
|
159
158
|
};
|
|
160
159
|
}
|
|
161
160
|
let appShellOptions;
|
|
@@ -199,10 +198,16 @@ async function normalizeOptions(context, projectName, options, extensions) {
|
|
|
199
198
|
* If SSR is activated, create a distinct entry file for the `index.html`.
|
|
200
199
|
* This is necessary because numerous server/cloud providers automatically serve the `index.html` as a static file
|
|
201
200
|
* if it exists (handling SSG).
|
|
201
|
+
*
|
|
202
202
|
* For instance, accessing `foo.com/` would lead to `foo.com/index.html` being served instead of hitting the server.
|
|
203
|
+
*
|
|
204
|
+
* This approach can also be applied to service workers, where the `index.csr.html` is served instead of the prerendered `index.html`.
|
|
203
205
|
*/
|
|
204
206
|
const indexBaseName = node_path_1.default.basename(options.index);
|
|
205
|
-
indexOutput =
|
|
207
|
+
indexOutput =
|
|
208
|
+
(ssrOptions || prerenderOptions) && indexBaseName === 'index.html'
|
|
209
|
+
? exports.INDEX_HTML_CSR
|
|
210
|
+
: indexBaseName;
|
|
206
211
|
}
|
|
207
212
|
else {
|
|
208
213
|
indexOutput = options.index.output || 'index.html';
|
|
@@ -231,7 +236,7 @@ async function normalizeOptions(context, projectName, options, extensions) {
|
|
|
231
236
|
}
|
|
232
237
|
}
|
|
233
238
|
// 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, instrumentForCoverage, } = options;
|
|
239
|
+
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, security, } = options;
|
|
235
240
|
// Return all the normalized options
|
|
236
241
|
return {
|
|
237
242
|
advancedOptimizations: !!aot && optimizationOptions.scripts,
|
|
@@ -290,6 +295,8 @@ async function normalizeOptions(context, projectName, options, extensions) {
|
|
|
290
295
|
partialSSRBuild: environment_options_1.usePartialSsrBuild || partialSSRBuild,
|
|
291
296
|
externalRuntimeStyles,
|
|
292
297
|
instrumentForCoverage,
|
|
298
|
+
security,
|
|
299
|
+
templateUpdates: !!options.templateUpdates,
|
|
293
300
|
};
|
|
294
301
|
}
|
|
295
302
|
async function getTailwindConfig(searchDirectories, workspaceRoot, context) {
|
|
@@ -342,6 +349,14 @@ function normalizeEntryPoints(workspaceRoot, browser, entryPoints = new Set()) {
|
|
|
342
349
|
// Use `browser` alone.
|
|
343
350
|
return { 'main': node_path_1.default.join(workspaceRoot, browser) };
|
|
344
351
|
}
|
|
352
|
+
else if (entryPoints instanceof Map) {
|
|
353
|
+
return Object.fromEntries(Array.from(entryPoints.entries(), ([name, entryPoint]) => {
|
|
354
|
+
// Get the full file path to a relative entry point input. Leave bare specifiers alone so they are resolved as modules.
|
|
355
|
+
const isRelativePath = entryPoint.startsWith('.');
|
|
356
|
+
const entryPointPath = isRelativePath ? node_path_1.default.join(workspaceRoot, entryPoint) : entryPoint;
|
|
357
|
+
return [name, entryPointPath];
|
|
358
|
+
}));
|
|
359
|
+
}
|
|
345
360
|
else {
|
|
346
361
|
// Use `entryPoints` alone.
|
|
347
362
|
const entryPointPaths = {};
|
|
@@ -61,7 +61,9 @@ export interface ResultMessage {
|
|
|
61
61
|
}
|
|
62
62
|
export interface ComponentUpdateResult extends BaseResult {
|
|
63
63
|
kind: ResultKind.ComponentUpdate;
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
64
|
+
updates: {
|
|
65
|
+
id: string;
|
|
66
|
+
type: 'style' | 'template';
|
|
67
|
+
content: string;
|
|
68
|
+
}[];
|
|
67
69
|
}
|