@angular/build 19.0.0-next.2 → 19.0.0-next.4
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 +10 -10
- package/src/builders/application/execute-post-bundle.js +29 -18
- package/src/builders/application/i18n.js +2 -11
- package/src/builders/application/options.d.ts +11 -0
- package/src/builders/application/options.js +23 -1
- package/src/builders/application/setup-bundling.js +7 -7
- 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 +7 -2
- package/src/builders/dev-server/vite-server.js +27 -12
- package/src/tools/angular/compilation/parallel-compilation.d.ts +1 -1
- package/src/tools/angular/compilation/parallel-compilation.js +5 -0
- package/src/tools/esbuild/angular/file-reference-tracker.d.ts +1 -1
- package/src/tools/esbuild/application-code-bundle.d.ts +1 -6
- package/src/tools/esbuild/application-code-bundle.js +105 -70
- package/src/tools/esbuild/bundler-context.js +14 -10
- package/src/tools/esbuild/cache.d.ts +1 -1
- package/src/tools/esbuild/javascript-transformer.js +6 -0
- package/src/tools/esbuild/utils.d.ts +9 -0
- package/src/tools/esbuild/utils.js +14 -0
- package/src/tools/sass/sass-service.js +15 -4
- package/src/tools/sass/worker.d.ts +13 -32
- package/src/tools/sass/worker.js +1 -0
- package/src/tools/vite/angular-memory-plugin.js +2 -2
- package/src/tools/vite/middlewares/ssr-middleware.d.ts +1 -4
- package/src/tools/vite/middlewares/ssr-middleware.js +25 -38
- package/src/typings.d.ts +7 -0
- package/src/utils/normalize-cache.js +1 -1
- package/src/utils/server-rendering/fetch-patch.js +4 -5
- package/src/utils/server-rendering/load-esm-from-memory.d.ts +12 -2
- package/src/utils/server-rendering/manifest.d.ts +44 -0
- package/src/utils/server-rendering/manifest.js +86 -0
- package/src/utils/server-rendering/prerender.d.ts +22 -2
- package/src/utils/server-rendering/prerender.js +51 -40
- package/src/utils/server-rendering/render-worker.d.ts +7 -8
- package/src/utils/server-rendering/render-worker.js +10 -13
- package/src/utils/server-rendering/routes-extractor-worker.d.ts +2 -6
- package/src/utils/server-rendering/routes-extractor-worker.js +3 -34
- package/src/utils/server-rendering/main-bundle-exports.d.ts +0 -27
- package/src/utils/server-rendering/main-bundle-exports.js +0 -9
- package/src/utils/server-rendering/render-page.d.ts +0 -26
- package/src/utils/server-rendering/render-page.js +0 -114
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.4",
|
|
4
4
|
"description": "Official build system for Angular",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"Angular CLI",
|
|
@@ -23,12 +23,12 @@
|
|
|
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.4",
|
|
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",
|
|
30
|
-
"@babel/plugin-syntax-import-attributes": "7.
|
|
31
|
-
"@inquirer/confirm": "3.
|
|
30
|
+
"@babel/plugin-syntax-import-attributes": "7.25.6",
|
|
31
|
+
"@inquirer/confirm": "3.2.0",
|
|
32
32
|
"@vitejs/plugin-basic-ssl": "1.1.0",
|
|
33
33
|
"browserslist": "^4.23.0",
|
|
34
34
|
"critters": "0.0.24",
|
|
@@ -36,16 +36,16 @@
|
|
|
36
36
|
"fast-glob": "3.3.2",
|
|
37
37
|
"https-proxy-agent": "7.0.5",
|
|
38
38
|
"listr2": "8.2.4",
|
|
39
|
-
"lmdb": "3.0
|
|
39
|
+
"lmdb": "3.1.0",
|
|
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
44
|
"piscina": "4.6.1",
|
|
45
|
-
"rollup": "4.21.
|
|
46
|
-
"sass": "1.
|
|
45
|
+
"rollup": "4.21.2",
|
|
46
|
+
"sass": "1.78.0",
|
|
47
47
|
"semver": "7.6.3",
|
|
48
|
-
"vite": "5.4.
|
|
48
|
+
"vite": "5.4.3",
|
|
49
49
|
"watchpack": "2.4.2"
|
|
50
50
|
},
|
|
51
51
|
"peerDependencies": {
|
|
@@ -53,11 +53,11 @@
|
|
|
53
53
|
"@angular/localize": "^19.0.0-next.0",
|
|
54
54
|
"@angular/platform-server": "^19.0.0-next.0",
|
|
55
55
|
"@angular/service-worker": "^19.0.0-next.0",
|
|
56
|
-
"@angular/ssr": "^19.0.0-next.
|
|
56
|
+
"@angular/ssr": "^19.0.0-next.4",
|
|
57
57
|
"less": "^4.2.0",
|
|
58
58
|
"postcss": "^8.4.0",
|
|
59
59
|
"tailwindcss": "^2.0.0 || ^3.0.0",
|
|
60
|
-
"typescript": ">=5.
|
|
60
|
+
"typescript": ">=5.5 <5.7"
|
|
61
61
|
},
|
|
62
62
|
"peerDependenciesMeta": {
|
|
63
63
|
"@angular/localize": {
|
|
@@ -16,8 +16,10 @@ 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");
|
|
19
20
|
const prerender_1 = require("../../utils/server-rendering/prerender");
|
|
20
21
|
const service_worker_1 = require("../../utils/service-worker");
|
|
22
|
+
const options_1 = require("./options");
|
|
21
23
|
/**
|
|
22
24
|
* Run additional builds steps including SSG, AppShell, Index HTML file and Service worker generation.
|
|
23
25
|
* @param options The normalized application builder options used to create the build.
|
|
@@ -32,15 +34,11 @@ async function executePostBundleSteps(options, outputFiles, assetFiles, initialF
|
|
|
32
34
|
const allErrors = [];
|
|
33
35
|
const allWarnings = [];
|
|
34
36
|
const prerenderedRoutes = [];
|
|
35
|
-
const { serviceWorker, indexHtmlOptions, optimizationOptions, sourcemapOptions, prerenderOptions, appShellOptions, workspaceRoot, verbose, } = options;
|
|
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.
|
|
37
|
+
const { baseHref = '/', serviceWorker, indexHtmlOptions, optimizationOptions, sourcemapOptions, ssrOptions, prerenderOptions, appShellOptions, workspaceRoot, verbose, } = options;
|
|
38
|
+
// Index HTML content without CSS inlining to be used for server rendering (AppShell, SSG and SSR).
|
|
39
|
+
// NOTE: Critical CSS inlining is deliberately omitted here, as it will be handled during server rendering.
|
|
40
|
+
// Additionally, when using prerendering or AppShell, the index HTML file may be regenerated.
|
|
41
|
+
// To prevent generating duplicate files with the same filename, a `Map` is used to store and manage the files.
|
|
44
42
|
const additionalHtmlOutputFiles = new Map();
|
|
45
43
|
// Generate index HTML file
|
|
46
44
|
// If localization is enabled, index generation is handled in the inlining process.
|
|
@@ -50,21 +48,34 @@ async function executePostBundleSteps(options, outputFiles, assetFiles, initialF
|
|
|
50
48
|
allWarnings.push(...warnings);
|
|
51
49
|
additionalHtmlOutputFiles.set(indexHtmlOptions.output, (0, utils_1.createOutputFile)(indexHtmlOptions.output, csrContent, bundler_context_1.BuildOutputFileType.Browser));
|
|
52
50
|
if (ssrContent) {
|
|
53
|
-
|
|
54
|
-
additionalHtmlOutputFiles.set(serverIndexHtmlFilename, (0, utils_1.createOutputFile)(serverIndexHtmlFilename, ssrContent, bundler_context_1.BuildOutputFileType.Server));
|
|
55
|
-
ssrIndexContent = ssrContent;
|
|
51
|
+
additionalHtmlOutputFiles.set(options_1.INDEX_HTML_SERVER, (0, utils_1.createOutputFile)(options_1.INDEX_HTML_SERVER, ssrContent, bundler_context_1.BuildOutputFileType.Server));
|
|
56
52
|
}
|
|
57
53
|
}
|
|
54
|
+
// Create server manifest
|
|
55
|
+
if (prerenderOptions || appShellOptions || ssrOptions) {
|
|
56
|
+
additionalOutputFiles.push((0, utils_1.createOutputFile)(manifest_1.SERVER_APP_MANIFEST_FILENAME, (0, manifest_1.generateAngularServerAppManifest)(additionalHtmlOutputFiles, outputFiles, optimizationOptions.styles.inlineCritical ?? false, undefined), bundler_context_1.BuildOutputFileType.Server));
|
|
57
|
+
}
|
|
58
58
|
// Pre-render (SSG) and App-shell
|
|
59
59
|
// If localization is enabled, prerendering is handled in the inlining process.
|
|
60
|
-
if (prerenderOptions || appShellOptions) {
|
|
61
|
-
(0, node_assert_1.default)(
|
|
62
|
-
const { output, warnings, errors, prerenderedRoutes: generatedRoutes, } = await (0, prerender_1.prerenderPages)(workspaceRoot, appShellOptions, prerenderOptions, outputFiles,
|
|
60
|
+
if ((prerenderOptions || appShellOptions) && !allErrors.length) {
|
|
61
|
+
(0, node_assert_1.default)(indexHtmlOptions, 'The "index" option is required when using the "ssg" or "appShell" options.');
|
|
62
|
+
const { output, warnings, errors, prerenderedRoutes: generatedRoutes, serializableRouteTreeNode, } = await (0, prerender_1.prerenderPages)(workspaceRoot, baseHref, appShellOptions, prerenderOptions, [...outputFiles, ...additionalOutputFiles], assetFiles, sourcemapOptions.scripts, environment_options_1.maxWorkers, verbose);
|
|
63
63
|
allErrors.push(...errors);
|
|
64
64
|
allWarnings.push(...warnings);
|
|
65
65
|
prerenderedRoutes.push(...Array.from(generatedRoutes));
|
|
66
|
-
|
|
67
|
-
|
|
66
|
+
const indexHasBeenPrerendered = generatedRoutes.has(indexHtmlOptions.output);
|
|
67
|
+
for (const [path, { content, appShellRoute }] of Object.entries(output)) {
|
|
68
|
+
// Update the index contents with the app shell under these conditions:
|
|
69
|
+
// - Replace 'index.html' with the app shell only if it hasn't been prerendered yet.
|
|
70
|
+
// - Always replace 'index.csr.html' with the app shell.
|
|
71
|
+
const filePath = appShellRoute && !indexHasBeenPrerendered ? indexHtmlOptions.output : path;
|
|
72
|
+
additionalHtmlOutputFiles.set(filePath, (0, utils_1.createOutputFile)(filePath, content, bundler_context_1.BuildOutputFileType.Browser));
|
|
73
|
+
}
|
|
74
|
+
if (ssrOptions) {
|
|
75
|
+
// Regenerate the manifest to append route tree. This is only needed if SSR is enabled.
|
|
76
|
+
const manifest = additionalOutputFiles.find((f) => f.path === manifest_1.SERVER_APP_MANIFEST_FILENAME);
|
|
77
|
+
(0, node_assert_1.default)(manifest, `${manifest_1.SERVER_APP_MANIFEST_FILENAME} was not found in output files.`);
|
|
78
|
+
manifest.contents = new TextEncoder().encode((0, manifest_1.generateAngularServerAppManifest)(additionalHtmlOutputFiles, outputFiles, optimizationOptions.styles.inlineCritical ?? false, serializableRouteTreeNode));
|
|
68
79
|
}
|
|
69
80
|
}
|
|
70
81
|
additionalOutputFiles.push(...additionalHtmlOutputFiles.values());
|
|
@@ -72,7 +83,7 @@ async function executePostBundleSteps(options, outputFiles, assetFiles, initialF
|
|
|
72
83
|
// If localization is enabled, service worker is handled in the inlining process.
|
|
73
84
|
if (serviceWorker) {
|
|
74
85
|
try {
|
|
75
|
-
const serviceWorkerResult = await (0, service_worker_1.augmentAppWithServiceWorkerEsbuild)(workspaceRoot, serviceWorker,
|
|
86
|
+
const serviceWorkerResult = await (0, service_worker_1.augmentAppWithServiceWorkerEsbuild)(workspaceRoot, serviceWorker, baseHref, options.indexHtmlOptions?.output,
|
|
76
87
|
// Ensure additional files recently added are used
|
|
77
88
|
[...outputFiles, ...additionalOutputFiles], assetFiles);
|
|
78
89
|
additionalOutputFiles.push((0, utils_1.createOutputFile)('ngsw.json', serviceWorkerResult.manifest, bundler_context_1.BuildOutputFileType.Browser));
|
|
@@ -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.
|
|
@@ -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,
|
|
@@ -90,15 +90,6 @@ async function inlineI18n(options, executionResult, initialFiles) {
|
|
|
90
90
|
}
|
|
91
91
|
return inlineResult;
|
|
92
92
|
}
|
|
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
93
|
/**
|
|
103
94
|
* Loads all active translations using the translation loaders from the `@angular/localize` package.
|
|
104
95
|
* @param context The architect builder context for the current build.
|
|
@@ -10,6 +10,16 @@ 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
12
|
import { Schema as ApplicationBuilderOptions, I18NTranslation, 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;
|
|
@@ -148,4 +158,5 @@ export declare function normalizeOptions(context: BuilderContext, projectName: s
|
|
|
148
158
|
[key: string]: string;
|
|
149
159
|
} | undefined;
|
|
150
160
|
}>;
|
|
161
|
+
export declare function getLocaleBaseHref(baseHref: string | undefined, i18n: NormalizedApplicationBuildOptions['i18nOptions'], locale: string): string | undefined;
|
|
151
162
|
export {};
|
|
@@ -10,7 +10,9 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
|
10
10
|
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
11
11
|
};
|
|
12
12
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
13
|
+
exports.INDEX_HTML_SERVER = exports.INDEX_HTML_CSR = void 0;
|
|
13
14
|
exports.normalizeOptions = normalizeOptions;
|
|
15
|
+
exports.getLocaleBaseHref = getLocaleBaseHref;
|
|
14
16
|
const node_fs_1 = require("node:fs");
|
|
15
17
|
const promises_1 = require("node:fs/promises");
|
|
16
18
|
const node_module_1 = require("node:module");
|
|
@@ -21,7 +23,18 @@ const environment_options_1 = require("../../utils/environment-options");
|
|
|
21
23
|
const i18n_options_1 = require("../../utils/i18n-options");
|
|
22
24
|
const normalize_cache_1 = require("../../utils/normalize-cache");
|
|
23
25
|
const postcss_configuration_1 = require("../../utils/postcss-configuration");
|
|
26
|
+
const url_1 = require("../../utils/url");
|
|
24
27
|
const schema_1 = require("./schema");
|
|
28
|
+
/**
|
|
29
|
+
* The filename for the client-side rendered HTML template.
|
|
30
|
+
* This template is used for client-side rendering (CSR) in a web application.
|
|
31
|
+
*/
|
|
32
|
+
exports.INDEX_HTML_CSR = 'index.csr.html';
|
|
33
|
+
/**
|
|
34
|
+
* The filename for the server-side rendered HTML template.
|
|
35
|
+
* This template is used for server-side rendering (SSR) in a web application.
|
|
36
|
+
*/
|
|
37
|
+
exports.INDEX_HTML_SERVER = 'index.server.html';
|
|
25
38
|
/**
|
|
26
39
|
* Normalize the user provided options by creating full paths for all path based options
|
|
27
40
|
* and converting multi-form options into a single form that can be directly used
|
|
@@ -164,7 +177,7 @@ async function normalizeOptions(context, projectName, options, extensions) {
|
|
|
164
177
|
* For instance, accessing `foo.com/` would lead to `foo.com/index.html` being served instead of hitting the server.
|
|
165
178
|
*/
|
|
166
179
|
const indexBaseName = node_path_1.default.basename(options.index);
|
|
167
|
-
indexOutput = ssrOptions && indexBaseName === 'index.html' ?
|
|
180
|
+
indexOutput = ssrOptions && indexBaseName === 'index.html' ? exports.INDEX_HTML_CSR : indexBaseName;
|
|
168
181
|
}
|
|
169
182
|
else {
|
|
170
183
|
indexOutput = options.index.output || 'index.html';
|
|
@@ -369,3 +382,12 @@ function normalizeGlobalEntries(rawEntries, defaultName) {
|
|
|
369
382
|
}
|
|
370
383
|
return [...bundles.values()];
|
|
371
384
|
}
|
|
385
|
+
function getLocaleBaseHref(baseHref, i18n, locale) {
|
|
386
|
+
if (i18n.flatOutput) {
|
|
387
|
+
return undefined;
|
|
388
|
+
}
|
|
389
|
+
if (i18n.locales[locale] && i18n.locales[locale].baseHref !== '') {
|
|
390
|
+
return (0, url_1.urlJoin)(baseHref || '', i18n.locales[locale].baseHref ?? `/${locale}/`);
|
|
391
|
+
}
|
|
392
|
+
return undefined;
|
|
393
|
+
}
|
|
@@ -22,22 +22,22 @@ const utils_1 = require("../../tools/esbuild/utils");
|
|
|
22
22
|
* @returns An array of BundlerContext objects.
|
|
23
23
|
*/
|
|
24
24
|
function setupBundlerContexts(options, browsers, codeBundleCache) {
|
|
25
|
-
const { appShellOptions, prerenderOptions, serverEntryPoint, ssrOptions, workspaceRoot } = options;
|
|
25
|
+
const { appShellOptions, prerenderOptions, serverEntryPoint, ssrOptions, workspaceRoot, watch = false, } = options;
|
|
26
26
|
const target = (0, utils_1.transformSupportedBrowsersToTargets)(browsers);
|
|
27
27
|
const bundlerContexts = [];
|
|
28
28
|
// Browser application code
|
|
29
|
-
bundlerContexts.push(new bundler_context_1.BundlerContext(workspaceRoot,
|
|
29
|
+
bundlerContexts.push(new bundler_context_1.BundlerContext(workspaceRoot, watch, (0, application_code_bundle_1.createBrowserCodeBundleOptions)(options, target, codeBundleCache)));
|
|
30
30
|
// Browser polyfills code
|
|
31
31
|
const browserPolyfillBundleOptions = (0, application_code_bundle_1.createBrowserPolyfillBundleOptions)(options, target, codeBundleCache);
|
|
32
32
|
if (browserPolyfillBundleOptions) {
|
|
33
|
-
bundlerContexts.push(new bundler_context_1.BundlerContext(workspaceRoot,
|
|
33
|
+
bundlerContexts.push(new bundler_context_1.BundlerContext(workspaceRoot, watch, browserPolyfillBundleOptions));
|
|
34
34
|
}
|
|
35
35
|
// Global Stylesheets
|
|
36
36
|
if (options.globalStyles.length > 0) {
|
|
37
37
|
for (const initial of [true, false]) {
|
|
38
38
|
const bundleOptions = (0, global_styles_1.createGlobalStylesBundleOptions)(options, target, initial);
|
|
39
39
|
if (bundleOptions) {
|
|
40
|
-
bundlerContexts.push(new bundler_context_1.BundlerContext(workspaceRoot,
|
|
40
|
+
bundlerContexts.push(new bundler_context_1.BundlerContext(workspaceRoot, watch, bundleOptions, () => initial));
|
|
41
41
|
}
|
|
42
42
|
}
|
|
43
43
|
}
|
|
@@ -46,7 +46,7 @@ function setupBundlerContexts(options, browsers, codeBundleCache) {
|
|
|
46
46
|
for (const initial of [true, false]) {
|
|
47
47
|
const bundleOptions = (0, global_scripts_1.createGlobalScriptsBundleOptions)(options, target, initial);
|
|
48
48
|
if (bundleOptions) {
|
|
49
|
-
bundlerContexts.push(new bundler_context_1.BundlerContext(workspaceRoot,
|
|
49
|
+
bundlerContexts.push(new bundler_context_1.BundlerContext(workspaceRoot, watch, bundleOptions, () => initial));
|
|
50
50
|
}
|
|
51
51
|
}
|
|
52
52
|
}
|
|
@@ -54,11 +54,11 @@ function setupBundlerContexts(options, browsers, codeBundleCache) {
|
|
|
54
54
|
if (serverEntryPoint && (prerenderOptions || appShellOptions || ssrOptions)) {
|
|
55
55
|
const nodeTargets = [...target, ...(0, utils_1.getSupportedNodeTargets)()];
|
|
56
56
|
// Server application code
|
|
57
|
-
bundlerContexts.push(new bundler_context_1.BundlerContext(workspaceRoot,
|
|
57
|
+
bundlerContexts.push(new bundler_context_1.BundlerContext(workspaceRoot, watch, (0, application_code_bundle_1.createServerMainCodeBundleOptions)(options, nodeTargets, codeBundleCache)));
|
|
58
58
|
// Server polyfills code
|
|
59
59
|
const serverPolyfillBundleOptions = (0, application_code_bundle_1.createServerPolyfillBundleOptions)(options, nodeTargets, codeBundleCache);
|
|
60
60
|
if (serverPolyfillBundleOptions) {
|
|
61
|
-
bundlerContexts.push(new bundler_context_1.BundlerContext(workspaceRoot,
|
|
61
|
+
bundlerContexts.push(new bundler_context_1.BundlerContext(workspaceRoot, watch, serverPolyfillBundleOptions));
|
|
62
62
|
}
|
|
63
63
|
}
|
|
64
64
|
return bundlerContexts;
|
|
@@ -9,7 +9,6 @@ export { type BuildOutputFile, BuildOutputFileType } from '@angular/build';
|
|
|
9
9
|
export { createRxjsEsmResolutionPlugin } from '../../tools/esbuild/rxjs-esm-resolution-plugin';
|
|
10
10
|
export { JavaScriptTransformer } from '../../tools/esbuild/javascript-transformer';
|
|
11
11
|
export { getFeatureSupport, isZonelessApp } from '../../tools/esbuild/utils';
|
|
12
|
-
export { renderPage } from '../../utils/server-rendering/render-page';
|
|
13
12
|
export { type IndexHtmlTransform } from '../../utils/index-file/index-html-generator';
|
|
14
13
|
export { purgeStaleBuildCache } from '../../utils/purge-cache';
|
|
15
14
|
export { getSupportedBrowsers } from '../../utils/supported-browsers';
|
|
@@ -7,7 +7,7 @@
|
|
|
7
7
|
* found in the LICENSE file at https://angular.dev/license
|
|
8
8
|
*/
|
|
9
9
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
10
|
-
exports.buildApplicationInternal = exports.transformSupportedBrowsersToTargets = exports.getSupportedBrowsers = exports.purgeStaleBuildCache = exports.
|
|
10
|
+
exports.buildApplicationInternal = exports.transformSupportedBrowsersToTargets = exports.getSupportedBrowsers = exports.purgeStaleBuildCache = exports.isZonelessApp = exports.getFeatureSupport = exports.JavaScriptTransformer = exports.createRxjsEsmResolutionPlugin = exports.BuildOutputFileType = void 0;
|
|
11
11
|
var build_1 = require("@angular/build");
|
|
12
12
|
Object.defineProperty(exports, "BuildOutputFileType", { enumerable: true, get: function () { return build_1.BuildOutputFileType; } });
|
|
13
13
|
var rxjs_esm_resolution_plugin_1 = require("../../tools/esbuild/rxjs-esm-resolution-plugin");
|
|
@@ -17,8 +17,6 @@ Object.defineProperty(exports, "JavaScriptTransformer", { enumerable: true, get:
|
|
|
17
17
|
var utils_1 = require("../../tools/esbuild/utils");
|
|
18
18
|
Object.defineProperty(exports, "getFeatureSupport", { enumerable: true, get: function () { return utils_1.getFeatureSupport; } });
|
|
19
19
|
Object.defineProperty(exports, "isZonelessApp", { enumerable: true, get: function () { return utils_1.isZonelessApp; } });
|
|
20
|
-
var render_page_1 = require("../../utils/server-rendering/render-page");
|
|
21
|
-
Object.defineProperty(exports, "renderPage", { enumerable: true, get: function () { return render_page_1.renderPage; } });
|
|
22
20
|
var purge_cache_1 = require("../../utils/purge-cache");
|
|
23
21
|
Object.defineProperty(exports, "purgeStaleBuildCache", { enumerable: true, get: function () { return purge_cache_1.purgeStaleBuildCache; } });
|
|
24
22
|
var supported_browsers_1 = require("../../utils/supported-browsers");
|
|
@@ -9,7 +9,7 @@ import type { BuilderContext } from '@angular-devkit/architect';
|
|
|
9
9
|
import type { Plugin } from 'esbuild';
|
|
10
10
|
import type { Connect, DepOptimizationConfig, InlineConfig } from 'vite';
|
|
11
11
|
import { Result } from '../application/results';
|
|
12
|
-
import { type ApplicationBuilderInternalOptions, type ExternalResultMetadata, JavaScriptTransformer } from './internal';
|
|
12
|
+
import { type ApplicationBuilderInternalOptions, BuildOutputFileType, type ExternalResultMetadata, JavaScriptTransformer } from './internal';
|
|
13
13
|
import type { NormalizedDevServerOptions } from './options';
|
|
14
14
|
import type { DevServerBuilderOutput } from './output';
|
|
15
15
|
interface OutputFileRecord {
|
|
@@ -18,6 +18,11 @@ interface OutputFileRecord {
|
|
|
18
18
|
hash?: string;
|
|
19
19
|
updated: boolean;
|
|
20
20
|
servable: boolean;
|
|
21
|
+
type: BuildOutputFileType;
|
|
22
|
+
}
|
|
23
|
+
interface DevServerExternalResultMetadata extends Omit<ExternalResultMetadata, 'explicit'> {
|
|
24
|
+
explicitBrowser: string[];
|
|
25
|
+
explicitServer: string[];
|
|
21
26
|
}
|
|
22
27
|
export type BuilderAction = (options: ApplicationBuilderInternalOptions, context: BuilderContext, plugins?: Plugin[]) => AsyncIterable<Result>;
|
|
23
28
|
export declare function serveWithVite(serverOptions: NormalizedDevServerOptions, builderName: string, builderAction: BuilderAction, context: BuilderContext, transformers?: {
|
|
@@ -26,6 +31,6 @@ export declare function serveWithVite(serverOptions: NormalizedDevServerOptions,
|
|
|
26
31
|
middleware?: Connect.NextHandleFunction[];
|
|
27
32
|
buildPlugins?: Plugin[];
|
|
28
33
|
}): AsyncIterableIterator<DevServerBuilderOutput>;
|
|
29
|
-
export declare function setupServer(serverOptions: NormalizedDevServerOptions, outputFiles: Map<string, OutputFileRecord>, assets: Map<string, string>, preserveSymlinks: boolean | undefined, externalMetadata:
|
|
34
|
+
export declare function setupServer(serverOptions: NormalizedDevServerOptions, outputFiles: Map<string, OutputFileRecord>, assets: Map<string, string>, preserveSymlinks: boolean | undefined, externalMetadata: DevServerExternalResultMetadata, ssr: boolean, prebundleTransformer: JavaScriptTransformer, target: string[], zoneless: boolean, prebundleLoaderExtensions: EsbuildLoaderOption | undefined, extensionMiddleware?: Connect.NextHandleFunction[], indexHtmlTransformer?: (content: string) => Promise<string>, thirdPartySourcemaps?: boolean): Promise<InlineConfig>;
|
|
30
35
|
type EsbuildLoaderOption = Exclude<DepOptimizationConfig['esbuildOptions'], undefined>['loader'];
|
|
31
36
|
export {};
|
|
@@ -107,7 +107,8 @@ async function* serveWithVite(serverOptions, builderName, builderAction, context
|
|
|
107
107
|
const externalMetadata = {
|
|
108
108
|
implicitBrowser: [],
|
|
109
109
|
implicitServer: [],
|
|
110
|
-
|
|
110
|
+
explicitBrowser: [],
|
|
111
|
+
explicitServer: [],
|
|
111
112
|
};
|
|
112
113
|
// Add cleanup logic via a builder teardown.
|
|
113
114
|
let deferred;
|
|
@@ -187,15 +188,18 @@ async function* serveWithVite(serverOptions, builderName, builderAction, context
|
|
|
187
188
|
requiresServerRestart = implicitServerFiltered.some((dep) => !previousImplicitServer.has(dep));
|
|
188
189
|
}
|
|
189
190
|
// Empty Arrays to avoid growing unlimited with every re-build.
|
|
190
|
-
externalMetadata.
|
|
191
|
+
externalMetadata.explicitBrowser.length = 0;
|
|
192
|
+
externalMetadata.explicitServer.length = 0;
|
|
191
193
|
externalMetadata.implicitServer.length = 0;
|
|
192
194
|
externalMetadata.implicitBrowser.length = 0;
|
|
193
|
-
externalMetadata.
|
|
195
|
+
externalMetadata.explicitBrowser.push(...explicit);
|
|
196
|
+
externalMetadata.explicitServer.push(...explicit, ...nodeJsBuiltinModules);
|
|
194
197
|
externalMetadata.implicitServer.push(...implicitServerFiltered);
|
|
195
198
|
externalMetadata.implicitBrowser.push(...implicitBrowserFiltered);
|
|
196
199
|
// The below needs to be sorted as Vite uses these options are part of the hashing invalidation algorithm.
|
|
197
200
|
// See: https://github.com/vitejs/vite/blob/0873bae0cfe0f0718ad2f5743dd34a17e4ab563d/packages/vite/src/node/optimizer/index.ts#L1203-L1239
|
|
198
|
-
externalMetadata.
|
|
201
|
+
externalMetadata.explicitBrowser.sort();
|
|
202
|
+
externalMetadata.explicitServer.sort();
|
|
199
203
|
externalMetadata.implicitServer.sort();
|
|
200
204
|
externalMetadata.implicitBrowser.sort();
|
|
201
205
|
}
|
|
@@ -204,12 +208,14 @@ async function* serveWithVite(serverOptions, builderName, builderAction, context
|
|
|
204
208
|
server.config.server.fs.allow = [
|
|
205
209
|
...new Set([...server.config.server.fs.allow, ...assetFiles.values()]),
|
|
206
210
|
];
|
|
207
|
-
handleUpdate(normalizePath, generatedFiles, server, serverOptions, context.logger);
|
|
208
211
|
if (requiresServerRestart) {
|
|
209
212
|
// Restart the server to force SSR dep re-optimization when a dependency has been added.
|
|
210
213
|
// This is a workaround for: https://github.com/vitejs/vite/issues/14896
|
|
211
214
|
await server.restart();
|
|
212
215
|
}
|
|
216
|
+
else {
|
|
217
|
+
await handleUpdate(normalizePath, generatedFiles, server, serverOptions, context.logger);
|
|
218
|
+
}
|
|
213
219
|
}
|
|
214
220
|
else {
|
|
215
221
|
const projectName = context.target?.project;
|
|
@@ -271,12 +277,14 @@ async function* serveWithVite(serverOptions, builderName, builderAction, context
|
|
|
271
277
|
}
|
|
272
278
|
await new Promise((resolve) => (deferred = resolve));
|
|
273
279
|
}
|
|
274
|
-
function handleUpdate(normalizePath, generatedFiles, server, serverOptions, logger) {
|
|
280
|
+
async function handleUpdate(normalizePath, generatedFiles, server, serverOptions, logger) {
|
|
275
281
|
const updatedFiles = [];
|
|
282
|
+
let isServerFileUpdated = false;
|
|
276
283
|
// Invalidate any updated files
|
|
277
284
|
for (const [file, record] of generatedFiles) {
|
|
278
285
|
if (record.updated) {
|
|
279
286
|
updatedFiles.push(file);
|
|
287
|
+
isServerFileUpdated ||= record.type === internal_1.BuildOutputFileType.Server;
|
|
280
288
|
const updatedModules = server.moduleGraph.getModulesByFile(normalizePath((0, node_path_1.join)(server.config.root, file)));
|
|
281
289
|
updatedModules?.forEach((m) => server?.moduleGraph.invalidateModule(m));
|
|
282
290
|
}
|
|
@@ -284,6 +292,11 @@ function handleUpdate(normalizePath, generatedFiles, server, serverOptions, logg
|
|
|
284
292
|
if (!updatedFiles.length) {
|
|
285
293
|
return;
|
|
286
294
|
}
|
|
295
|
+
// clean server apps cache
|
|
296
|
+
if (isServerFileUpdated) {
|
|
297
|
+
const { ɵdestroyAngularServerApp } = (await server.ssrLoadModule('/main.server.mjs'));
|
|
298
|
+
ɵdestroyAngularServerApp();
|
|
299
|
+
}
|
|
287
300
|
if (serverOptions.liveReload || serverOptions.hmr) {
|
|
288
301
|
if (updatedFiles.every((f) => f.endsWith('.css'))) {
|
|
289
302
|
const timestamp = Date.now();
|
|
@@ -334,6 +347,7 @@ function analyzeResultFiles(normalizePath, htmlIndexPath, resultFiles, generated
|
|
|
334
347
|
contents: file.contents,
|
|
335
348
|
servable,
|
|
336
349
|
size: file.contents.byteLength,
|
|
350
|
+
type: file.type,
|
|
337
351
|
updated: false,
|
|
338
352
|
});
|
|
339
353
|
continue;
|
|
@@ -352,6 +366,7 @@ function analyzeResultFiles(normalizePath, htmlIndexPath, resultFiles, generated
|
|
|
352
366
|
size: file.contents.byteLength,
|
|
353
367
|
hash: file.hash,
|
|
354
368
|
updated: true,
|
|
369
|
+
type: file.type,
|
|
355
370
|
servable,
|
|
356
371
|
});
|
|
357
372
|
}
|
|
@@ -422,18 +437,18 @@ async function setupServer(serverOptions, outputFiles, assets, preserveSymlinks,
|
|
|
422
437
|
},
|
|
423
438
|
// This is needed when `externalDependencies` is used to prevent Vite load errors.
|
|
424
439
|
// NOTE: If Vite adds direct support for externals, this can be removed.
|
|
425
|
-
preTransformRequests: externalMetadata.
|
|
440
|
+
preTransformRequests: externalMetadata.explicitBrowser.length === 0,
|
|
426
441
|
},
|
|
427
442
|
ssr: {
|
|
428
443
|
// Note: `true` and `/.*/` have different sematics. When true, the `external` option is ignored.
|
|
429
444
|
noExternal: /.*/,
|
|
430
445
|
// Exclude any Node.js built in module and provided dependencies (currently build defined externals)
|
|
431
|
-
external: externalMetadata.
|
|
446
|
+
external: externalMetadata.explicitServer,
|
|
432
447
|
optimizeDeps: getDepOptimizationConfig({
|
|
433
448
|
// Only enable with caching since it causes prebundle dependencies to be cached
|
|
434
449
|
disabled: serverOptions.prebundle === false,
|
|
435
450
|
// Exclude any explicitly defined dependencies (currently build defined externals and node.js built-ins)
|
|
436
|
-
exclude: externalMetadata.
|
|
451
|
+
exclude: externalMetadata.explicitServer,
|
|
437
452
|
// Include all implict dependencies from the external packages internal option
|
|
438
453
|
include: externalMetadata.implicitServer,
|
|
439
454
|
ssr: true,
|
|
@@ -452,19 +467,19 @@ async function setupServer(serverOptions, outputFiles, assets, preserveSymlinks,
|
|
|
452
467
|
outputFiles,
|
|
453
468
|
assets,
|
|
454
469
|
ssr,
|
|
455
|
-
external: externalMetadata.
|
|
470
|
+
external: externalMetadata.explicitBrowser,
|
|
456
471
|
indexHtmlTransformer,
|
|
457
472
|
extensionMiddleware,
|
|
458
473
|
normalizePath,
|
|
459
474
|
}),
|
|
460
|
-
(0, id_prefix_plugin_1.createRemoveIdPrefixPlugin)(externalMetadata.
|
|
475
|
+
(0, id_prefix_plugin_1.createRemoveIdPrefixPlugin)(externalMetadata.explicitBrowser),
|
|
461
476
|
],
|
|
462
477
|
// Browser only optimizeDeps. (This does not run for SSR dependencies).
|
|
463
478
|
optimizeDeps: getDepOptimizationConfig({
|
|
464
479
|
// Only enable with caching since it causes prebundle dependencies to be cached
|
|
465
480
|
disabled: serverOptions.prebundle === false,
|
|
466
481
|
// Exclude any explicitly defined dependencies (currently build defined externals)
|
|
467
|
-
exclude: externalMetadata.
|
|
482
|
+
exclude: externalMetadata.explicitBrowser,
|
|
468
483
|
// Include all implict dependencies from the external packages internal option
|
|
469
484
|
include: externalMetadata.implicitBrowser,
|
|
470
485
|
ssr: false,
|
|
@@ -22,7 +22,7 @@ export declare class ParallelCompilation extends AngularCompilation {
|
|
|
22
22
|
#private;
|
|
23
23
|
readonly jit: boolean;
|
|
24
24
|
constructor(jit: boolean);
|
|
25
|
-
initialize(tsconfig: string, hostOptions: AngularHostOptions, compilerOptionsTransformer?: (
|
|
25
|
+
initialize(tsconfig: string, hostOptions: AngularHostOptions, compilerOptionsTransformer?: (compilerOptions: CompilerOptions) => CompilerOptions): Promise<{
|
|
26
26
|
affectedFiles: ReadonlySet<SourceFile>;
|
|
27
27
|
compilerOptions: CompilerOptions;
|
|
28
28
|
referencedFiles: readonly string[];
|
|
@@ -40,6 +40,11 @@ class ParallelCompilation extends angular_compilation_1.AngularCompilation {
|
|
|
40
40
|
useAtomics: !process.versions.webcontainer,
|
|
41
41
|
filename: localRequire.resolve('./parallel-worker'),
|
|
42
42
|
recordTiming: false,
|
|
43
|
+
env: {
|
|
44
|
+
...process.env,
|
|
45
|
+
// Enable compile code caching if enabled for the main process (only exists on Node.js v22.8+)
|
|
46
|
+
'NODE_COMPILE_CACHE': (0, node_module_1.getCompileCacheDir)?.(),
|
|
47
|
+
},
|
|
43
48
|
});
|
|
44
49
|
}
|
|
45
50
|
initialize(tsconfig, hostOptions, compilerOptionsTransformer) {
|
|
@@ -11,10 +11,5 @@ import { SourceFileCache } from './angular/source-file-cache';
|
|
|
11
11
|
import { BundlerOptionsFactory } from './bundler-context';
|
|
12
12
|
export declare function createBrowserCodeBundleOptions(options: NormalizedApplicationBuildOptions, target: string[], sourceFileCache?: SourceFileCache): BuildOptions;
|
|
13
13
|
export declare function createBrowserPolyfillBundleOptions(options: NormalizedApplicationBuildOptions, target: string[], sourceFileCache?: SourceFileCache): BuildOptions | BundlerOptionsFactory | undefined;
|
|
14
|
-
/**
|
|
15
|
-
* Create an esbuild 'build' options object for the server bundle.
|
|
16
|
-
* @param options The builder's user-provider normalized options.
|
|
17
|
-
* @returns An esbuild BuildOptions object.
|
|
18
|
-
*/
|
|
19
|
-
export declare function createServerCodeBundleOptions(options: NormalizedApplicationBuildOptions, target: string[], sourceFileCache: SourceFileCache): BuildOptions;
|
|
20
14
|
export declare function createServerPolyfillBundleOptions(options: NormalizedApplicationBuildOptions, target: string[], sourceFileCache?: SourceFileCache): BundlerOptionsFactory | undefined;
|
|
15
|
+
export declare function createServerMainCodeBundleOptions(options: NormalizedApplicationBuildOptions, target: string[], sourceFileCache: SourceFileCache): BuildOptions;
|