@webjsdev/server 0.9.0 → 0.10.0
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/README.md +4 -1
- package/index.d.ts +427 -109
- package/index.js +8 -4
- package/package.json +3 -3
- package/src/action-flash.js +185 -0
- package/src/action-params.js +156 -0
- package/src/action-route.js +8 -9
- package/src/action-seed.js +44 -5
- package/src/actions.js +96 -14
- package/src/api.js +67 -10
- package/src/app-layout.js +133 -0
- package/src/asset-hash.js +82 -49
- package/src/auth.js +612 -108
- package/src/browser-entries.js +2 -17
- package/src/build-epoch.js +1 -1
- package/src/cache-tags.js +5 -1
- package/src/check/rules-actions.js +37 -1
- package/src/check/rules-components.js +114 -40
- package/src/check/rules-imports.js +175 -4
- package/src/check/rules-route-modules.js +200 -0
- package/src/check/rules-routes.js +55 -0
- package/src/check/rules-routing.js +143 -95
- package/src/check/rules-typescript.js +24 -2
- package/src/check/rules.js +104 -9
- package/src/check/runner-support.js +53 -171
- package/src/check/runner.js +22 -6
- package/src/client-signals.js +171 -0
- package/src/component-scanner.js +22 -16
- package/src/context.js +152 -16
- package/src/cookie-store.js +262 -0
- package/src/core-exports.js +190 -0
- package/src/dev/bun-app-source.js +95 -5
- package/src/dev/config.js +7 -51
- package/src/dev/dev-service-worker.js +48 -0
- package/src/dev/esm-hot-hooks.js +373 -0
- package/src/dev/handler.js +502 -155
- package/src/dev/helpers.js +127 -96
- package/src/dev/hot-host.js +33 -6
- package/src/dev/poke-state.js +110 -0
- package/src/dev/serve.js +177 -129
- package/src/dev/server.js +92 -33
- package/src/dev/specifier-versions.js +125 -0
- package/src/dev/watch-ignore.js +49 -4
- package/src/dev/watch-poll.js +78 -0
- package/src/dev/watch-tree.js +59 -22
- package/src/dev-classify.js +59 -26
- package/src/dev-error.js +104 -3
- package/src/dev-hot-classify.js +291 -0
- package/src/dev-hot-client.js +245 -0
- package/src/dev-import.js +22 -5
- package/src/dev-overlay.js +26 -0
- package/src/dev-ready-probe.js +69 -0
- package/src/dev-regenerate.js +2 -2
- package/src/dev-reload-hold.js +49 -20
- package/src/dev-reload-reason.js +61 -0
- package/src/dev-reload-worker.js +62 -13
- package/src/dev-secret.js +73 -0
- package/src/dev-source-locations-hook.js +4 -1
- package/src/dev-source-locations.js +33 -2
- package/src/dev.js +0 -1
- package/src/env-files.js +124 -0
- package/src/file-storage.js +2 -2
- package/src/foreign-imports.js +228 -0
- package/src/form-action-identity.js +52 -25
- package/src/form-dispatch.js +140 -65
- package/src/html-cache.js +35 -4
- package/src/importmap.js +2 -2
- package/src/instrumentation.js +59 -3
- package/src/js-scan.js +5 -4
- package/src/jwe.js +155 -0
- package/src/lazy-components.js +166 -0
- package/src/listener-core.js +4 -2
- package/src/lit-hints.js +172 -0
- package/src/middleware-load.js +248 -0
- package/src/module-graph.js +73 -47
- package/src/module-side-effect.js +284 -0
- package/src/public-files.js +73 -0
- package/src/redirect-location.js +19 -0
- package/src/redirects.js +9 -1
- package/src/route-frontier.js +151 -0
- package/src/route-report.js +130 -0
- package/src/router.js +120 -13
- package/src/session.js +32 -10
- package/src/ssr/client-router-flag.js +1 -1
- package/src/ssr/document.js +37 -13
- package/src/ssr/head.js +78 -23
- package/src/ssr/preloads.js +31 -45
- package/src/ssr/render.js +241 -55
- package/src/ssr/responses.js +51 -4
- package/src/ssr/shipped-modules.js +22 -16
- package/src/testing.d.ts +31 -2
- package/src/testing.js +80 -17
- package/src/thenable-params.js +26 -0
- package/src/vendor/jspm.js +12 -1
- package/src/vendor/pins.js +9 -8
- package/src/vendor/scanner.js +14 -9
- package/src/vendor.js +5 -3
- package/webjs-config.schema.json +1 -6
- package/src/component-elision.js +0 -1828
- package/src/elision-differential.js +0 -101
- package/src/elision-report.js +0 -193
package/src/ssr/head.js
CHANGED
|
@@ -639,28 +639,22 @@ export function wrapHead(opts) {
|
|
|
639
639
|
}
|
|
640
640
|
metaTags.push(`<meta name="viewport" content="${escapeAttr(viewportStr || 'width=device-width,initial-scale=1')}">`);
|
|
641
641
|
|
|
642
|
-
|
|
642
|
+
// themeColor: a string, a `{ color, media? }` descriptor, or an array of
|
|
643
|
+
// them (Next's viewport shape): one <meta> per descriptor.
|
|
644
|
+
for (const tc of themeColorList(m.themeColor)) {
|
|
645
|
+
const media = tc.media ? ` media="${escapeAttr(tc.media)}"` : '';
|
|
646
|
+
metaTags.push(`<meta name="theme-color" content="${escapeAttr(tc.color)}"${media}>`);
|
|
647
|
+
}
|
|
643
648
|
if (m.colorScheme) metaTags.push(`<meta name="color-scheme" content="${escapeAttr(m.colorScheme)}">`);
|
|
644
649
|
|
|
645
|
-
// robots:
|
|
650
|
+
// robots: a string or Next's object (index, follow, the directive keys, and
|
|
651
|
+
// a nested `googleBot` resolved the same way into <meta name="googlebot">).
|
|
646
652
|
if (m.robots) {
|
|
647
|
-
|
|
648
|
-
|
|
649
|
-
|
|
650
|
-
const
|
|
651
|
-
if (
|
|
652
|
-
else if (m.robots.index === true) parts.push('index');
|
|
653
|
-
if (m.robots.follow === false) parts.push('nofollow');
|
|
654
|
-
else if (m.robots.follow === true) parts.push('follow');
|
|
655
|
-
if (m.robots.noarchive) parts.push('noarchive');
|
|
656
|
-
if (m.robots.nosnippet) parts.push('nosnippet');
|
|
657
|
-
if (m.robots.noimageindex) parts.push('noimageindex');
|
|
658
|
-
if (parts.length) {
|
|
659
|
-
metaTags.push(`<meta name="robots" content="${escapeAttr(parts.join(', '))}">`);
|
|
660
|
-
}
|
|
661
|
-
if (typeof m.robots.googleBot === 'string') {
|
|
662
|
-
metaTags.push(`<meta name="googlebot" content="${escapeAttr(m.robots.googleBot)}">`);
|
|
663
|
-
}
|
|
653
|
+
const basic = resolveRobotsValue(m.robots);
|
|
654
|
+
if (basic) metaTags.push(`<meta name="robots" content="${escapeAttr(basic)}">`);
|
|
655
|
+
if (typeof m.robots === 'object') {
|
|
656
|
+
const gb = resolveRobotsValue(m.robots.googleBot);
|
|
657
|
+
if (gb) metaTags.push(`<meta name="googlebot" content="${escapeAttr(gb)}">`);
|
|
664
658
|
}
|
|
665
659
|
}
|
|
666
660
|
|
|
@@ -870,8 +864,8 @@ export function wrapHead(opts) {
|
|
|
870
864
|
// above. `vendorPreloadTargets` still excludes core deliberately; this hint
|
|
871
865
|
// is emitted from the head builder, not the vendor path.
|
|
872
866
|
//
|
|
873
|
-
// Gated on the boot actually shipping something. A
|
|
874
|
-
// boot module and must not be handed a preload for a runtime it never loads
|
|
867
|
+
// Gated on the boot actually shipping something. A page with no component
|
|
868
|
+
// ships no boot module and must not be handed a preload for a runtime it never loads
|
|
875
869
|
// (#780), which also keeps it off `global-error.{js,ts}`, whose document is
|
|
876
870
|
// returned verbatim with no importmap and no boot script.
|
|
877
871
|
if (opts.moduleUrls.length || lazyEntries) {
|
|
@@ -1109,6 +1103,13 @@ export function wrapHead(opts) {
|
|
|
1109
1103
|
// conditional line makes the CSP-off document one newline shorter than the
|
|
1110
1104
|
// CSP-on one, and the framework guarantees the two render identically
|
|
1111
1105
|
// apart from the nonce itself.
|
|
1106
|
+
//
|
|
1107
|
+
// The dev reload client goes BEFORE the boot script (#1689): module scripts
|
|
1108
|
+
// run in document order, and it installs the hot client (the template
|
|
1109
|
+
// interner core's `html()` reads) that has to exist before the first
|
|
1110
|
+
// component module evaluates. It sits on the boot's own line and the blank
|
|
1111
|
+
// line after the boot is where it used to be, so a production document,
|
|
1112
|
+
// which has no reload client, is unchanged.
|
|
1112
1113
|
const title = m.title || 'webjs app';
|
|
1113
1114
|
|
|
1114
1115
|
return `<!doctype html>
|
|
@@ -1122,10 +1123,64 @@ ${metaTags.join('\n')}
|
|
|
1122
1123
|
${publicEnvShim({ dev: opts.dev, nonce: opts.nonce })}${embedScriptTag({ dev: opts.dev, nonce: opts.nonce })}${clientRouterEnabled() ? '' : `\n<script${n}>window.__WEBJS_CLIENT_ROUTER__=false;</script>`}
|
|
1123
1124
|
${importMapTag({ nonce: opts.nonce })}
|
|
1124
1125
|
${linkTags.join('\n')}
|
|
1125
|
-
${scriptTags.length ? scriptTags.join('\n') + '\n' : ''}${boot}
|
|
1126
|
-
|
|
1126
|
+
${reload}${scriptTags.length ? scriptTags.join('\n') + '\n' : ''}${boot}
|
|
1127
|
+
|
|
1127
1128
|
${suspenseBoot}
|
|
1128
1129
|
</head>
|
|
1129
1130
|
<body>
|
|
1130
1131
|
`;
|
|
1131
1132
|
}
|
|
1133
|
+
|
|
1134
|
+
/** Next's robot directive keys, in its emit order. */
|
|
1135
|
+
const ROBOTS_KEYS = [
|
|
1136
|
+
'noarchive', 'nosnippet', 'noimageindex', 'nocache', 'notranslate', 'indexifembedded',
|
|
1137
|
+
'nositelinkssearchbox', 'unavailable_after', 'max-video-preview', 'max-image-preview', 'max-snippet',
|
|
1138
|
+
];
|
|
1139
|
+
|
|
1140
|
+
/**
|
|
1141
|
+
* A port of Next.js's `resolveRobotsValue` (resolve-basics.ts): a string
|
|
1142
|
+
* passes through; an object becomes `index` / `noindex`, `follow` /
|
|
1143
|
+
* `nofollow`, then each set directive key (`key` for `true`,
|
|
1144
|
+
* `key:value` otherwise).
|
|
1145
|
+
* @param {unknown} robots
|
|
1146
|
+
* @returns {string | null}
|
|
1147
|
+
*/
|
|
1148
|
+
export function resolveRobotsValue(robots) {
|
|
1149
|
+
if (!robots) return null;
|
|
1150
|
+
if (typeof robots === 'string') return robots;
|
|
1151
|
+
if (typeof robots !== 'object') return null;
|
|
1152
|
+
const r = /** @type {Record<string, unknown>} */ (robots);
|
|
1153
|
+
const values = [];
|
|
1154
|
+
if (r.index) values.push('index');
|
|
1155
|
+
else if (typeof r.index === 'boolean') values.push('noindex');
|
|
1156
|
+
if (r.follow) values.push('follow');
|
|
1157
|
+
else if (typeof r.follow === 'boolean') values.push('nofollow');
|
|
1158
|
+
for (const key of ROBOTS_KEYS) {
|
|
1159
|
+
const value = r[key];
|
|
1160
|
+
if (typeof value !== 'undefined' && value !== false) {
|
|
1161
|
+
values.push(typeof value === 'boolean' ? key : `${key}:${value}`);
|
|
1162
|
+
}
|
|
1163
|
+
}
|
|
1164
|
+
return values.length ? values.join(', ') : null;
|
|
1165
|
+
}
|
|
1166
|
+
|
|
1167
|
+
/**
|
|
1168
|
+
* Normalize Next's `themeColor` (a string, a descriptor, or an array of
|
|
1169
|
+
* descriptors) to a list of `{ color, media? }`.
|
|
1170
|
+
* @param {unknown} v
|
|
1171
|
+
* @returns {{ color: string, media?: string }[]}
|
|
1172
|
+
*/
|
|
1173
|
+
export function themeColorList(v) {
|
|
1174
|
+
if (!v) return [];
|
|
1175
|
+
if (typeof v === 'string') return [{ color: v }];
|
|
1176
|
+
const list = Array.isArray(v) ? v : [v];
|
|
1177
|
+
/** @type {{ color: string, media?: string }[]} */
|
|
1178
|
+
const out = [];
|
|
1179
|
+
for (const d of list) {
|
|
1180
|
+
if (typeof d === 'string') out.push({ color: d });
|
|
1181
|
+
else if (d && typeof d === 'object' && typeof d.color === 'string') {
|
|
1182
|
+
out.push(typeof d.media === 'string' ? { color: d.color, media: d.media } : { color: d.color });
|
|
1183
|
+
}
|
|
1184
|
+
}
|
|
1185
|
+
return out;
|
|
1186
|
+
}
|
package/src/ssr/preloads.js
CHANGED
|
@@ -31,21 +31,16 @@ export function toUrlPath(file, appDir) {
|
|
|
31
31
|
* are NOT preloaded: they're loaded by the IntersectionObserver-based
|
|
32
32
|
* lazy-loader when the element enters the viewport.
|
|
33
33
|
*
|
|
34
|
-
* Elidable (display-only) components are skipped entirely: their imports
|
|
35
|
-
* are stripped from the served source, so preloading their module would
|
|
36
|
-
* fetch JS the browser never executes.
|
|
37
|
-
*
|
|
38
34
|
* A tag counts as lazy when its class says so at runtime (`isLazy`) OR its
|
|
39
35
|
* file declares `static lazy = true` in source (`lazyFiles`, #1524), the same
|
|
40
36
|
* per-file verdict the served-source rewrite uses, so the two never disagree.
|
|
41
37
|
*
|
|
42
38
|
* @param {Set<string>} usedTags
|
|
43
39
|
* @param {string} appDir
|
|
44
|
-
* @param {Set<string>} [elidable] absolute paths of elidable component files
|
|
45
40
|
* @param {Map<string, string[]>} [lazyFiles] lazy component file -> its tags
|
|
46
41
|
* @returns {{ eager: string[], lazy: Record<string, string> }}
|
|
47
42
|
*/
|
|
48
|
-
export function componentPreloads(usedTags, appDir,
|
|
43
|
+
export function componentPreloads(usedTags, appDir, lazyFiles) {
|
|
49
44
|
const eager = [];
|
|
50
45
|
/** @type {Record<string, string>} */
|
|
51
46
|
const lazy = {};
|
|
@@ -55,7 +50,6 @@ export function componentPreloads(usedTags, appDir, elidable, lazyFiles) {
|
|
|
55
50
|
try {
|
|
56
51
|
const abs = fileURLToPath(fileUrl);
|
|
57
52
|
if (!abs.startsWith(appDir)) continue;
|
|
58
|
-
if (elidable && elidable.has(abs)) continue;
|
|
59
53
|
const url = toUrlPath(abs, appDir);
|
|
60
54
|
if (isLazy(tag) || (lazyFiles && lazyFiles.has(abs))) {
|
|
61
55
|
lazy[tag] = url;
|
|
@@ -90,13 +84,13 @@ export function componentPreloads(usedTags, appDir, elidable, lazyFiles) {
|
|
|
90
84
|
* @param {import('../module-graph.js').ModuleGraph | undefined} graph
|
|
91
85
|
* @param {string[]} entryFiles absolute paths of the SHIPPED page/layout modules (from `moduleUrls`)
|
|
92
86
|
* @param {string} appDir
|
|
93
|
-
* @param {Set<string>} [elidableComponents] absolute paths to skip in the walk
|
|
94
87
|
* @param {Set<string>} [serverFiles] the action / server-file index, never preloaded
|
|
88
|
+
* @param {Set<string>} [skip] absolute paths to skip in the walk (the lazy files)
|
|
95
89
|
* @param {string[]} [precomputedDeps] the transitive closure `pagePreloadHints` already walked for
|
|
96
90
|
* THESE roots and THIS skip set. Omitted, the walk runs here (a direct caller)
|
|
97
91
|
* @returns {string[]}
|
|
98
92
|
*/
|
|
99
|
-
export function deduplicatedPreloads(componentUrls, moduleUrls, graph, entryFiles, appDir, serverFiles,
|
|
93
|
+
export function deduplicatedPreloads(componentUrls, moduleUrls, graph, entryFiles, appDir, serverFiles, skip, precomputedDeps) {
|
|
100
94
|
const seen = new Set(moduleUrls);
|
|
101
95
|
const result = [];
|
|
102
96
|
|
|
@@ -133,10 +127,9 @@ export function deduplicatedPreloads(componentUrls, moduleUrls, graph, entryFile
|
|
|
133
127
|
const abs = resolve(appDir, url.startsWith('/') ? url.slice(1) : url);
|
|
134
128
|
allEntries.push(abs);
|
|
135
129
|
}
|
|
136
|
-
// Skip
|
|
137
|
-
// them:
|
|
138
|
-
|
|
139
|
-
deps = transitiveDeps(graph, allEntries, appDir, elidableComponents);
|
|
130
|
+
// Skip the lazy components and any subtree reachable only through
|
|
131
|
+
// them: the lazy loader fetches those on first sight, not up front.
|
|
132
|
+
deps = transitiveDeps(graph, allEntries, appDir, skip);
|
|
140
133
|
}
|
|
141
134
|
for (const dep of deps) {
|
|
142
135
|
if (byIndex(dep)) continue;
|
|
@@ -153,11 +146,11 @@ export function deduplicatedPreloads(componentUrls, moduleUrls, graph, entryFile
|
|
|
153
146
|
/**
|
|
154
147
|
* Collect the bare npm vendor specifiers the page's SHIPPED modules import
|
|
155
148
|
* (#754). The walk ROOTS are the boot's actually-shipped module set: the caller
|
|
156
|
-
* passes `entryFiles` = the absolute paths of `moduleUrls` (
|
|
157
|
-
*
|
|
158
|
-
*
|
|
159
|
-
*
|
|
160
|
-
*
|
|
149
|
+
* passes `entryFiles` = the absolute paths of `moduleUrls` (the components each
|
|
150
|
+
* route module renders, never a route module itself, #1686), plus
|
|
151
|
+
* `componentUrls` = the rendered components. From those roots it walks the
|
|
152
|
+
* transitive app-graph closure (the lazy components and the subtree reachable
|
|
153
|
+
* only through them excluded), and collects each reached file's bare
|
|
161
154
|
* imports, excluding server files. The specifiers are resolved to `modulepreload`
|
|
162
155
|
* targets via the vendor importmap; a specifier not in the map (unpinned /
|
|
163
156
|
* unreached) drops out there.
|
|
@@ -166,35 +159,34 @@ export function deduplicatedPreloads(componentUrls, moduleUrls, graph, entryFile
|
|
|
166
159
|
* dropped from the boot, whether a dropped page's SSR-only DIRECT vendor import
|
|
167
160
|
* or its SSR-only RELATIVE HELPER's vendor, is never collected: the dropped
|
|
168
161
|
* module is not a root, and nothing that ships imports it (pages/layouts are not
|
|
169
|
-
* importable). So the canonical SSR-only-dependency pattern
|
|
170
|
-
*
|
|
162
|
+
* importable). So the canonical SSR-only-dependency pattern is never preloaded
|
|
163
|
+
* (no over-fetch).
|
|
171
164
|
*
|
|
172
165
|
* @param {import('../module-graph.js').ModuleGraph | undefined} graph
|
|
173
166
|
* @param {string[]} entryFiles absolute paths of the SHIPPED page/layout modules (from `moduleUrls`)
|
|
174
167
|
* @param {string[]} componentUrls rendered eager component URL paths
|
|
175
168
|
* @param {string} appDir
|
|
176
|
-
* @param {Set<string>} [
|
|
169
|
+
* @param {Set<string>} [skip] absolute paths to skip in the walk (the lazy files)
|
|
177
170
|
* @param {Set<string>} [serverFiles] the action / server-file index (`'use server'`, incl. no-`.server.` files)
|
|
178
171
|
* @param {string[]} [precomputedDeps] the transitive closure `pagePreloadHints` already walked for
|
|
179
172
|
* THESE roots and THIS skip set. Omitted, the walk runs here (a direct caller)
|
|
180
173
|
* @returns {Set<string>}
|
|
181
174
|
*/
|
|
182
|
-
export function reachedVendorSpecifiers(graph, entryFiles, componentUrls, appDir,
|
|
175
|
+
export function reachedVendorSpecifiers(graph, entryFiles, componentUrls, appDir, skip, serverFiles, precomputedDeps) {
|
|
183
176
|
/** @type {Set<string>} */
|
|
184
177
|
const specs = new Set();
|
|
185
178
|
if (!graph) return specs;
|
|
186
179
|
const bare = bareImports(graph);
|
|
187
180
|
if (!bare.size) return specs;
|
|
188
|
-
// Roots = the
|
|
189
|
-
//
|
|
190
|
-
// absolute paths. Walk their non-elided transitive closure, unless
|
|
181
|
+
// Roots = the boot's shipped modules + the rendered components, keyed by the
|
|
182
|
+
// graph's own absolute paths. Walk their transitive closure, unless
|
|
191
183
|
// `pagePreloadHints` already walked it for this render (#1644).
|
|
192
184
|
const allEntries = [...entryFiles];
|
|
193
185
|
for (const url of componentUrls) {
|
|
194
186
|
allEntries.push(resolve(appDir, url.startsWith('/') ? url.slice(1) : url));
|
|
195
187
|
}
|
|
196
188
|
const files = new Set(allEntries);
|
|
197
|
-
for (const dep of precomputedDeps || transitiveDeps(graph, allEntries, appDir,
|
|
189
|
+
for (const dep of precomputedDeps || transitiveDeps(graph, allEntries, appDir, skip)) files.add(dep);
|
|
198
190
|
for (const file of files) {
|
|
199
191
|
// A server file is never served to the browser (its source is an RPC /
|
|
200
192
|
// throw-at-load stub), so a vendor it imports never ships and must NOT be
|
|
@@ -211,28 +203,23 @@ export function reachedVendorSpecifiers(graph, entryFiles, componentUrls, appDir
|
|
|
211
203
|
}
|
|
212
204
|
|
|
213
205
|
/**
|
|
214
|
-
* The skip set for the preload walks:
|
|
215
|
-
*
|
|
216
|
-
*
|
|
217
|
-
* @type {WeakMap<Map<string, string[]>,
|
|
206
|
+
* The skip set for the preload walks: every `static lazy` component file
|
|
207
|
+
* (#1524). Built once per lazy map (a per-build object), since it was rebuilt
|
|
208
|
+
* per render (#1644).
|
|
209
|
+
* @type {WeakMap<Map<string, string[]>, Set<string>>}
|
|
218
210
|
*/
|
|
219
211
|
const SKIP_MEMO = new WeakMap();
|
|
220
|
-
const NO_ELIDABLE = new Set();
|
|
221
212
|
|
|
222
213
|
/**
|
|
223
|
-
* @param {Set<string> | undefined} elidable
|
|
224
214
|
* @param {Map<string, string[]> | undefined} lazyFiles
|
|
225
215
|
* @returns {Set<string> | undefined}
|
|
226
216
|
*/
|
|
227
|
-
function preloadSkipSet(
|
|
228
|
-
if (!lazyFiles || !lazyFiles.size) return
|
|
229
|
-
|
|
230
|
-
let byElidable = SKIP_MEMO.get(lazyFiles);
|
|
231
|
-
if (!byElidable) { byElidable = new WeakMap(); SKIP_MEMO.set(lazyFiles, byElidable); }
|
|
232
|
-
let skip = byElidable.get(key);
|
|
217
|
+
function preloadSkipSet(lazyFiles) {
|
|
218
|
+
if (!lazyFiles || !lazyFiles.size) return undefined;
|
|
219
|
+
let skip = SKIP_MEMO.get(lazyFiles);
|
|
233
220
|
if (!skip) {
|
|
234
|
-
skip = new Set(
|
|
235
|
-
|
|
221
|
+
skip = new Set(lazyFiles.keys());
|
|
222
|
+
SKIP_MEMO.set(lazyFiles, skip);
|
|
236
223
|
}
|
|
237
224
|
return skip;
|
|
238
225
|
}
|
|
@@ -245,8 +232,8 @@ function preloadSkipSet(elidable, lazyFiles) {
|
|
|
245
232
|
* walks it once and hands the closure to both.
|
|
246
233
|
*
|
|
247
234
|
* The walk roots are the BOOT's actually-shipped module set (`moduleUrls`,
|
|
248
|
-
*
|
|
249
|
-
*
|
|
235
|
+
* the component frontier of each route module, #1686) plus the rendered eager
|
|
236
|
+
* components, NOT the raw route entries: rooting at
|
|
250
237
|
* the raw entries would walk a dropped page's SSR-only subtree and hint a
|
|
251
238
|
* `modulepreload` for a module nothing that ships imports (#780, the
|
|
252
239
|
* app-module analog of the #754 vendor over-fetch).
|
|
@@ -256,15 +243,14 @@ function preloadSkipSet(elidable, lazyFiles) {
|
|
|
256
243
|
* appDir: string,
|
|
257
244
|
* moduleUrls: string[],
|
|
258
245
|
* eagerComponents: string[],
|
|
259
|
-
* elidableComponents: Set<string> | undefined,
|
|
260
246
|
* lazyFiles: Map<string, string[]> | undefined,
|
|
261
247
|
* serverFiles: Set<string> | undefined,
|
|
262
248
|
* }} input
|
|
263
249
|
* @returns {{ preloads: string[], vendorSpecifiers: Set<string>, skip: Set<string> | undefined }}
|
|
264
250
|
*/
|
|
265
251
|
export function pagePreloadHints(input) {
|
|
266
|
-
const { graph, appDir, moduleUrls, eagerComponents,
|
|
267
|
-
const skip = preloadSkipSet(
|
|
252
|
+
const { graph, appDir, moduleUrls, eagerComponents, lazyFiles, serverFiles } = input;
|
|
253
|
+
const skip = preloadSkipSet(lazyFiles);
|
|
268
254
|
const shippedRoots = moduleUrls.map((u) => resolve(appDir, u.startsWith('/') ? u.slice(1) : u));
|
|
269
255
|
/** @type {string[] | undefined} */
|
|
270
256
|
let deps;
|