@angular/build 19.0.1 → 19.0.3
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 +3 -3
- package/src/builders/application/execute-post-bundle.js +3 -3
- package/src/builders/application/options.js +15 -14
- package/src/private.d.ts +5 -1
- package/src/private.js +7 -3
- package/src/tools/esbuild/angular/compiler-plugin.js +16 -0
- package/src/tools/esbuild/application-code-bundle.js +25 -39
- package/src/tools/esbuild/global-scripts.js +2 -1
- package/src/utils/index-file/augment-index-html.js +14 -4
- package/src/utils/normalize-cache.js +1 -1
- package/src/utils/server-rendering/manifest.d.ts +3 -1
- package/src/utils/server-rendering/manifest.js +22 -10
- package/src/utils/server-rendering/prerender.js +3 -3
- package/src/utils/server-rendering/routes-extractor-worker.js +6 -1
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@angular/build",
|
|
3
|
-
"version": "19.0.
|
|
3
|
+
"version": "19.0.3",
|
|
4
4
|
"description": "Official build system for Angular",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"Angular CLI",
|
|
@@ -23,7 +23,7 @@
|
|
|
23
23
|
"builders": "builders.json",
|
|
24
24
|
"dependencies": {
|
|
25
25
|
"@ampproject/remapping": "2.3.0",
|
|
26
|
-
"@angular-devkit/architect": "0.1900.
|
|
26
|
+
"@angular-devkit/architect": "0.1900.3",
|
|
27
27
|
"@babel/core": "7.26.0",
|
|
28
28
|
"@babel/helper-annotate-as-pure": "7.25.9",
|
|
29
29
|
"@babel/helper-split-export-declaration": "7.24.7",
|
|
@@ -57,7 +57,7 @@
|
|
|
57
57
|
"@angular/localize": "^19.0.0",
|
|
58
58
|
"@angular/platform-server": "^19.0.0",
|
|
59
59
|
"@angular/service-worker": "^19.0.0",
|
|
60
|
-
"@angular/ssr": "^19.0.
|
|
60
|
+
"@angular/ssr": "^19.0.3",
|
|
61
61
|
"less": "^4.2.0",
|
|
62
62
|
"postcss": "^8.4.0",
|
|
63
63
|
"tailwindcss": "^2.0.0 || ^3.0.0",
|
|
@@ -37,7 +37,7 @@ async function executePostBundleSteps(options, outputFiles, assetFiles, initialF
|
|
|
37
37
|
const allErrors = [];
|
|
38
38
|
const allWarnings = [];
|
|
39
39
|
const prerenderedRoutes = {};
|
|
40
|
-
const { baseHref = '/', serviceWorker, indexHtmlOptions, optimizationOptions, sourcemapOptions, outputMode, serverEntryPoint, prerenderOptions, appShellOptions, workspaceRoot, partialSSRBuild, } = options;
|
|
40
|
+
const { baseHref = '/', serviceWorker, i18nOptions, indexHtmlOptions, optimizationOptions, sourcemapOptions, outputMode, serverEntryPoint, prerenderOptions, appShellOptions, workspaceRoot, partialSSRBuild, } = options;
|
|
41
41
|
// Index HTML content without CSS inlining to be used for server rendering (AppShell, SSG and SSR).
|
|
42
42
|
// NOTE: Critical CSS inlining is deliberately omitted here, as it will be handled during server rendering.
|
|
43
43
|
// Additionally, when using prerendering or AppShell, the index HTML file may be regenerated.
|
|
@@ -56,7 +56,7 @@ async function executePostBundleSteps(options, outputFiles, assetFiles, initialF
|
|
|
56
56
|
}
|
|
57
57
|
// Create server manifest
|
|
58
58
|
if (serverEntryPoint) {
|
|
59
|
-
const { manifestContent, serverAssetsChunks } = (0, manifest_1.generateAngularServerAppManifest)(additionalHtmlOutputFiles, outputFiles, optimizationOptions.styles.inlineCritical ?? false, undefined, locale);
|
|
59
|
+
const { manifestContent, serverAssetsChunks } = (0, manifest_1.generateAngularServerAppManifest)(additionalHtmlOutputFiles, outputFiles, optimizationOptions.styles.inlineCritical ?? false, undefined, locale, baseHref);
|
|
60
60
|
additionalOutputFiles.push(...serverAssetsChunks, (0, utils_1.createOutputFile)(manifest_1.SERVER_APP_MANIFEST_FILENAME, manifestContent, bundler_context_1.BuildOutputFileType.ServerApplication));
|
|
61
61
|
}
|
|
62
62
|
// Pre-render (SSG) and App-shell
|
|
@@ -95,7 +95,7 @@ async function executePostBundleSteps(options, outputFiles, assetFiles, initialF
|
|
|
95
95
|
// Regenerate the manifest to append route tree. This is only needed if SSR is enabled.
|
|
96
96
|
const manifest = additionalOutputFiles.find((f) => f.path === manifest_1.SERVER_APP_MANIFEST_FILENAME);
|
|
97
97
|
(0, node_assert_1.default)(manifest, `${manifest_1.SERVER_APP_MANIFEST_FILENAME} was not found in output files.`);
|
|
98
|
-
const { manifestContent, serverAssetsChunks } = (0, manifest_1.generateAngularServerAppManifest)(additionalHtmlOutputFiles, outputFiles, optimizationOptions.styles.inlineCritical ?? false, serializableRouteTreeNodeForManifest, locale);
|
|
98
|
+
const { manifestContent, serverAssetsChunks } = (0, manifest_1.generateAngularServerAppManifest)(additionalHtmlOutputFiles, outputFiles, optimizationOptions.styles.inlineCritical ?? false, serializableRouteTreeNodeForManifest, locale, baseHref);
|
|
99
99
|
for (const chunk of serverAssetsChunks) {
|
|
100
100
|
const idx = additionalOutputFiles.findIndex(({ path }) => path === chunk.path);
|
|
101
101
|
if (idx === -1) {
|
|
@@ -194,24 +194,25 @@ async function normalizeOptions(context, projectName, options, extensions) {
|
|
|
194
194
|
let indexOutput;
|
|
195
195
|
// The output file will be created within the configured output path
|
|
196
196
|
if (typeof options.index === 'string') {
|
|
197
|
-
|
|
198
|
-
* If SSR is activated, create a distinct entry file for the `index.html`.
|
|
199
|
-
* This is necessary because numerous server/cloud providers automatically serve the `index.html` as a static file
|
|
200
|
-
* if it exists (handling SSG).
|
|
201
|
-
*
|
|
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`.
|
|
205
|
-
*/
|
|
206
|
-
const indexBaseName = node_path_1.default.basename(options.index);
|
|
207
|
-
indexOutput =
|
|
208
|
-
(ssrOptions || prerenderOptions) && indexBaseName === 'index.html'
|
|
209
|
-
? exports.INDEX_HTML_CSR
|
|
210
|
-
: indexBaseName;
|
|
197
|
+
indexOutput = options.index;
|
|
211
198
|
}
|
|
212
199
|
else {
|
|
213
200
|
indexOutput = options.index.output || 'index.html';
|
|
214
201
|
}
|
|
202
|
+
/**
|
|
203
|
+
* If SSR is activated, create a distinct entry file for the `index.html`.
|
|
204
|
+
* This is necessary because numerous server/cloud providers automatically serve the `index.html` as a static file
|
|
205
|
+
* if it exists (handling SSG).
|
|
206
|
+
*
|
|
207
|
+
* For instance, accessing `foo.com/` would lead to `foo.com/index.html` being served instead of hitting the server.
|
|
208
|
+
*
|
|
209
|
+
* This approach can also be applied to service workers, where the `index.csr.html` is served instead of the prerendered `index.html`.
|
|
210
|
+
*/
|
|
211
|
+
const indexBaseName = node_path_1.default.basename(indexOutput);
|
|
212
|
+
indexOutput =
|
|
213
|
+
(ssrOptions || prerenderOptions) && indexBaseName === 'index.html'
|
|
214
|
+
? exports.INDEX_HTML_CSR
|
|
215
|
+
: indexBaseName;
|
|
215
216
|
indexHtmlOptions = {
|
|
216
217
|
input: node_path_1.default.join(workspaceRoot, typeof options.index === 'string' ? options.index : options.index.input),
|
|
217
218
|
output: indexOutput,
|
package/src/private.d.ts
CHANGED
|
@@ -11,6 +11,8 @@
|
|
|
11
11
|
* All exports are not supported for external use, do not provide SemVer guarantees, and
|
|
12
12
|
* their existence may change in any future version.
|
|
13
13
|
*/
|
|
14
|
+
import { CompilerPluginOptions } from './tools/esbuild/angular/compiler-plugin';
|
|
15
|
+
import { BundleStylesheetOptions } from './tools/esbuild/stylesheets/bundle-options';
|
|
14
16
|
export { buildApplicationInternal } from './builders/application';
|
|
15
17
|
export type { ApplicationBuilderInternalOptions } from './builders/application/options';
|
|
16
18
|
export { type Result, type ResultFile, ResultKind } from './builders/application/results';
|
|
@@ -23,7 +25,9 @@ export { SassWorkerImplementation } from './tools/sass/sass-service';
|
|
|
23
25
|
export { SourceFileCache } from './tools/esbuild/angular/source-file-cache';
|
|
24
26
|
export { createJitResourceTransformer } from './tools/angular/transformers/jit-resource-transformer';
|
|
25
27
|
export { JavaScriptTransformer } from './tools/esbuild/javascript-transformer';
|
|
26
|
-
export
|
|
28
|
+
export declare function createCompilerPlugin(pluginOptions: CompilerPluginOptions, styleOptions: BundleStylesheetOptions & {
|
|
29
|
+
inlineStyleLanguage: string;
|
|
30
|
+
}): import('esbuild').Plugin;
|
|
27
31
|
export * from './utils/bundle-calculator';
|
|
28
32
|
export { checkPort } from './utils/check-port';
|
|
29
33
|
export { deleteOutputDir } from './utils/delete-output-dir';
|
package/src/private.js
CHANGED
|
@@ -21,13 +21,16 @@ var __exportStar = (this && this.__exportStar) || function(m, exports) {
|
|
|
21
21
|
for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
|
|
22
22
|
};
|
|
23
23
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
24
|
-
exports.assertCompatibleAngularVersion = exports.getSupportedBrowsers = exports.generateBuildStatsTable = exports.augmentAppWithServiceWorker = exports.purgeStaleBuildCache = exports.createTranslationLoader = exports.loadProxyConfiguration = exports.InlineCriticalCssProcessor = exports.IndexHtmlGenerator = exports.loadTranslations = exports.createI18nOptions = exports.deleteOutputDir = exports.checkPort = exports.
|
|
24
|
+
exports.assertCompatibleAngularVersion = exports.getSupportedBrowsers = exports.generateBuildStatsTable = exports.augmentAppWithServiceWorker = exports.purgeStaleBuildCache = exports.createTranslationLoader = exports.loadProxyConfiguration = exports.InlineCriticalCssProcessor = exports.IndexHtmlGenerator = exports.loadTranslations = exports.createI18nOptions = exports.deleteOutputDir = exports.checkPort = exports.JavaScriptTransformer = exports.createJitResourceTransformer = exports.SourceFileCache = exports.SassWorkerImplementation = exports.transformSupportedBrowsersToTargets = exports.emitFilesToDisk = exports.serveWithVite = exports.ResultKind = exports.buildApplicationInternal = void 0;
|
|
25
|
+
exports.createCompilerPlugin = createCompilerPlugin;
|
|
25
26
|
/**
|
|
26
27
|
* @fileoverview
|
|
27
28
|
* Private exports intended only for use with the @angular-devkit/build-angular package.
|
|
28
29
|
* All exports are not supported for external use, do not provide SemVer guarantees, and
|
|
29
30
|
* their existence may change in any future version.
|
|
30
31
|
*/
|
|
32
|
+
const compiler_plugin_1 = require("./tools/esbuild/angular/compiler-plugin");
|
|
33
|
+
const component_stylesheets_1 = require("./tools/esbuild/angular/component-stylesheets");
|
|
31
34
|
// Builders
|
|
32
35
|
var application_1 = require("./builders/application");
|
|
33
36
|
Object.defineProperty(exports, "buildApplicationInternal", { enumerable: true, get: function () { return application_1.buildApplicationInternal; } });
|
|
@@ -49,8 +52,9 @@ var jit_resource_transformer_1 = require("./tools/angular/transformers/jit-resou
|
|
|
49
52
|
Object.defineProperty(exports, "createJitResourceTransformer", { enumerable: true, get: function () { return jit_resource_transformer_1.createJitResourceTransformer; } });
|
|
50
53
|
var javascript_transformer_1 = require("./tools/esbuild/javascript-transformer");
|
|
51
54
|
Object.defineProperty(exports, "JavaScriptTransformer", { enumerable: true, get: function () { return javascript_transformer_1.JavaScriptTransformer; } });
|
|
52
|
-
|
|
53
|
-
|
|
55
|
+
function createCompilerPlugin(pluginOptions, styleOptions) {
|
|
56
|
+
return (0, compiler_plugin_1.createCompilerPlugin)(pluginOptions, new component_stylesheets_1.ComponentStylesheetBundler(styleOptions, styleOptions.inlineStyleLanguage, pluginOptions.incremental));
|
|
57
|
+
}
|
|
54
58
|
// Utilities
|
|
55
59
|
__exportStar(require("./utils/bundle-calculator"), exports);
|
|
56
60
|
var check_port_1 = require("./utils/check-port");
|
|
@@ -386,6 +386,22 @@ function createCompilerPlugin(pluginOptions, stylesheetBundler) {
|
|
|
386
386
|
};
|
|
387
387
|
}, true);
|
|
388
388
|
}));
|
|
389
|
+
// Add a load handler if there are file replacement option entries for JSON files
|
|
390
|
+
if (pluginOptions.fileReplacements &&
|
|
391
|
+
Object.keys(pluginOptions.fileReplacements).some((value) => value.endsWith('.json'))) {
|
|
392
|
+
build.onLoad({ filter: /\.json$/ }, (0, load_result_cache_1.createCachedLoad)(pluginOptions.loadResultCache, async (args) => {
|
|
393
|
+
const replacement = pluginOptions.fileReplacements?.[path.normalize(args.path)];
|
|
394
|
+
if (replacement) {
|
|
395
|
+
return {
|
|
396
|
+
contents: await Promise.resolve().then(() => __importStar(require('fs/promises'))).then(({ readFile }) => readFile(path.normalize(replacement))),
|
|
397
|
+
loader: 'json',
|
|
398
|
+
watchFiles: [replacement],
|
|
399
|
+
};
|
|
400
|
+
}
|
|
401
|
+
// If no replacement defined, let esbuild handle it directly
|
|
402
|
+
return null;
|
|
403
|
+
}));
|
|
404
|
+
}
|
|
389
405
|
// Setup bundling of component templates and stylesheets when in JIT mode
|
|
390
406
|
if (pluginOptions.jit) {
|
|
391
407
|
(0, jit_plugin_callbacks_1.setupJitPluginCallbacks)(build, stylesheetBundler, additionalResults, pluginOptions.loadResultCache);
|
|
@@ -171,7 +171,6 @@ function createServerMainCodeBundleOptions(options, target, sourceFileCache, sty
|
|
|
171
171
|
return (loadResultCache) => {
|
|
172
172
|
const pluginOptions = (0, compiler_plugin_options_1.createCompilerPluginOptions)(options, sourceFileCache, loadResultCache);
|
|
173
173
|
const mainServerNamespace = 'angular:main-server';
|
|
174
|
-
const mainServerInjectPolyfillsNamespace = 'angular:main-server-inject-polyfills';
|
|
175
174
|
const mainServerInjectManifestNamespace = 'angular:main-server-inject-manifest';
|
|
176
175
|
const zoneless = (0, utils_1.isZonelessApp)(polyfills);
|
|
177
176
|
const entryPoints = {
|
|
@@ -187,7 +186,9 @@ function createServerMainCodeBundleOptions(options, target, sourceFileCache, sty
|
|
|
187
186
|
const buildOptions = {
|
|
188
187
|
...getEsBuildServerCommonOptions(options),
|
|
189
188
|
target,
|
|
190
|
-
|
|
189
|
+
banner: {
|
|
190
|
+
js: `import './polyfills.server.mjs';`,
|
|
191
|
+
},
|
|
191
192
|
entryPoints,
|
|
192
193
|
supported: (0, utils_1.getFeatureSupport)(target, zoneless),
|
|
193
194
|
plugins: [
|
|
@@ -217,16 +218,9 @@ function createServerMainCodeBundleOptions(options, target, sourceFileCache, sty
|
|
|
217
218
|
buildOptions.external.push('xhr2');
|
|
218
219
|
}
|
|
219
220
|
buildOptions.plugins.push((0, server_bundle_metadata_plugin_1.createServerBundleMetadata)(), (0, virtual_module_plugin_1.createVirtualModulePlugin)({
|
|
220
|
-
namespace: mainServerInjectPolyfillsNamespace,
|
|
221
|
-
cache: loadResultCache,
|
|
222
|
-
loadContent: () => ({
|
|
223
|
-
contents: `import './polyfills.server.mjs';`,
|
|
224
|
-
loader: 'js',
|
|
225
|
-
resolveDir: workspaceRoot,
|
|
226
|
-
}),
|
|
227
|
-
}), (0, virtual_module_plugin_1.createVirtualModulePlugin)({
|
|
228
221
|
namespace: mainServerInjectManifestNamespace,
|
|
229
222
|
cache: loadResultCache,
|
|
223
|
+
entryPointOnly: false,
|
|
230
224
|
loadContent: async () => {
|
|
231
225
|
const contents = [
|
|
232
226
|
// Configure `@angular/ssr` manifest.
|
|
@@ -246,15 +240,17 @@ function createServerMainCodeBundleOptions(options, target, sourceFileCache, sty
|
|
|
246
240
|
loadContent: async () => {
|
|
247
241
|
const mainServerEntryPointJsImport = entryFileToWorkspaceRelative(workspaceRoot, mainServerEntryPoint);
|
|
248
242
|
const contents = [
|
|
243
|
+
// Inject manifest
|
|
244
|
+
`import '${mainServerInjectManifestNamespace}';`,
|
|
245
|
+
// Add @angular/ssr exports
|
|
246
|
+
`export {
|
|
247
|
+
ɵdestroyAngularServerApp,
|
|
248
|
+
ɵextractRoutesAndCreateRouteTree,
|
|
249
|
+
ɵgetOrCreateAngularServerApp,
|
|
250
|
+
} from '@angular/ssr';`,
|
|
249
251
|
// Re-export all symbols including default export from 'main.server.ts'
|
|
250
252
|
`export { default } from '${mainServerEntryPointJsImport}';`,
|
|
251
253
|
`export * from '${mainServerEntryPointJsImport}';`,
|
|
252
|
-
// Add @angular/ssr exports
|
|
253
|
-
`export {
|
|
254
|
-
ɵdestroyAngularServerApp,
|
|
255
|
-
ɵextractRoutesAndCreateRouteTree,
|
|
256
|
-
ɵgetOrCreateAngularServerApp,
|
|
257
|
-
} from '@angular/ssr';`,
|
|
258
254
|
];
|
|
259
255
|
return {
|
|
260
256
|
contents: contents.join('\n'),
|
|
@@ -277,17 +273,21 @@ function createSsrEntryCodeBundleOptions(options, target, sourceFileCache, style
|
|
|
277
273
|
const pluginOptions = (0, compiler_plugin_options_1.createCompilerPluginOptions)(options, sourceFileCache, loadResultCache);
|
|
278
274
|
const ssrEntryNamespace = 'angular:ssr-entry';
|
|
279
275
|
const ssrInjectManifestNamespace = 'angular:ssr-entry-inject-manifest';
|
|
280
|
-
const ssrInjectRequireNamespace = 'angular:ssr-entry-inject-require';
|
|
281
276
|
const isNodePlatform = options.ssrOptions?.platform !== schema_1.ExperimentalPlatform.Neutral;
|
|
282
|
-
const inject = [ssrInjectManifestNamespace];
|
|
283
|
-
if (isNodePlatform) {
|
|
284
|
-
inject.unshift(ssrInjectRequireNamespace);
|
|
285
|
-
}
|
|
286
277
|
const buildOptions = {
|
|
287
278
|
...getEsBuildServerCommonOptions(options),
|
|
288
279
|
target,
|
|
280
|
+
banner: isNodePlatform
|
|
281
|
+
? {
|
|
282
|
+
js: [
|
|
283
|
+
// Note: Needed as esbuild does not provide require shims / proxy from ESModules.
|
|
284
|
+
// See: https://github.com/evanw/esbuild/issues/1921.
|
|
285
|
+
`import { createRequire } from 'node:module';`,
|
|
286
|
+
`globalThis['require'] ??= createRequire(import.meta.url);`,
|
|
287
|
+
].join('\n'),
|
|
288
|
+
}
|
|
289
|
+
: undefined,
|
|
289
290
|
entryPoints: {
|
|
290
|
-
// TODO: consider renaming to index
|
|
291
291
|
'server': ssrEntryNamespace,
|
|
292
292
|
},
|
|
293
293
|
supported: (0, utils_1.getFeatureSupport)(target, true),
|
|
@@ -299,7 +299,6 @@ function createSsrEntryCodeBundleOptions(options, target, sourceFileCache, style
|
|
|
299
299
|
// Component stylesheet bundler
|
|
300
300
|
stylesheetBundler),
|
|
301
301
|
],
|
|
302
|
-
inject,
|
|
303
302
|
};
|
|
304
303
|
buildOptions.plugins ??= [];
|
|
305
304
|
if (externalPackages) {
|
|
@@ -317,24 +316,9 @@ function createSsrEntryCodeBundleOptions(options, target, sourceFileCache, style
|
|
|
317
316
|
buildOptions.external.push('xhr2');
|
|
318
317
|
}
|
|
319
318
|
buildOptions.plugins.push((0, server_bundle_metadata_plugin_1.createServerBundleMetadata)({ ssrEntryBundle: true }), (0, virtual_module_plugin_1.createVirtualModulePlugin)({
|
|
320
|
-
namespace: ssrInjectRequireNamespace,
|
|
321
|
-
cache: loadResultCache,
|
|
322
|
-
loadContent: () => {
|
|
323
|
-
const contents = [
|
|
324
|
-
// Note: Needed as esbuild does not provide require shims / proxy from ESModules.
|
|
325
|
-
// See: https://github.com/evanw/esbuild/issues/1921.
|
|
326
|
-
`import { createRequire } from 'node:module';`,
|
|
327
|
-
`globalThis['require'] ??= createRequire(import.meta.url);`,
|
|
328
|
-
];
|
|
329
|
-
return {
|
|
330
|
-
contents: contents.join('\n'),
|
|
331
|
-
loader: 'js',
|
|
332
|
-
resolveDir: workspaceRoot,
|
|
333
|
-
};
|
|
334
|
-
},
|
|
335
|
-
}), (0, virtual_module_plugin_1.createVirtualModulePlugin)({
|
|
336
319
|
namespace: ssrInjectManifestNamespace,
|
|
337
320
|
cache: loadResultCache,
|
|
321
|
+
entryPointOnly: false,
|
|
338
322
|
loadContent: () => {
|
|
339
323
|
const contents = [
|
|
340
324
|
// Configure `@angular/ssr` app engine manifest.
|
|
@@ -354,6 +338,8 @@ function createSsrEntryCodeBundleOptions(options, target, sourceFileCache, style
|
|
|
354
338
|
loadContent: () => {
|
|
355
339
|
const serverEntryPointJsImport = entryFileToWorkspaceRelative(workspaceRoot, serverEntryPoint);
|
|
356
340
|
const contents = [
|
|
341
|
+
// Configure `@angular/ssr` app engine manifest.
|
|
342
|
+
`import '${ssrInjectManifestNamespace}';`,
|
|
357
343
|
// Re-export all symbols including default export
|
|
358
344
|
`import * as server from '${serverEntryPointJsImport}';`,
|
|
359
345
|
`export * from '${serverEntryPointJsImport}';`,
|
|
@@ -49,7 +49,7 @@ const virtual_module_plugin_1 = require("./virtual-module-plugin");
|
|
|
49
49
|
* @returns An esbuild BuildOptions object.
|
|
50
50
|
*/
|
|
51
51
|
function createGlobalScriptsBundleOptions(options, target, initial) {
|
|
52
|
-
const { globalScripts, optimizationOptions, outputNames, preserveSymlinks, sourcemapOptions, jsonLogs, workspaceRoot, } = options;
|
|
52
|
+
const { globalScripts, optimizationOptions, outputNames, preserveSymlinks, sourcemapOptions, jsonLogs, workspaceRoot, define, } = options;
|
|
53
53
|
const namespace = 'angular:script/global';
|
|
54
54
|
const entryPoints = {};
|
|
55
55
|
let found = false;
|
|
@@ -83,6 +83,7 @@ function createGlobalScriptsBundleOptions(options, target, initial) {
|
|
|
83
83
|
platform: 'neutral',
|
|
84
84
|
target,
|
|
85
85
|
preserveSymlinks,
|
|
86
|
+
define,
|
|
86
87
|
plugins: [
|
|
87
88
|
(0, sourcemap_ignorelist_plugin_1.createSourcemapIgnorelistPlugin)(),
|
|
88
89
|
(0, virtual_module_plugin_1.createVirtualModulePlugin)({
|
|
@@ -21,7 +21,7 @@ const valid_self_closing_tags_1 = require("./valid-self-closing-tags");
|
|
|
21
21
|
*/
|
|
22
22
|
// eslint-disable-next-line max-lines-per-function
|
|
23
23
|
async function augmentIndexHtml(params) {
|
|
24
|
-
const { loadOutputFile, files, entrypoints, sri, deployUrl
|
|
24
|
+
const { loadOutputFile, files, entrypoints, sri, deployUrl, lang, baseHref, html, imageDomains } = params;
|
|
25
25
|
const warnings = [];
|
|
26
26
|
const errors = [];
|
|
27
27
|
let { crossOrigin = 'none' } = params;
|
|
@@ -57,7 +57,7 @@ async function augmentIndexHtml(params) {
|
|
|
57
57
|
}
|
|
58
58
|
let scriptTags = [];
|
|
59
59
|
for (const [src, isModule] of scripts) {
|
|
60
|
-
const attrs = [`src="${deployUrl}
|
|
60
|
+
const attrs = [`src="${generateUrl(src, deployUrl)}"`];
|
|
61
61
|
// This is also need for non entry-points as they may contain problematic code.
|
|
62
62
|
if (isModule) {
|
|
63
63
|
attrs.push('type="module"');
|
|
@@ -77,7 +77,7 @@ async function augmentIndexHtml(params) {
|
|
|
77
77
|
let headerLinkTags = [];
|
|
78
78
|
let bodyLinkTags = [];
|
|
79
79
|
for (const src of stylesheets) {
|
|
80
|
-
const attrs = [`rel="stylesheet"`, `href="${deployUrl}
|
|
80
|
+
const attrs = [`rel="stylesheet"`, `href="${generateUrl(src, deployUrl)}"`];
|
|
81
81
|
if (crossOrigin !== 'none') {
|
|
82
82
|
attrs.push(`crossorigin="${crossOrigin}"`);
|
|
83
83
|
}
|
|
@@ -89,7 +89,7 @@ async function augmentIndexHtml(params) {
|
|
|
89
89
|
}
|
|
90
90
|
if (params.hints?.length) {
|
|
91
91
|
for (const hint of params.hints) {
|
|
92
|
-
const attrs = [`rel="${hint.mode}"`, `href="${
|
|
92
|
+
const attrs = [`rel="${hint.mode}"`, `href="${generateUrl(hint.url, deployUrl)}"`];
|
|
93
93
|
if (hint.mode !== 'modulepreload' && crossOrigin !== 'none') {
|
|
94
94
|
// Value is considered anonymous by the browser when not present or empty
|
|
95
95
|
attrs.push(crossOrigin === 'anonymous' ? 'crossorigin' : `crossorigin="${crossOrigin}"`);
|
|
@@ -215,6 +215,16 @@ function generateSriAttributes(content) {
|
|
|
215
215
|
const hash = (0, node_crypto_1.createHash)(algo).update(content, 'utf8').digest('base64');
|
|
216
216
|
return `integrity="${algo}-${hash}"`;
|
|
217
217
|
}
|
|
218
|
+
function generateUrl(value, deployUrl) {
|
|
219
|
+
if (!deployUrl) {
|
|
220
|
+
return value;
|
|
221
|
+
}
|
|
222
|
+
// Skip if root-relative, absolute or protocol relative url
|
|
223
|
+
if (/^((?:\w+:)?\/\/|data:|chrome:|\/)/.test(value)) {
|
|
224
|
+
return value;
|
|
225
|
+
}
|
|
226
|
+
return `${deployUrl}${value}`;
|
|
227
|
+
}
|
|
218
228
|
function updateAttribute(tag, name, value) {
|
|
219
229
|
const index = tag.attrs.findIndex((a) => a.name === name);
|
|
220
230
|
const newValue = { name, value };
|
|
@@ -10,7 +10,7 @@ Object.defineProperty(exports, "__esModule", { value: true });
|
|
|
10
10
|
exports.normalizeCacheOptions = normalizeCacheOptions;
|
|
11
11
|
const node_path_1 = require("node:path");
|
|
12
12
|
/** Version placeholder is replaced during the build process with actual package version */
|
|
13
|
-
const VERSION = '19.0.
|
|
13
|
+
const VERSION = '19.0.3';
|
|
14
14
|
function hasCacheMetadata(value) {
|
|
15
15
|
return (!!value &&
|
|
16
16
|
typeof value === 'object' &&
|
|
@@ -40,12 +40,14 @@ export declare function generateAngularServerAppEngineManifest(i18nOptions: Norm
|
|
|
40
40
|
* server-side rendering and routing.
|
|
41
41
|
* @param locale - An optional string representing the locale or language code to be used for
|
|
42
42
|
* the application, helping with localization and rendering content specific to the locale.
|
|
43
|
+
* @param baseHref - The base HREF for the application. This is used to set the base URL
|
|
44
|
+
* for all relative URLs in the application.
|
|
43
45
|
*
|
|
44
46
|
* @returns An object containing:
|
|
45
47
|
* - `manifestContent`: A string of the SSR manifest content.
|
|
46
48
|
* - `serverAssetsChunks`: An array of build output files containing the generated assets for the server.
|
|
47
49
|
*/
|
|
48
|
-
export declare function generateAngularServerAppManifest(additionalHtmlOutputFiles: Map<string, BuildOutputFile>, outputFiles: BuildOutputFile[], inlineCriticalCss: boolean, routes: readonly unknown[] | undefined, locale: string | undefined): {
|
|
50
|
+
export declare function generateAngularServerAppManifest(additionalHtmlOutputFiles: Map<string, BuildOutputFile>, outputFiles: BuildOutputFile[], inlineCriticalCss: boolean, routes: readonly unknown[] | undefined, locale: string | undefined, baseHref: string): {
|
|
49
51
|
manifestContent: string;
|
|
50
52
|
serverAssetsChunks: BuildOutputFile[];
|
|
51
53
|
};
|
|
@@ -48,7 +48,7 @@ function escapeUnsafeChars(str) {
|
|
|
48
48
|
* for all relative URLs in the application.
|
|
49
49
|
*/
|
|
50
50
|
function generateAngularServerAppEngineManifest(i18nOptions, baseHref) {
|
|
51
|
-
const
|
|
51
|
+
const entryPoints = {};
|
|
52
52
|
if (i18nOptions.shouldInline) {
|
|
53
53
|
for (const locale of i18nOptions.inlineLocales) {
|
|
54
54
|
const importPath = './' + (i18nOptions.flatOutput ? '' : locale + '/') + MAIN_SERVER_OUTPUT_FILENAME;
|
|
@@ -57,18 +57,22 @@ function generateAngularServerAppEngineManifest(i18nOptions, baseHref) {
|
|
|
57
57
|
const start = localeWithBaseHref[0] === '/' ? 1 : 0;
|
|
58
58
|
const end = localeWithBaseHref[localeWithBaseHref.length - 1] === '/' ? -1 : undefined;
|
|
59
59
|
localeWithBaseHref = localeWithBaseHref.slice(start, end);
|
|
60
|
-
|
|
60
|
+
entryPoints[localeWithBaseHref] = `() => import('${importPath}')`;
|
|
61
61
|
}
|
|
62
62
|
}
|
|
63
63
|
else {
|
|
64
|
-
|
|
64
|
+
entryPoints[''] = `() => import('./${MAIN_SERVER_OUTPUT_FILENAME}')`;
|
|
65
65
|
}
|
|
66
66
|
const manifestContent = `
|
|
67
67
|
export default {
|
|
68
68
|
basePath: '${baseHref ?? '/'}',
|
|
69
|
-
entryPoints:
|
|
69
|
+
entryPoints: {
|
|
70
|
+
${Object.entries(entryPoints)
|
|
71
|
+
.map(([key, value]) => `'${key}': ${value}`)
|
|
72
|
+
.join(',\n ')}
|
|
73
|
+
},
|
|
70
74
|
};
|
|
71
|
-
|
|
75
|
+
`;
|
|
72
76
|
return manifestContent;
|
|
73
77
|
}
|
|
74
78
|
/**
|
|
@@ -89,29 +93,37 @@ export default {
|
|
|
89
93
|
* server-side rendering and routing.
|
|
90
94
|
* @param locale - An optional string representing the locale or language code to be used for
|
|
91
95
|
* the application, helping with localization and rendering content specific to the locale.
|
|
96
|
+
* @param baseHref - The base HREF for the application. This is used to set the base URL
|
|
97
|
+
* for all relative URLs in the application.
|
|
92
98
|
*
|
|
93
99
|
* @returns An object containing:
|
|
94
100
|
* - `manifestContent`: A string of the SSR manifest content.
|
|
95
101
|
* - `serverAssetsChunks`: An array of build output files containing the generated assets for the server.
|
|
96
102
|
*/
|
|
97
|
-
function generateAngularServerAppManifest(additionalHtmlOutputFiles, outputFiles, inlineCriticalCss, routes, locale) {
|
|
103
|
+
function generateAngularServerAppManifest(additionalHtmlOutputFiles, outputFiles, inlineCriticalCss, routes, locale, baseHref) {
|
|
98
104
|
const serverAssetsChunks = [];
|
|
99
|
-
const
|
|
105
|
+
const serverAssets = {};
|
|
100
106
|
for (const file of [...additionalHtmlOutputFiles.values(), ...outputFiles]) {
|
|
101
107
|
const extension = (0, node_path_1.extname)(file.path);
|
|
102
108
|
if (extension === '.html' || (inlineCriticalCss && extension === '.css')) {
|
|
103
109
|
const jsChunkFilePath = `assets-chunks/${file.path.replace(/[./]/g, '_')}.mjs`;
|
|
104
110
|
serverAssetsChunks.push((0, utils_1.createOutputFile)(jsChunkFilePath, `export default \`${escapeUnsafeChars(file.text)}\`;`, bundler_context_1.BuildOutputFileType.ServerApplication));
|
|
105
|
-
|
|
111
|
+
serverAssets[file.path] =
|
|
112
|
+
`{size: ${file.size}, hash: '${file.hash}', text: () => import('./${jsChunkFilePath}').then(m => m.default)}`;
|
|
106
113
|
}
|
|
107
114
|
}
|
|
108
115
|
const manifestContent = `
|
|
109
116
|
export default {
|
|
110
117
|
bootstrap: () => import('./main.server.mjs').then(m => m.default),
|
|
111
118
|
inlineCriticalCss: ${inlineCriticalCss},
|
|
119
|
+
baseHref: '${baseHref}',
|
|
120
|
+
locale: ${JSON.stringify(locale)},
|
|
112
121
|
routes: ${JSON.stringify(routes, undefined, 2)},
|
|
113
|
-
assets:
|
|
114
|
-
|
|
122
|
+
assets: {
|
|
123
|
+
${Object.entries(serverAssets)
|
|
124
|
+
.map(([key, value]) => `'${key}': ${value}`)
|
|
125
|
+
.join(',\n ')}
|
|
126
|
+
},
|
|
115
127
|
};
|
|
116
128
|
`;
|
|
117
129
|
return { manifestContent, serverAssetsChunks };
|
|
@@ -90,7 +90,7 @@ async function prerenderPages(workspaceRoot, baseHref, appShellOptions, prerende
|
|
|
90
90
|
};
|
|
91
91
|
}
|
|
92
92
|
// Render routes
|
|
93
|
-
const { errors: renderingErrors, output } = await renderPages(baseHref, sourcemap, serializableRouteTreeNodeForPrerender, maxThreads, workspaceRoot, outputFilesForWorker, assetsReversed,
|
|
93
|
+
const { errors: renderingErrors, output } = await renderPages(baseHref, sourcemap, serializableRouteTreeNodeForPrerender, maxThreads, workspaceRoot, outputFilesForWorker, assetsReversed, outputMode, appShellRoute ?? appShellOptions?.route);
|
|
94
94
|
errors.push(...renderingErrors);
|
|
95
95
|
return {
|
|
96
96
|
errors,
|
|
@@ -99,7 +99,7 @@ async function prerenderPages(workspaceRoot, baseHref, appShellOptions, prerende
|
|
|
99
99
|
serializableRouteTreeNode,
|
|
100
100
|
};
|
|
101
101
|
}
|
|
102
|
-
async function renderPages(baseHref, sourcemap, serializableRouteTreeNode, maxThreads, workspaceRoot, outputFilesForWorker, assetFilesForWorker,
|
|
102
|
+
async function renderPages(baseHref, sourcemap, serializableRouteTreeNode, maxThreads, workspaceRoot, outputFilesForWorker, assetFilesForWorker, outputMode, appShellRoute) {
|
|
103
103
|
const output = {};
|
|
104
104
|
const errors = [];
|
|
105
105
|
const workerExecArgv = [utils_1.IMPORT_EXEC_ARGV];
|
|
@@ -125,7 +125,7 @@ async function renderPages(baseHref, sourcemap, serializableRouteTreeNode, maxTh
|
|
|
125
125
|
for (const { route, redirectTo, renderMode } of serializableRouteTreeNode) {
|
|
126
126
|
// Remove the base href from the file output path.
|
|
127
127
|
const routeWithoutBaseHref = addTrailingSlash(route).startsWith(baseHrefWithLeadingSlash)
|
|
128
|
-
? addLeadingSlash(route.slice(baseHrefWithLeadingSlash.length
|
|
128
|
+
? addLeadingSlash(route.slice(baseHrefWithLeadingSlash.length))
|
|
129
129
|
: route;
|
|
130
130
|
const outPath = node_path_1.posix.join(removeLeadingSlash(routeWithoutBaseHref), 'index.html');
|
|
131
131
|
if (typeof redirectTo === 'string') {
|
|
@@ -21,7 +21,12 @@ async function extractRoutes() {
|
|
|
21
21
|
const serverURL = outputMode !== undefined && hasSsrEntry ? await (0, launch_server_1.launchServer)() : launch_server_1.DEFAULT_URL;
|
|
22
22
|
(0, fetch_patch_1.patchFetchToLoadInMemoryAssets)(serverURL);
|
|
23
23
|
const { ɵextractRoutesAndCreateRouteTree: extractRoutesAndCreateRouteTree } = await (0, load_esm_from_memory_1.loadEsmModuleFromMemory)('./main.server.mjs');
|
|
24
|
-
const { routeTree, appShellRoute, errors } = await extractRoutesAndCreateRouteTree(
|
|
24
|
+
const { routeTree, appShellRoute, errors } = await extractRoutesAndCreateRouteTree({
|
|
25
|
+
url: serverURL,
|
|
26
|
+
invokeGetPrerenderParams: outputMode !== undefined,
|
|
27
|
+
includePrerenderFallbackRoutes: outputMode === schema_1.OutputMode.Server,
|
|
28
|
+
signal: AbortSignal.timeout(30_000),
|
|
29
|
+
});
|
|
25
30
|
return {
|
|
26
31
|
errors,
|
|
27
32
|
appShellRoute,
|