@angular/build 18.0.0-rc.0 → 18.0.0-rc.2
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 +7 -7
- package/src/tools/esbuild/bundler-context.d.ts +1 -0
- package/src/tools/esbuild/bundler-context.js +14 -5
- package/src/tools/esbuild/index-html-generator.js +12 -1
- package/src/tools/sass/rebasing-importer.js +11 -3
- package/src/tools/sass/worker.js +3 -3
- package/src/utils/format-bytes.js +2 -2
- package/src/utils/normalize-cache.js +1 -1
- package/src/utils/server-rendering/fetch-patch.js +2 -1
- package/src/utils/server-rendering/render-page.js +8 -3
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@angular/build",
|
|
3
|
-
"version": "18.0.0-rc.
|
|
3
|
+
"version": "18.0.0-rc.2",
|
|
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.1800.0-rc.
|
|
26
|
+
"@angular-devkit/architect": "0.1800.0-rc.2",
|
|
27
27
|
"@babel/core": "7.24.5",
|
|
28
28
|
"@babel/helper-annotate-as-pure": "7.22.5",
|
|
29
29
|
"@babel/helper-split-export-declaration": "7.24.5",
|
|
@@ -31,7 +31,7 @@
|
|
|
31
31
|
"ansi-colors": "4.1.3",
|
|
32
32
|
"browserslist": "^4.23.0",
|
|
33
33
|
"critters": "0.0.22",
|
|
34
|
-
"esbuild": "0.
|
|
34
|
+
"esbuild": "0.21.1",
|
|
35
35
|
"fast-glob": "3.3.2",
|
|
36
36
|
"https-proxy-agent": "7.0.4",
|
|
37
37
|
"inquirer": "9.2.20",
|
|
@@ -42,10 +42,10 @@
|
|
|
42
42
|
"piscina": "4.4.0",
|
|
43
43
|
"parse5-html-rewriting-stream": "7.0.0",
|
|
44
44
|
"postcss": "8.4.38",
|
|
45
|
-
"sass": "1.
|
|
46
|
-
"semver": "7.6.
|
|
47
|
-
"undici": "6.
|
|
48
|
-
"vite": "5.2.
|
|
45
|
+
"sass": "1.77.0",
|
|
46
|
+
"semver": "7.6.1",
|
|
47
|
+
"undici": "6.16.0",
|
|
48
|
+
"vite": "5.2.11",
|
|
49
49
|
"watchpack": "2.4.1"
|
|
50
50
|
},
|
|
51
51
|
"peerDependencies": {
|
|
@@ -233,6 +233,7 @@ class BundlerContext {
|
|
|
233
233
|
type,
|
|
234
234
|
entrypoint: true,
|
|
235
235
|
serverFile: this.#platformIsServer,
|
|
236
|
+
depth: 0,
|
|
236
237
|
};
|
|
237
238
|
if (!this.initialFilter || this.initialFilter(record)) {
|
|
238
239
|
initialFiles.set(relativeFilePath, record);
|
|
@@ -241,10 +242,17 @@ class BundlerContext {
|
|
|
241
242
|
}
|
|
242
243
|
}
|
|
243
244
|
// Analyze for transitive initial files
|
|
244
|
-
const
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
245
|
+
const entriesToAnalyze = [...initialFiles];
|
|
246
|
+
let currentEntry;
|
|
247
|
+
while ((currentEntry = entriesToAnalyze.pop())) {
|
|
248
|
+
const [entryPath, entryRecord] = currentEntry;
|
|
249
|
+
for (const initialImport of result.metafile.outputs[entryPath].imports) {
|
|
250
|
+
const existingRecord = initialFiles.get(initialImport.path);
|
|
251
|
+
if (existingRecord) {
|
|
252
|
+
// Store the smallest value depth
|
|
253
|
+
if (existingRecord.depth > entryRecord.depth + 1) {
|
|
254
|
+
existingRecord.depth = entryRecord.depth + 1;
|
|
255
|
+
}
|
|
248
256
|
continue;
|
|
249
257
|
}
|
|
250
258
|
if (initialImport.kind === 'import-statement' || initialImport.kind === 'import-rule') {
|
|
@@ -253,12 +261,13 @@ class BundlerContext {
|
|
|
253
261
|
entrypoint: false,
|
|
254
262
|
external: initialImport.external,
|
|
255
263
|
serverFile: this.#platformIsServer,
|
|
264
|
+
depth: entryRecord.depth + 1,
|
|
256
265
|
};
|
|
257
266
|
if (!this.initialFilter || this.initialFilter(record)) {
|
|
258
267
|
initialFiles.set(initialImport.path, record);
|
|
259
268
|
}
|
|
260
269
|
if (!initialImport.external) {
|
|
261
|
-
|
|
270
|
+
entriesToAnalyze.push([initialImport.path, record]);
|
|
262
271
|
}
|
|
263
272
|
}
|
|
264
273
|
}
|
|
@@ -15,6 +15,11 @@ const node_assert_1 = __importDefault(require("node:assert"));
|
|
|
15
15
|
const node_path_1 = __importDefault(require("node:path"));
|
|
16
16
|
const index_html_generator_1 = require("../../utils/index-file/index-html-generator");
|
|
17
17
|
const bundler_context_1 = require("./bundler-context");
|
|
18
|
+
/**
|
|
19
|
+
* The maximum number of module preload link elements that should be added for
|
|
20
|
+
* initial scripts.
|
|
21
|
+
*/
|
|
22
|
+
const MODULE_PRELOAD_MAX = 3;
|
|
18
23
|
async function generateIndexHtml(initialFiles, outputFiles, buildOptions, lang) {
|
|
19
24
|
// Analyze metafile for initial link-based hints.
|
|
20
25
|
// Skip if the internal externalPackages option is enabled since this option requires
|
|
@@ -23,12 +28,18 @@ async function generateIndexHtml(initialFiles, outputFiles, buildOptions, lang)
|
|
|
23
28
|
const { indexHtmlOptions, externalPackages, optimizationOptions, crossOrigin, subresourceIntegrity, baseHref, } = buildOptions;
|
|
24
29
|
(0, node_assert_1.default)(indexHtmlOptions, 'indexHtmlOptions cannot be undefined.');
|
|
25
30
|
if (!externalPackages && indexHtmlOptions.preloadInitial) {
|
|
31
|
+
let modulePreloadCount = 0;
|
|
26
32
|
for (const [key, value] of initialFiles) {
|
|
27
33
|
if (value.entrypoint || value.serverFile) {
|
|
28
34
|
// Entry points are already referenced in the HTML
|
|
29
35
|
continue;
|
|
30
36
|
}
|
|
31
|
-
|
|
37
|
+
// Only add shallow preloads
|
|
38
|
+
if (value.depth > 1) {
|
|
39
|
+
continue;
|
|
40
|
+
}
|
|
41
|
+
if (value.type === 'script' && modulePreloadCount < MODULE_PRELOAD_MAX) {
|
|
42
|
+
modulePreloadCount++;
|
|
32
43
|
hints.push({ url: key, mode: 'modulepreload' });
|
|
33
44
|
}
|
|
34
45
|
else if (value.type === 'style') {
|
|
@@ -15,6 +15,7 @@ const magic_string_1 = __importDefault(require("magic-string"));
|
|
|
15
15
|
const node_fs_1 = require("node:fs");
|
|
16
16
|
const node_path_1 = require("node:path");
|
|
17
17
|
const node_url_1 = require("node:url");
|
|
18
|
+
const error_1 = require("../../utils/error");
|
|
18
19
|
const lexer_1 = require("./lexer");
|
|
19
20
|
/**
|
|
20
21
|
* Ensures that a bare specifier URL path that is intended to be treated as
|
|
@@ -195,8 +196,15 @@ class RelativeUrlRebasingImporter extends UrlRebasingImporter {
|
|
|
195
196
|
try {
|
|
196
197
|
entries = (0, node_fs_1.readdirSync)(directory, { withFileTypes: true });
|
|
197
198
|
}
|
|
198
|
-
catch {
|
|
199
|
-
|
|
199
|
+
catch (error) {
|
|
200
|
+
(0, error_1.assertIsError)(error);
|
|
201
|
+
// If the containing directory does not exist return null to indicate it cannot be resolved
|
|
202
|
+
if (error.code === 'ENOENT') {
|
|
203
|
+
return null;
|
|
204
|
+
}
|
|
205
|
+
throw new Error(`Error reading directory ["${directory}"] while resolving Sass import`, {
|
|
206
|
+
cause: error,
|
|
207
|
+
});
|
|
200
208
|
}
|
|
201
209
|
foundDefaults = [];
|
|
202
210
|
foundImports = [];
|
|
@@ -205,7 +213,7 @@ class RelativeUrlRebasingImporter extends UrlRebasingImporter {
|
|
|
205
213
|
let isDirectory;
|
|
206
214
|
let isFile;
|
|
207
215
|
if (entry.isSymbolicLink()) {
|
|
208
|
-
const stats = (0, node_fs_1.statSync)((0, node_path_1.join)(
|
|
216
|
+
const stats = (0, node_fs_1.statSync)((0, node_path_1.join)(directory, entry.name));
|
|
209
217
|
isDirectory = stats.isDirectory();
|
|
210
218
|
isFile = stats.isFile();
|
|
211
219
|
}
|
package/src/tools/sass/worker.js
CHANGED
|
@@ -38,14 +38,14 @@ node_worker_threads_1.parentPort.on('message', (message) => {
|
|
|
38
38
|
// functions combined with the shared memory `importSignal` and the Node.js
|
|
39
39
|
// `receiveMessageOnPort` function are used to ensure synchronous behavior.
|
|
40
40
|
const proxyImporter = {
|
|
41
|
-
findFileUrl: (url,
|
|
41
|
+
findFileUrl: (url, { fromImport, containingUrl }) => {
|
|
42
42
|
Atomics.store(importerSignal, 0, 0);
|
|
43
43
|
workerImporterPort.postMessage({
|
|
44
44
|
id,
|
|
45
45
|
url,
|
|
46
46
|
options: {
|
|
47
|
-
|
|
48
|
-
containingUrl:
|
|
47
|
+
fromImport,
|
|
48
|
+
containingUrl: containingUrl ? (0, node_url_1.fileURLToPath)(containingUrl) : null,
|
|
49
49
|
},
|
|
50
50
|
});
|
|
51
51
|
Atomics.wait(importerSignal, 0, 0);
|
|
@@ -13,8 +13,8 @@ function formatSize(size) {
|
|
|
13
13
|
return '0 bytes';
|
|
14
14
|
}
|
|
15
15
|
const abbreviations = ['bytes', 'kB', 'MB', 'GB'];
|
|
16
|
-
const index = Math.floor(Math.log(size) / Math.log(
|
|
17
|
-
const roundedSize = size / Math.pow(
|
|
16
|
+
const index = Math.floor(Math.log(size) / Math.log(1000));
|
|
17
|
+
const roundedSize = size / Math.pow(1000, index);
|
|
18
18
|
// bytes don't have a fraction
|
|
19
19
|
const fractionDigits = index === 0 ? 0 : 2;
|
|
20
20
|
return `${roundedSize.toFixed(fractionDigits)} ${abbreviations[index]}`;
|
|
@@ -10,7 +10,7 @@ Object.defineProperty(exports, "__esModule", { value: true });
|
|
|
10
10
|
exports.normalizeCacheOptions = void 0;
|
|
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 = '18.0.0-rc.
|
|
13
|
+
const VERSION = '18.0.0-rc.2';
|
|
14
14
|
function hasCacheMetadata(value) {
|
|
15
15
|
return (!!value &&
|
|
16
16
|
typeof value === 'object' &&
|
|
@@ -36,7 +36,8 @@ function patchFetchToLoadInMemoryAssets() {
|
|
|
36
36
|
else {
|
|
37
37
|
return originalFetch(input, init);
|
|
38
38
|
}
|
|
39
|
-
const {
|
|
39
|
+
const { protocol } = url;
|
|
40
|
+
const pathname = decodeURIComponent(url.pathname);
|
|
40
41
|
if (protocol !== RESOLVE_PROTOCOL || !assetFiles[pathname]) {
|
|
41
42
|
// Only handle relative requests or files that are in assets.
|
|
42
43
|
return originalFetch(input, init);
|
|
@@ -68,22 +68,27 @@ async function renderPage({ route, serverContext, document, inlineCriticalCss, o
|
|
|
68
68
|
},
|
|
69
69
|
},
|
|
70
70
|
];
|
|
71
|
-
let html;
|
|
72
71
|
(0, node_assert_1.default)(bootstrapAppFnOrModule, 'The file "./main.server.mjs" does not have a default export for an AppServerModule or a bootstrapping function.');
|
|
72
|
+
let renderAppPromise;
|
|
73
73
|
if (isBootstrapFn(bootstrapAppFnOrModule)) {
|
|
74
|
-
|
|
74
|
+
renderAppPromise = renderApplication(bootstrapAppFnOrModule, {
|
|
75
75
|
document,
|
|
76
76
|
url: route,
|
|
77
77
|
platformProviders,
|
|
78
78
|
});
|
|
79
79
|
}
|
|
80
80
|
else {
|
|
81
|
-
|
|
81
|
+
renderAppPromise = renderModule(bootstrapAppFnOrModule, {
|
|
82
82
|
document,
|
|
83
83
|
url: route,
|
|
84
84
|
extraProviders: platformProviders,
|
|
85
85
|
});
|
|
86
86
|
}
|
|
87
|
+
// The below should really handled by the framework!!!.
|
|
88
|
+
// See: https://github.com/angular/angular/issues/51549
|
|
89
|
+
let timer;
|
|
90
|
+
const renderingTimeout = new Promise((_, reject) => (timer = setTimeout(() => reject(new Error(`Page ${new URL(route, 'resolve://').pathname} did not render in 30 seconds.`)), 30_000)));
|
|
91
|
+
const html = await Promise.race([renderAppPromise, renderingTimeout]).finally(() => clearTimeout(timer));
|
|
87
92
|
if (inlineCriticalCss) {
|
|
88
93
|
const { InlineCriticalCssProcessor } = await Promise.resolve().then(() => __importStar(require('../../utils/index-file/inline-critical-css')));
|
|
89
94
|
const inlineCriticalCssProcessor = new InlineCriticalCssProcessor({
|