@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
|
@@ -12,12 +12,13 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
|
12
12
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
13
13
|
exports.createBrowserCodeBundleOptions = createBrowserCodeBundleOptions;
|
|
14
14
|
exports.createBrowserPolyfillBundleOptions = createBrowserPolyfillBundleOptions;
|
|
15
|
-
exports.createServerCodeBundleOptions = createServerCodeBundleOptions;
|
|
16
15
|
exports.createServerPolyfillBundleOptions = createServerPolyfillBundleOptions;
|
|
16
|
+
exports.createServerMainCodeBundleOptions = createServerMainCodeBundleOptions;
|
|
17
17
|
const node_assert_1 = __importDefault(require("node:assert"));
|
|
18
18
|
const node_crypto_1 = require("node:crypto");
|
|
19
19
|
const node_path_1 = require("node:path");
|
|
20
20
|
const environment_options_1 = require("../../utils/environment-options");
|
|
21
|
+
const manifest_1 = require("../../utils/server-rendering/manifest");
|
|
21
22
|
const compiler_plugin_1 = require("./angular/compiler-plugin");
|
|
22
23
|
const compiler_plugin_options_1 = require("./compiler-plugin-options");
|
|
23
24
|
const external_packages_plugin_1 = require("./external-packages-plugin");
|
|
@@ -110,29 +111,28 @@ function createBrowserPolyfillBundleOptions(options, target, sourceFileCache) {
|
|
|
110
111
|
// cannot be used with fully incremental bundling yet.
|
|
111
112
|
return hasTypeScriptEntries ? buildOptions : () => buildOptions;
|
|
112
113
|
}
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
114
|
+
function createServerPolyfillBundleOptions(options, target, sourceFileCache) {
|
|
115
|
+
const serverPolyfills = [];
|
|
116
|
+
const polyfillsFromConfig = new Set(options.polyfills);
|
|
117
|
+
if (!(0, utils_1.isZonelessApp)(options.polyfills)) {
|
|
118
|
+
serverPolyfills.push('zone.js/node');
|
|
119
|
+
}
|
|
120
|
+
if (polyfillsFromConfig.has('@angular/localize') ||
|
|
121
|
+
polyfillsFromConfig.has('@angular/localize/init')) {
|
|
122
|
+
serverPolyfills.push('@angular/localize/init');
|
|
123
|
+
}
|
|
124
|
+
serverPolyfills.push('@angular/platform-server/init');
|
|
125
|
+
const namespace = 'angular:polyfills-server';
|
|
126
|
+
const polyfillBundleOptions = getEsBuildCommonPolyfillsOptions({
|
|
127
|
+
...options,
|
|
128
|
+
polyfills: serverPolyfills,
|
|
129
|
+
}, namespace, false, sourceFileCache);
|
|
130
|
+
if (!polyfillBundleOptions) {
|
|
131
|
+
return;
|
|
130
132
|
}
|
|
131
|
-
const zoneless = (0, utils_1.isZonelessApp)(polyfills);
|
|
132
133
|
const buildOptions = {
|
|
133
|
-
...
|
|
134
|
+
...polyfillBundleOptions,
|
|
134
135
|
platform: 'node',
|
|
135
|
-
splitting: true,
|
|
136
136
|
outExtension: { '.js': '.mjs' },
|
|
137
137
|
// Note: `es2015` is needed for RxJS v6. If not specified, `module` would
|
|
138
138
|
// match and the ES5 distribution would be bundled and ends up breaking at
|
|
@@ -140,14 +140,45 @@ function createServerCodeBundleOptions(options, target, sourceFileCache) {
|
|
|
140
140
|
// More details: https://github.com/angular/angular-cli/issues/25405.
|
|
141
141
|
mainFields: ['es2020', 'es2015', 'module', 'main'],
|
|
142
142
|
entryNames: '[name]',
|
|
143
|
-
target,
|
|
144
143
|
banner: {
|
|
145
|
-
js:
|
|
144
|
+
js: [
|
|
145
|
+
// Note: Needed as esbuild does not provide require shims / proxy from ESModules.
|
|
146
|
+
// See: https://github.com/evanw/esbuild/issues/1921.
|
|
147
|
+
`import { createRequire } from 'node:module';`,
|
|
148
|
+
`globalThis['require'] ??= createRequire(import.meta.url);`,
|
|
149
|
+
].join('\n'),
|
|
150
|
+
},
|
|
151
|
+
target,
|
|
152
|
+
entryPoints: {
|
|
153
|
+
'polyfills.server': namespace,
|
|
146
154
|
},
|
|
155
|
+
};
|
|
156
|
+
return () => buildOptions;
|
|
157
|
+
}
|
|
158
|
+
function createServerMainCodeBundleOptions(options, target, sourceFileCache) {
|
|
159
|
+
const { serverEntryPoint: mainServerEntryPoint, workspaceRoot, externalPackages, ssrOptions, polyfills, } = options;
|
|
160
|
+
(0, node_assert_1.default)(mainServerEntryPoint, 'createServerCodeBundleOptions should not be called without a defined serverEntryPoint.');
|
|
161
|
+
const { pluginOptions, styleOptions } = (0, compiler_plugin_options_1.createCompilerPluginOptions)(options, target, sourceFileCache);
|
|
162
|
+
const mainServerNamespace = 'angular:main-server';
|
|
163
|
+
const mainServerInjectPolyfillsNamespace = 'angular:main-server-inject-polyfills';
|
|
164
|
+
const mainServerInjectManifestNamespace = 'angular:main-server-inject-manifest';
|
|
165
|
+
const zoneless = (0, utils_1.isZonelessApp)(polyfills);
|
|
166
|
+
const entryPoints = {
|
|
167
|
+
'main.server': mainServerNamespace,
|
|
168
|
+
};
|
|
169
|
+
const ssrEntryPoint = ssrOptions?.entry;
|
|
170
|
+
if (ssrEntryPoint) {
|
|
171
|
+
// Old behavior: 'server.ts' was bundled together with the SSR (Server-Side Rendering) code.
|
|
172
|
+
// This approach combined server-side logic and rendering into a single bundle.
|
|
173
|
+
entryPoints['server'] = ssrEntryPoint;
|
|
174
|
+
}
|
|
175
|
+
const buildOptions = {
|
|
176
|
+
...getEsBuildServerCommonOptions(options),
|
|
177
|
+
target,
|
|
178
|
+
inject: [mainServerInjectPolyfillsNamespace, mainServerInjectManifestNamespace],
|
|
147
179
|
entryPoints,
|
|
148
180
|
supported: (0, utils_1.getFeatureSupport)(target, zoneless),
|
|
149
181
|
plugins: [
|
|
150
|
-
(0, loader_import_attribute_plugin_1.createLoaderImportAttributePlugin)(),
|
|
151
182
|
(0, wasm_plugin_1.createWasmPlugin)({ allowAsync: zoneless, cache: sourceFileCache?.loadResultCache }),
|
|
152
183
|
(0, sourcemap_ignorelist_plugin_1.createSourcemapIgnorelistPlugin)(),
|
|
153
184
|
(0, compiler_plugin_1.createCompilerPlugin)(
|
|
@@ -164,20 +195,49 @@ function createServerCodeBundleOptions(options, target, sourceFileCache) {
|
|
|
164
195
|
else {
|
|
165
196
|
buildOptions.plugins.push((0, rxjs_esm_resolution_plugin_1.createRxjsEsmResolutionPlugin)());
|
|
166
197
|
}
|
|
198
|
+
// Mark manifest and polyfills file as external as these are generated by a different bundle step.
|
|
199
|
+
(buildOptions.external ??= []).push(...utils_1.SERVER_GENERATED_EXTERNALS);
|
|
167
200
|
buildOptions.plugins.push((0, virtual_module_plugin_1.createVirtualModulePlugin)({
|
|
201
|
+
namespace: mainServerInjectPolyfillsNamespace,
|
|
202
|
+
cache: sourceFileCache?.loadResultCache,
|
|
203
|
+
loadContent: () => ({
|
|
204
|
+
contents: `import './polyfills.server.mjs';`,
|
|
205
|
+
loader: 'js',
|
|
206
|
+
resolveDir: workspaceRoot,
|
|
207
|
+
}),
|
|
208
|
+
}), (0, virtual_module_plugin_1.createVirtualModulePlugin)({
|
|
209
|
+
namespace: mainServerInjectManifestNamespace,
|
|
210
|
+
cache: sourceFileCache?.loadResultCache,
|
|
211
|
+
loadContent: async () => {
|
|
212
|
+
const contents = [
|
|
213
|
+
// Configure `@angular/ssr` manifest.
|
|
214
|
+
`import manifest from './${manifest_1.SERVER_APP_MANIFEST_FILENAME}';`,
|
|
215
|
+
`import { ɵsetAngularAppManifest } from '@angular/ssr';`,
|
|
216
|
+
`ɵsetAngularAppManifest(manifest);`,
|
|
217
|
+
];
|
|
218
|
+
return {
|
|
219
|
+
contents: contents.join('\n'),
|
|
220
|
+
loader: 'js',
|
|
221
|
+
resolveDir: workspaceRoot,
|
|
222
|
+
};
|
|
223
|
+
},
|
|
224
|
+
}), (0, virtual_module_plugin_1.createVirtualModulePlugin)({
|
|
168
225
|
namespace: mainServerNamespace,
|
|
169
226
|
cache: sourceFileCache?.loadResultCache,
|
|
170
227
|
loadContent: async () => {
|
|
228
|
+
const mainServerEntryPointJsImport = entryFileToWorkspaceRelative(workspaceRoot, mainServerEntryPoint);
|
|
171
229
|
const contents = [
|
|
172
|
-
|
|
173
|
-
`export {
|
|
230
|
+
// Re-export all symbols including default export from 'main.server.ts'
|
|
231
|
+
`export { default } from '${mainServerEntryPointJsImport}';`,
|
|
232
|
+
`export * from '${mainServerEntryPointJsImport}';`,
|
|
233
|
+
// Add @angular/ssr exports
|
|
234
|
+
`export {
|
|
235
|
+
ɵServerRenderContext,
|
|
236
|
+
ɵdestroyAngularServerApp,
|
|
237
|
+
ɵextractRoutesAndCreateRouteTree,
|
|
238
|
+
ɵgetOrCreateAngularServerApp,
|
|
239
|
+
} from '@angular/ssr';`,
|
|
174
240
|
];
|
|
175
|
-
if (watch) {
|
|
176
|
-
contents.push(`export { ɵresetCompiledComponents } from '@angular/core';`);
|
|
177
|
-
}
|
|
178
|
-
if (prerenderOptions?.discoverRoutes) {
|
|
179
|
-
contents.push(`export { ɵgetRoutesFromAngularRouterConfig } from '@angular/ssr';`);
|
|
180
|
-
}
|
|
181
241
|
return {
|
|
182
242
|
contents: contents.join('\n'),
|
|
183
243
|
loader: 'js',
|
|
@@ -190,27 +250,9 @@ function createServerCodeBundleOptions(options, target, sourceFileCache) {
|
|
|
190
250
|
}
|
|
191
251
|
return buildOptions;
|
|
192
252
|
}
|
|
193
|
-
function
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
if (!(0, utils_1.isZonelessApp)(options.polyfills)) {
|
|
197
|
-
serverPolyfills.push('zone.js/node');
|
|
198
|
-
}
|
|
199
|
-
if (polyfillsFromConfig.has('@angular/localize') ||
|
|
200
|
-
polyfillsFromConfig.has('@angular/localize/init')) {
|
|
201
|
-
serverPolyfills.push('@angular/localize/init');
|
|
202
|
-
}
|
|
203
|
-
serverPolyfills.push('@angular/platform-server/init');
|
|
204
|
-
const namespace = 'angular:polyfills-server';
|
|
205
|
-
const polyfillBundleOptions = getEsBuildCommonPolyfillsOptions({
|
|
206
|
-
...options,
|
|
207
|
-
polyfills: serverPolyfills,
|
|
208
|
-
}, namespace, false, sourceFileCache);
|
|
209
|
-
if (!polyfillBundleOptions) {
|
|
210
|
-
return;
|
|
211
|
-
}
|
|
212
|
-
const buildOptions = {
|
|
213
|
-
...polyfillBundleOptions,
|
|
253
|
+
function getEsBuildServerCommonOptions(options) {
|
|
254
|
+
return {
|
|
255
|
+
...getEsBuildCommonOptions(options),
|
|
214
256
|
platform: 'node',
|
|
215
257
|
outExtension: { '.js': '.mjs' },
|
|
216
258
|
// Note: `es2015` is needed for RxJS v6. If not specified, `module` would
|
|
@@ -219,31 +261,18 @@ function createServerPolyfillBundleOptions(options, target, sourceFileCache) {
|
|
|
219
261
|
// More details: https://github.com/angular/angular-cli/issues/25405.
|
|
220
262
|
mainFields: ['es2020', 'es2015', 'module', 'main'],
|
|
221
263
|
entryNames: '[name]',
|
|
222
|
-
banner: {
|
|
223
|
-
js: [
|
|
224
|
-
// Note: Needed as esbuild does not provide require shims / proxy from ESModules.
|
|
225
|
-
// See: https://github.com/evanw/esbuild/issues/1921.
|
|
226
|
-
`import { createRequire } from 'node:module';`,
|
|
227
|
-
`globalThis['require'] ??= createRequire(import.meta.url);`,
|
|
228
|
-
].join('\n'),
|
|
229
|
-
},
|
|
230
|
-
target,
|
|
231
|
-
entryPoints: {
|
|
232
|
-
'polyfills.server': namespace,
|
|
233
|
-
},
|
|
234
264
|
};
|
|
235
|
-
return () => buildOptions;
|
|
236
265
|
}
|
|
237
266
|
function getEsBuildCommonOptions(options) {
|
|
238
|
-
const { workspaceRoot, outExtension, optimizationOptions, sourcemapOptions, tsconfig, externalDependencies, outputNames, preserveSymlinks, jit, loaderExtensions, jsonLogs, } = options;
|
|
267
|
+
const { workspaceRoot, outExtension, optimizationOptions, sourcemapOptions, tsconfig, externalDependencies, outputNames, preserveSymlinks, jit, loaderExtensions, jsonLogs, i18nOptions, } = options;
|
|
239
268
|
// Ensure unique hashes for i18n translation changes when using post-process inlining.
|
|
240
269
|
// This hash value is added as a footer to each file and ensures that the output file names (with hashes)
|
|
241
270
|
// change when translation files have changed. If this is not done the post processed files may have
|
|
242
271
|
// different content but would retain identical production file names which would lead to browser caching problems.
|
|
243
272
|
let footer;
|
|
244
|
-
if (
|
|
273
|
+
if (i18nOptions.shouldInline) {
|
|
245
274
|
// Update file hashes to include translation file content
|
|
246
|
-
const i18nHash = Object.values(
|
|
275
|
+
const i18nHash = Object.values(i18nOptions.locales).reduce((data, locale) => data + locale.files.map((file) => file.integrity || '').join('|'), '');
|
|
247
276
|
footer = { js: `/**i18n:${(0, node_crypto_1.createHash)('sha256').update(i18nHash).digest('hex')}*/` };
|
|
248
277
|
}
|
|
249
278
|
return {
|
|
@@ -267,7 +296,7 @@ function getEsBuildCommonOptions(options) {
|
|
|
267
296
|
splitting: true,
|
|
268
297
|
chunkNames: options.namedChunks ? '[name]-[hash]' : 'chunk-[hash]',
|
|
269
298
|
tsconfig,
|
|
270
|
-
external: externalDependencies,
|
|
299
|
+
external: externalDependencies ? [...externalDependencies] : undefined,
|
|
271
300
|
write: false,
|
|
272
301
|
preserveSymlinks,
|
|
273
302
|
define: {
|
|
@@ -360,3 +389,9 @@ function getEsBuildCommonPolyfillsOptions(options, namespace, tryToResolvePolyfi
|
|
|
360
389
|
}));
|
|
361
390
|
return buildOptions;
|
|
362
391
|
}
|
|
392
|
+
function entryFileToWorkspaceRelative(workspaceRoot, entryFile) {
|
|
393
|
+
return ('./' +
|
|
394
|
+
(0, node_path_1.relative)(workspaceRoot, entryFile)
|
|
395
|
+
.replace(/.[mc]?ts$/, '')
|
|
396
|
+
.replace(/\\/g, '/'));
|
|
397
|
+
}
|
|
@@ -138,6 +138,7 @@ class BundlerContext {
|
|
|
138
138
|
}
|
|
139
139
|
return result;
|
|
140
140
|
}
|
|
141
|
+
// eslint-disable-next-line max-lines-per-function
|
|
141
142
|
async #performBundle() {
|
|
142
143
|
// Create esbuild options if not present
|
|
143
144
|
if (this.#esbuildOptions === undefined) {
|
|
@@ -165,12 +166,6 @@ class BundlerContext {
|
|
|
165
166
|
// For non-incremental builds, perform a single build
|
|
166
167
|
result = await (0, esbuild_1.build)(this.#esbuildOptions);
|
|
167
168
|
}
|
|
168
|
-
if (this.#platformIsServer) {
|
|
169
|
-
for (const entry of Object.values(result.metafile.outputs)) {
|
|
170
|
-
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
171
|
-
entry['ng-platform-server'] = true;
|
|
172
|
-
}
|
|
173
|
-
}
|
|
174
169
|
}
|
|
175
170
|
catch (failure) {
|
|
176
171
|
// Build failures will throw an exception which contains errors/warnings
|
|
@@ -280,6 +275,7 @@ class BundlerContext {
|
|
|
280
275
|
for (const { imports } of Object.values(result.metafile.outputs)) {
|
|
281
276
|
for (const importData of imports) {
|
|
282
277
|
if (!importData.external ||
|
|
278
|
+
utils_1.SERVER_GENERATED_EXTERNALS.has(importData.path) ||
|
|
283
279
|
(importData.kind !== 'import-statement' &&
|
|
284
280
|
importData.kind !== 'dynamic-import' &&
|
|
285
281
|
importData.kind !== 'require-call')) {
|
|
@@ -295,13 +291,21 @@ class BundlerContext {
|
|
|
295
291
|
if (!/\.([cm]?js|css|wasm)(\.map)?$/i.test(file.path)) {
|
|
296
292
|
fileType = BuildOutputFileType.Media;
|
|
297
293
|
}
|
|
294
|
+
else if (this.#platformIsServer) {
|
|
295
|
+
fileType = BuildOutputFileType.Server;
|
|
296
|
+
}
|
|
298
297
|
else {
|
|
299
|
-
fileType =
|
|
300
|
-
? BuildOutputFileType.Server
|
|
301
|
-
: BuildOutputFileType.Browser;
|
|
298
|
+
fileType = BuildOutputFileType.Browser;
|
|
302
299
|
}
|
|
303
300
|
return (0, utils_1.convertOutputFile)(file, fileType);
|
|
304
301
|
});
|
|
302
|
+
let externalConfiguration = this.#esbuildOptions.external;
|
|
303
|
+
if (this.#platformIsServer && externalConfiguration) {
|
|
304
|
+
externalConfiguration = externalConfiguration.filter((dep) => !utils_1.SERVER_GENERATED_EXTERNALS.has(dep));
|
|
305
|
+
if (!externalConfiguration.length) {
|
|
306
|
+
externalConfiguration = undefined;
|
|
307
|
+
}
|
|
308
|
+
}
|
|
305
309
|
// Return the successful build results
|
|
306
310
|
return {
|
|
307
311
|
...result,
|
|
@@ -310,7 +314,7 @@ class BundlerContext {
|
|
|
310
314
|
externalImports: {
|
|
311
315
|
[this.#platformIsServer ? 'server' : 'browser']: externalImports,
|
|
312
316
|
},
|
|
313
|
-
externalConfiguration
|
|
317
|
+
externalConfiguration,
|
|
314
318
|
errors: undefined,
|
|
315
319
|
};
|
|
316
320
|
}
|
|
@@ -84,5 +84,5 @@ export declare class MemoryCache<V> extends Cache<V, Map<string, V>> {
|
|
|
84
84
|
* Provides all the values currently present in the cache instance.
|
|
85
85
|
* @returns An iterable of all values in the cache.
|
|
86
86
|
*/
|
|
87
|
-
values():
|
|
87
|
+
values(): MapIterator<V>;
|
|
88
88
|
}
|
|
@@ -13,6 +13,7 @@ Object.defineProperty(exports, "__esModule", { value: true });
|
|
|
13
13
|
exports.JavaScriptTransformer = void 0;
|
|
14
14
|
const node_crypto_1 = require("node:crypto");
|
|
15
15
|
const promises_1 = require("node:fs/promises");
|
|
16
|
+
const node_module_1 = require("node:module");
|
|
16
17
|
const piscina_1 = __importDefault(require("piscina"));
|
|
17
18
|
/**
|
|
18
19
|
* A class that performs transformation of JavaScript files and raw data.
|
|
@@ -48,6 +49,11 @@ class JavaScriptTransformer {
|
|
|
48
49
|
// Shutdown idle threads after 1 second of inactivity
|
|
49
50
|
idleTimeout: 1000,
|
|
50
51
|
recordTiming: false,
|
|
52
|
+
env: {
|
|
53
|
+
...process.env,
|
|
54
|
+
// Enable compile code caching if enabled for the main process (only exists on Node.js v22.8+)
|
|
55
|
+
'NODE_COMPILE_CACHE': (0, node_module_1.getCompileCacheDir)?.(),
|
|
56
|
+
},
|
|
51
57
|
});
|
|
52
58
|
return this.#workerPool;
|
|
53
59
|
}
|
|
@@ -47,3 +47,12 @@ export declare function logMessages(logger: BuilderContext['logger'], executionR
|
|
|
47
47
|
*/
|
|
48
48
|
export declare function isZonelessApp(polyfills: string[] | undefined): boolean;
|
|
49
49
|
export declare function getEntryPointName(entryPoint: string): string;
|
|
50
|
+
/**
|
|
51
|
+
* A set of server-generated dependencies that are treated as external.
|
|
52
|
+
*
|
|
53
|
+
* These dependencies are marked as external because they are produced by a
|
|
54
|
+
* separate bundling process and are not included in the primary bundle. This
|
|
55
|
+
* ensures that these generated files are resolved from an external source rather
|
|
56
|
+
* than being part of the main bundle.
|
|
57
|
+
*/
|
|
58
|
+
export declare const SERVER_GENERATED_EXTERNALS: Set<string>;
|
|
@@ -7,6 +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.SERVER_GENERATED_EXTERNALS = void 0;
|
|
10
11
|
exports.logBuildStats = logBuildStats;
|
|
11
12
|
exports.getChunkNameFromMetafile = getChunkNameFromMetafile;
|
|
12
13
|
exports.calculateEstimatedTransferSizes = calculateEstimatedTransferSizes;
|
|
@@ -29,6 +30,7 @@ const node_path_1 = require("node:path");
|
|
|
29
30
|
const node_url_1 = require("node:url");
|
|
30
31
|
const node_zlib_1 = require("node:zlib");
|
|
31
32
|
const semver_1 = require("semver");
|
|
33
|
+
const manifest_1 = require("../../utils/server-rendering/manifest");
|
|
32
34
|
const stats_table_1 = require("../../utils/stats-table");
|
|
33
35
|
const bundler_context_1 = require("./bundler-context");
|
|
34
36
|
function logBuildStats(metafile, outputFiles, initial, budgetFailures, colors, changedFiles, estimatedTransferSizes, ssrOutputEnabled, verbose) {
|
|
@@ -385,3 +387,15 @@ function getEntryPointName(entryPoint) {
|
|
|
385
387
|
.replace(/\.[cm]?[jt]s$/, '')
|
|
386
388
|
.replace(/[\\/.]/g, '-');
|
|
387
389
|
}
|
|
390
|
+
/**
|
|
391
|
+
* A set of server-generated dependencies that are treated as external.
|
|
392
|
+
*
|
|
393
|
+
* These dependencies are marked as external because they are produced by a
|
|
394
|
+
* separate bundling process and are not included in the primary bundle. This
|
|
395
|
+
* ensures that these generated files are resolved from an external source rather
|
|
396
|
+
* than being part of the main bundle.
|
|
397
|
+
*/
|
|
398
|
+
exports.SERVER_GENERATED_EXTERNALS = new Set([
|
|
399
|
+
'./polyfills.server.mjs',
|
|
400
|
+
'./' + manifest_1.SERVER_APP_MANIFEST_FILENAME,
|
|
401
|
+
]);
|
|
@@ -34,17 +34,22 @@ var __disposeResources = (this && this.__disposeResources) || (function (Suppres
|
|
|
34
34
|
env.error = env.hasError ? new SuppressedError(e, env.error, "An error was suppressed during disposal.") : e;
|
|
35
35
|
env.hasError = true;
|
|
36
36
|
}
|
|
37
|
+
var r, s = 0;
|
|
37
38
|
function next() {
|
|
38
|
-
while (env.stack.
|
|
39
|
-
var rec = env.stack.pop();
|
|
39
|
+
while (r = env.stack.pop()) {
|
|
40
40
|
try {
|
|
41
|
-
|
|
42
|
-
if (
|
|
41
|
+
if (!r.async && s === 1) return s = 0, env.stack.push(r), Promise.resolve().then(next);
|
|
42
|
+
if (r.dispose) {
|
|
43
|
+
var result = r.dispose.call(r.value);
|
|
44
|
+
if (r.async) return s |= 2, Promise.resolve(result).then(next, function(e) { fail(e); return next(); });
|
|
45
|
+
}
|
|
46
|
+
else s |= 1;
|
|
43
47
|
}
|
|
44
48
|
catch (e) {
|
|
45
49
|
fail(e);
|
|
46
50
|
}
|
|
47
51
|
}
|
|
52
|
+
if (s === 1) return env.hasError ? Promise.reject(env.error) : Promise.resolve();
|
|
48
53
|
if (env.hasError) throw env.error;
|
|
49
54
|
}
|
|
50
55
|
return next();
|
|
@@ -59,6 +64,7 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
|
59
64
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
60
65
|
exports.SassWorkerImplementation = void 0;
|
|
61
66
|
const node_assert_1 = __importDefault(require("node:assert"));
|
|
67
|
+
const node_module_1 = require("node:module");
|
|
62
68
|
const node_url_1 = require("node:url");
|
|
63
69
|
const node_worker_threads_1 = require("node:worker_threads");
|
|
64
70
|
const piscina_1 = require("piscina");
|
|
@@ -95,6 +101,11 @@ class SassWorkerImplementation {
|
|
|
95
101
|
// Shutdown idle threads after 1 second of inactivity
|
|
96
102
|
idleTimeout: 1000,
|
|
97
103
|
recordTiming: false,
|
|
104
|
+
env: {
|
|
105
|
+
...process.env,
|
|
106
|
+
// Enable compile code caching if enabled for the main process (only exists on Node.js v22.8+)
|
|
107
|
+
'NODE_COMPILE_CACHE': (0, node_module_1.getCompileCacheDir)?.(),
|
|
108
|
+
},
|
|
98
109
|
});
|
|
99
110
|
return this.#workerPool;
|
|
100
111
|
}
|
|
@@ -5,6 +5,7 @@
|
|
|
5
5
|
* Use of this source code is governed by an MIT-style license that can be
|
|
6
6
|
* found in the LICENSE file at https://angular.dev/license
|
|
7
7
|
*/
|
|
8
|
+
import { RawSourceMap } from '@ampproject/remapping';
|
|
8
9
|
import { MessagePort } from 'node:worker_threads';
|
|
9
10
|
import { SourceSpan, StringOptions } from 'sass';
|
|
10
11
|
import type { SerializableWarningMessage } from './sass-service';
|
|
@@ -38,45 +39,25 @@ interface RenderRequestMessage {
|
|
|
38
39
|
*/
|
|
39
40
|
rebase: boolean;
|
|
40
41
|
}
|
|
41
|
-
|
|
42
|
+
interface RenderResult {
|
|
42
43
|
warnings: SerializableWarningMessage[] | undefined;
|
|
43
44
|
result: {
|
|
44
|
-
loadedUrls: string[];
|
|
45
45
|
css: string;
|
|
46
|
-
|
|
46
|
+
loadedUrls: string[];
|
|
47
|
+
sourceMap?: RawSourceMap;
|
|
47
48
|
};
|
|
48
|
-
|
|
49
|
-
|
|
49
|
+
}
|
|
50
|
+
interface RenderError {
|
|
50
51
|
warnings: SerializableWarningMessage[] | undefined;
|
|
51
52
|
error: {
|
|
52
|
-
|
|
53
|
+
message: string;
|
|
54
|
+
stack?: string;
|
|
55
|
+
span?: Omit<SourceSpan, 'url'> & {
|
|
53
56
|
url?: string;
|
|
54
57
|
};
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
sassMessage: string;
|
|
58
|
-
sassStack: string;
|
|
59
|
-
};
|
|
60
|
-
result?: undefined;
|
|
61
|
-
} | {
|
|
62
|
-
warnings: SerializableWarningMessage[] | undefined;
|
|
63
|
-
error: {
|
|
64
|
-
message: string;
|
|
65
|
-
stack: string | undefined;
|
|
66
|
-
span?: undefined;
|
|
67
|
-
sassMessage?: undefined;
|
|
68
|
-
sassStack?: undefined;
|
|
58
|
+
sassMessage?: string;
|
|
59
|
+
sassStack?: string;
|
|
69
60
|
};
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
warnings: SerializableWarningMessage[] | undefined;
|
|
73
|
-
error: {
|
|
74
|
-
message: string;
|
|
75
|
-
span?: undefined;
|
|
76
|
-
stack?: undefined;
|
|
77
|
-
sassMessage?: undefined;
|
|
78
|
-
sassStack?: undefined;
|
|
79
|
-
};
|
|
80
|
-
result?: undefined;
|
|
81
|
-
}>;
|
|
61
|
+
}
|
|
62
|
+
export default function renderSassStylesheet(request: RenderRequestMessage): Promise<RenderResult | RenderError>;
|
|
82
63
|
export {};
|
package/src/tools/sass/worker.js
CHANGED
|
@@ -95,6 +95,7 @@ async function renderSassStylesheet(request) {
|
|
|
95
95
|
warnings,
|
|
96
96
|
result: {
|
|
97
97
|
...result,
|
|
98
|
+
sourceMap: result.sourceMap,
|
|
98
99
|
// URL is not serializable so to convert to string here and back to URL in the parent.
|
|
99
100
|
loadedUrls: result.loadedUrls.map((p) => (0, node_url_1.fileURLToPath)(p)),
|
|
100
101
|
},
|
|
@@ -82,10 +82,10 @@ function createAngularMemoryPlugin(options) {
|
|
|
82
82
|
// Returning a function, installs middleware after the main transform middleware but
|
|
83
83
|
// before the built-in HTML middleware
|
|
84
84
|
return () => {
|
|
85
|
-
server.middlewares.use(middlewares_1.angularHtmlFallbackMiddleware);
|
|
86
85
|
if (ssr) {
|
|
87
|
-
server.middlewares.use((0, middlewares_1.createAngularSSRMiddleware)(server,
|
|
86
|
+
server.middlewares.use((0, middlewares_1.createAngularSSRMiddleware)(server, indexHtmlTransformer));
|
|
88
87
|
}
|
|
88
|
+
server.middlewares.use(middlewares_1.angularHtmlFallbackMiddleware);
|
|
89
89
|
server.middlewares.use((0, middlewares_1.createAngularIndexHtmlMiddleware)(server, outputFiles, indexHtmlTransformer));
|
|
90
90
|
};
|
|
91
91
|
},
|
|
@@ -6,7 +6,4 @@
|
|
|
6
6
|
* found in the LICENSE file at https://angular.dev/license
|
|
7
7
|
*/
|
|
8
8
|
import type { Connect, ViteDevServer } from 'vite';
|
|
9
|
-
export declare function createAngularSSRMiddleware(server: ViteDevServer,
|
|
10
|
-
contents: Uint8Array;
|
|
11
|
-
servable: boolean;
|
|
12
|
-
}>, indexHtmlTransformer?: (content: string) => Promise<string>): Connect.NextHandleFunction;
|
|
9
|
+
export declare function createAngularSSRMiddleware(server: ViteDevServer, indexHtmlTransformer?: (content: string) => Promise<string>): Connect.NextHandleFunction;
|
|
@@ -8,49 +8,36 @@
|
|
|
8
8
|
*/
|
|
9
9
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
10
10
|
exports.createAngularSSRMiddleware = createAngularSSRMiddleware;
|
|
11
|
-
const render_page_1 = require("../../../utils/server-rendering/render-page");
|
|
12
11
|
const utils_1 = require("../utils");
|
|
13
|
-
function createAngularSSRMiddleware(server,
|
|
12
|
+
function createAngularSSRMiddleware(server, indexHtmlTransformer) {
|
|
13
|
+
let cachedAngularServerApp;
|
|
14
14
|
return function (req, res, next) {
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
// Skip if path is not defined.
|
|
18
|
-
!url ||
|
|
19
|
-
// Skip if path is like a file.
|
|
20
|
-
// NOTE: We use a mime type lookup to mitigate against matching requests like: /browse/pl.0ef59752c0cd457dbf1391f08cbd936f
|
|
21
|
-
(0, utils_1.lookupMimeTypeFromRequest)(url)) {
|
|
22
|
-
next();
|
|
23
|
-
return;
|
|
15
|
+
if (req.url === undefined) {
|
|
16
|
+
return next();
|
|
24
17
|
}
|
|
25
|
-
const
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
18
|
+
const resolvedUrls = server.resolvedUrls;
|
|
19
|
+
const baseUrl = resolvedUrls?.local[0] ?? resolvedUrls?.network[0];
|
|
20
|
+
const url = new URL(req.url, baseUrl);
|
|
21
|
+
(async () => {
|
|
22
|
+
const { ɵgetOrCreateAngularServerApp } = (await server.ssrLoadModule('/main.server.mjs'));
|
|
23
|
+
const angularServerApp = ɵgetOrCreateAngularServerApp();
|
|
24
|
+
// Only Add the transform hook only if it's a different instance.
|
|
25
|
+
if (cachedAngularServerApp !== angularServerApp) {
|
|
26
|
+
angularServerApp.hooks.on('html:transform:pre', async ({ html }) => {
|
|
27
|
+
const processedHtml = await server.transformIndexHtml(url.pathname, html);
|
|
28
|
+
return indexHtmlTransformer?.(processedHtml) ?? processedHtml;
|
|
29
|
+
});
|
|
30
|
+
cachedAngularServerApp = angularServerApp;
|
|
31
|
+
}
|
|
32
|
+
const response = await angularServerApp.render(new Request(url, { signal: AbortSignal.timeout(30_000) }), undefined);
|
|
33
|
+
return response?.text();
|
|
34
|
+
})()
|
|
35
|
+
.then((content) => {
|
|
36
|
+
if (typeof content !== 'string') {
|
|
37
|
+
return next();
|
|
37
38
|
}
|
|
38
|
-
const { content: ssrContent } = await (0, render_page_1.renderPage)({
|
|
39
|
-
document: processedHtml,
|
|
40
|
-
route: new URL(req.originalUrl ?? '/', baseUrl).toString(),
|
|
41
|
-
serverContext: 'ssr',
|
|
42
|
-
loadBundle: (uri) =>
|
|
43
|
-
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
44
|
-
server.ssrLoadModule(uri.slice(1)),
|
|
45
|
-
// Files here are only needed for critical CSS inlining.
|
|
46
|
-
outputFiles: {},
|
|
47
|
-
// TODO: add support for critical css inlining.
|
|
48
|
-
inlineCriticalCss: false,
|
|
49
|
-
});
|
|
50
|
-
res.setHeader('Content-Type', 'text/html');
|
|
51
|
-
res.setHeader('Cache-Control', 'no-cache');
|
|
52
39
|
(0, utils_1.appendServerConfiguredHeaders)(server, res);
|
|
53
|
-
res.end(
|
|
40
|
+
res.end(content);
|
|
54
41
|
})
|
|
55
42
|
.catch((error) => next(error));
|
|
56
43
|
};
|
package/src/typings.d.ts
CHANGED
|
@@ -17,3 +17,10 @@
|
|
|
17
17
|
declare module 'esbuild' {
|
|
18
18
|
export * from 'esbuild-wasm';
|
|
19
19
|
}
|
|
20
|
+
|
|
21
|
+
/**
|
|
22
|
+
* Augment the Node.js module builtin types to support the v22.8+ compile cache functions
|
|
23
|
+
*/
|
|
24
|
+
declare module 'node:module' {
|
|
25
|
+
function getCompileCacheDir(): string | undefined;
|
|
26
|
+
}
|
|
@@ -10,7 +10,7 @@ Object.defineProperty(exports, "__esModule", { value: true });
|
|
|
10
10
|
exports.normalizeCacheOptions = normalizeCacheOptions;
|
|
11
11
|
const node_path_1 = require("node:path");
|
|
12
12
|
/** Version placeholder is replaced during the build process with actual package version */
|
|
13
|
-
const VERSION = '19.0.0-next.
|
|
13
|
+
const VERSION = '19.0.0-next.4';
|
|
14
14
|
function hasCacheMetadata(value) {
|
|
15
15
|
return (!!value &&
|
|
16
16
|
typeof value === 'object' &&
|