vinext 1.4.1 → 1.4.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/README.md +5 -2
- package/dist/build/action-owner-manifest.js +1 -0
- package/dist/build/prerender-paths.d.ts +11 -1
- package/dist/build/prerender-paths.js +36 -10
- package/dist/check.js +1 -1
- package/dist/cli.js +1 -1
- package/dist/client/dev-error-overlay.d.ts +2 -1
- package/dist/client/dev-error-overlay.js +8 -3
- package/dist/config/config-matchers.js +8 -4
- package/dist/config/destination-params.js +5 -2
- package/dist/config/next-config.d.ts +25 -1
- package/dist/config/next-config.js +31 -1
- package/dist/entries/app-rsc-entry.js +65 -30
- package/dist/entries/app-rsc-manifest.js +4 -0
- package/dist/entries/pages-server-entry.js +19 -4
- package/dist/index.js +37 -37
- package/dist/init-cloudflare.js +18 -2
- package/dist/init-platform.js +2 -2
- package/dist/init.js +42 -5
- package/dist/plugins/css-target.d.ts +18 -0
- package/dist/plugins/css-target.js +93 -0
- package/dist/routing/app-route-graph.d.ts +10 -0
- package/dist/routing/app-route-graph.js +15 -1
- package/dist/server/api-handler.d.ts +2 -0
- package/dist/server/api-handler.js +10 -8
- package/dist/server/app-action-forwarding.js +3 -1
- package/dist/server/app-browser-entry.js +37 -41
- package/dist/server/app-browser-error.d.ts +1 -1
- package/dist/server/app-browser-error.js +13 -4
- package/dist/server/app-browser-supplemental-refresh.d.ts +13 -0
- package/dist/server/app-browser-supplemental-refresh.js +36 -4
- package/dist/server/app-elements.d.ts +3 -0
- package/dist/server/app-elements.js +14 -1
- package/dist/server/app-fallback-renderer.js +2 -2
- package/dist/server/app-middleware.d.ts +2 -0
- package/dist/server/app-middleware.js +1 -0
- package/dist/server/app-optimistic-routing.d.ts +12 -1
- package/dist/server/app-optimistic-routing.js +38 -16
- package/dist/server/app-page-boundary-render.js +4 -2
- package/dist/server/app-page-cache-render.js +1 -1
- package/dist/server/app-page-dispatch.d.ts +11 -1
- package/dist/server/app-page-dispatch.js +78 -31
- package/dist/server/app-page-element-builder.d.ts +11 -20
- package/dist/server/app-page-element-builder.js +39 -50
- package/dist/server/app-page-intercept-segment-config.d.ts +56 -0
- package/dist/server/app-page-intercept-segment-config.js +90 -0
- package/dist/server/app-page-navigation-params.d.ts +23 -0
- package/dist/server/app-page-navigation-params.js +49 -0
- package/dist/server/app-page-render.d.ts +5 -2
- package/dist/server/app-page-render.js +17 -3
- package/dist/server/app-page-request.d.ts +24 -2
- package/dist/server/app-page-request.js +10 -10
- package/dist/server/app-page-route-wiring.d.ts +17 -5
- package/dist/server/app-page-route-wiring.js +19 -13
- package/dist/server/app-page-segment-plan.js +9 -1
- package/dist/server/app-page-segment-state.d.ts +9 -0
- package/dist/server/app-page-segment-state.js +54 -1
- package/dist/server/app-pages-bridge.d.ts +6 -0
- package/dist/server/app-pages-bridge.js +8 -3
- package/dist/server/app-request-stage-independent-entry.js +2 -3
- package/dist/server/app-response-stage-entry.js +1 -0
- package/dist/server/app-route-module-loader.d.ts +2 -0
- package/dist/server/app-route-module-loader.js +1 -0
- package/dist/server/app-router-entry.js +2 -3
- package/dist/server/app-rsc-cache-busting.d.ts +8 -0
- package/dist/server/app-rsc-cache-busting.js +13 -1
- package/dist/server/app-rsc-combined-handler.js +2 -1
- package/dist/server/app-rsc-handler.d.ts +14 -1
- package/dist/server/app-rsc-handler.js +111 -62
- package/dist/server/app-rsc-response-finalizer.d.ts +18 -3
- package/dist/server/app-rsc-response-finalizer.js +61 -7
- package/dist/server/app-rsc-route-matching.d.ts +14 -0
- package/dist/server/app-rsc-route-matching.js +42 -18
- package/dist/server/app-server-action-execution.js +16 -10
- package/dist/server/app-ssr-entry.js +8 -0
- package/dist/server/cache-control.d.ts +2 -0
- package/dist/server/cache-control.js +3 -1
- package/dist/server/config-headers.d.ts +7 -0
- package/dist/server/config-headers.js +20 -1
- package/dist/server/image-animation.d.ts +9 -0
- package/dist/server/image-animation.js +118 -0
- package/dist/server/image-local-patterns.d.ts +21 -0
- package/dist/server/image-local-patterns.js +59 -0
- package/dist/server/image-optimization.d.ts +48 -27
- package/dist/server/image-optimization.js +316 -22
- package/dist/server/image-source-reader.d.ts +34 -0
- package/dist/server/image-source-reader.js +126 -0
- package/dist/server/metadata-route-response.d.ts +6 -1
- package/dist/server/metadata-route-response.js +46 -10
- package/dist/server/middleware-matcher.d.ts +1 -0
- package/dist/server/middleware-matcher.js +1 -1
- package/dist/server/middleware-runtime.d.ts +5 -0
- package/dist/server/middleware-runtime.js +48 -15
- package/dist/server/middleware.d.ts +1 -1
- package/dist/server/middleware.js +2 -1
- package/dist/server/nitro-public-files-plugin.js +20 -8
- package/dist/server/nitro-request-target-plugin.d.ts +17 -0
- package/dist/server/nitro-request-target-plugin.js +22 -0
- package/dist/server/open-redirect.d.ts +2 -1
- package/dist/server/open-redirect.js +2 -1
- package/dist/server/pages-client-assets.d.ts +1 -0
- package/dist/server/pages-data-route.d.ts +5 -1
- package/dist/server/pages-data-route.js +14 -6
- package/dist/server/pages-i18n.d.ts +7 -0
- package/dist/server/pages-i18n.js +14 -1
- package/dist/server/pages-node-compat.js +7 -3
- package/dist/server/pages-page-handler.js +4 -4
- package/dist/server/pages-request-pipeline.d.ts +9 -0
- package/dist/server/pages-request-pipeline.js +35 -15
- package/dist/server/pages-request-stage-entry.js +8 -2
- package/dist/server/pages-router-entry.js +3 -0
- package/dist/server/prod-server.d.ts +1 -1
- package/dist/server/prod-server.js +64 -62
- package/dist/server/request-pipeline.d.ts +5 -0
- package/dist/server/request-pipeline.js +11 -1
- package/dist/server/response-stage-cacheability.d.ts +7 -0
- package/dist/server/response-stage-cacheability.js +6 -5
- package/dist/server/srvx-middleware-origin.d.ts +13 -0
- package/dist/server/srvx-middleware-origin.js +19 -0
- package/dist/server/srvx-request-target.d.ts +12 -0
- package/dist/server/srvx-request-target.js +20 -0
- package/dist/server/static-file-cache.js +10 -22
- package/dist/server/worker-image-optimization.d.ts +10 -3
- package/dist/server/worker-image-optimization.js +43 -9
- package/dist/server/worker-revalidation-context.js +1 -0
- package/dist/server/worker-utils.d.ts +8 -0
- package/dist/server/worker-utils.js +19 -2
- package/dist/shims/error-boundary.d.ts +6 -2
- package/dist/shims/error-boundary.js +4 -2
- package/dist/shims/image-props.d.ts +6 -0
- package/dist/shims/image-props.js +39 -3
- package/dist/shims/image.js +3 -3
- package/dist/shims/request-context.d.ts +3 -1
- package/dist/shims/slot.d.ts +3 -0
- package/dist/shims/slot.js +67 -9
- package/dist/shims/url-utils.js +6 -1
- package/dist/utils/base-path.d.ts +7 -0
- package/dist/utils/base-path.js +11 -1
- package/dist/utils/client-entry-manifest.d.ts +5 -0
- package/dist/utils/client-entry-manifest.js +1 -0
- package/dist/utils/client-runtime-metadata.d.ts +5 -0
- package/dist/utils/client-runtime-metadata.js +33 -7
- package/package.json +1 -1
package/dist/shims/slot.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
"use client";
|
|
2
2
|
import { APP_BFCACHE_SEGMENT_IDENTITIES_KEY, AppElementsWire, UNMATCHED_SLOT } from "../server/app-elements-wire.js";
|
|
3
|
-
import "../server/app-elements.js";
|
|
3
|
+
import { readOptimisticStateKeyRebinder } from "../server/app-elements.js";
|
|
4
4
|
import { isNestedBfcacheSlotSegmentId, isNestedBfcacheSlotSegmentIdFor } from "../server/bfcache-identity.js";
|
|
5
5
|
import { notFound } from "./navigation-errors.js";
|
|
6
6
|
import { getBfcacheIdMapContext, getBfcacheSegmentIdContext } from "./navigation-context-state.js";
|
|
@@ -51,6 +51,25 @@ const BfcacheSegmentIdContext = getBfcacheSegmentIdContext();
|
|
|
51
51
|
const EMPTY_BFCACHE_STATE_KEYS = Object.freeze({});
|
|
52
52
|
const MAX_BFCACHE_SLOT_ENTRIES_WITH_CACHE_COMPONENTS = 3;
|
|
53
53
|
const MAX_BFCACHE_SLOT_ENTRIES_WITHOUT_CACHE_COMPONENTS = 1;
|
|
54
|
+
const rootBfcacheRetainedKeysReports = /* @__PURE__ */ new Map();
|
|
55
|
+
function isBfcacheIdentityRetained(identity) {
|
|
56
|
+
return hasBfcacheRetainedKey(rootBfcacheRetainedKeysReports, identity);
|
|
57
|
+
}
|
|
58
|
+
function hasBfcacheRetainedKey(reports, identity) {
|
|
59
|
+
for (const report of reports.values()) {
|
|
60
|
+
if (report.keys.includes(identity) || report.hiddenKeys.includes(identity)) return true;
|
|
61
|
+
if (hasBfcacheRetainedKey(report.activeReports, identity)) return true;
|
|
62
|
+
}
|
|
63
|
+
return false;
|
|
64
|
+
}
|
|
65
|
+
const BfcacheRetainedKeysContext = React$1.createContext(rootBfcacheRetainedKeysReports);
|
|
66
|
+
function collectBfcacheRetainedKeys(reports, keys) {
|
|
67
|
+
for (const report of reports.values()) {
|
|
68
|
+
for (const key of report.keys) keys.add(key);
|
|
69
|
+
for (const key of report.hiddenKeys) keys.add(key);
|
|
70
|
+
collectBfcacheRetainedKeys(report.activeReports, keys);
|
|
71
|
+
}
|
|
72
|
+
}
|
|
54
73
|
const BfcacheIdentityMapContext = React$1.createContext(EMPTY_BFCACHE_STATE_KEYS);
|
|
55
74
|
function isCacheComponentsEnabled() {
|
|
56
75
|
return String(process.env.__NEXT_CACHE_COMPONENTS) === "true";
|
|
@@ -136,34 +155,71 @@ function warnTransportMetadataEntry(id) {
|
|
|
136
155
|
* falling back to the live boundary values for entries that predate per-entry
|
|
137
156
|
* capture.
|
|
138
157
|
*/
|
|
139
|
-
function BfcacheEntryProviders({ entry, fallbackElements, fallbackSegmentId, fallbackStateKeyMap, SegmentContext }) {
|
|
158
|
+
function BfcacheEntryProviders({ entry, fallbackElements, fallbackSegmentId, fallbackStateKeyMap, retainedKeysReports, SegmentContext }) {
|
|
140
159
|
return /* @__PURE__ */ jsx(BfcacheIdentityMapContext.Provider, {
|
|
141
160
|
value: entry.stateKeyMap ?? fallbackStateKeyMap,
|
|
142
161
|
children: /* @__PURE__ */ jsx(ElementsContext.Provider, {
|
|
143
162
|
value: entry.elements ?? fallbackElements,
|
|
144
163
|
children: /* @__PURE__ */ jsx(SegmentContext.Provider, {
|
|
145
164
|
value: entry.segmentId ?? fallbackSegmentId,
|
|
146
|
-
children:
|
|
165
|
+
children: /* @__PURE__ */ jsx(BfcacheRetainedKeysContext.Provider, {
|
|
166
|
+
value: retainedKeysReports,
|
|
167
|
+
children: entry.content
|
|
168
|
+
})
|
|
147
169
|
})
|
|
148
170
|
})
|
|
149
171
|
});
|
|
150
172
|
}
|
|
151
|
-
function useBfcacheSlotEntries(activeEntry) {
|
|
173
|
+
function useBfcacheSlotEntries(listId, activeEntry) {
|
|
152
174
|
const snapshotsByStateKey = React$1.useRef(/* @__PURE__ */ new Map());
|
|
153
175
|
const [entryOrder, setEntryOrder] = React$1.useState(() => [activeEntry.stateKey]);
|
|
176
|
+
const [retainedKeysReportsByStateKey] = React$1.useState(() => /* @__PURE__ */ new Map());
|
|
177
|
+
const getRetainedKeysReports = (stateKey) => {
|
|
178
|
+
let reports = retainedKeysReportsByStateKey.get(stateKey);
|
|
179
|
+
if (!reports) {
|
|
180
|
+
reports = /* @__PURE__ */ new Map();
|
|
181
|
+
retainedKeysReportsByStateKey.set(stateKey, reports);
|
|
182
|
+
}
|
|
183
|
+
return reports;
|
|
184
|
+
};
|
|
154
185
|
const committedSnapshots = snapshotsByStateKey.current;
|
|
155
186
|
const staged = stageBfcacheSlotEntryForRender(committedSnapshots, entryOrder, activeEntry);
|
|
187
|
+
for (const [index, entry] of staged.entries.entries()) {
|
|
188
|
+
if (entry.stateKey === activeEntry.stateKey || entry.retainedKeys) continue;
|
|
189
|
+
const retainedKeys = /* @__PURE__ */ new Set([entry.stateKey]);
|
|
190
|
+
collectBfcacheRetainedKeys(getRetainedKeysReports(entry.stateKey), retainedKeys);
|
|
191
|
+
const hiddenEntry = {
|
|
192
|
+
...entry,
|
|
193
|
+
retainedKeys: [...retainedKeys]
|
|
194
|
+
};
|
|
195
|
+
staged.entries[index] = hiddenEntry;
|
|
196
|
+
staged.snapshots.set(entry.stateKey, hiddenEntry);
|
|
197
|
+
}
|
|
156
198
|
const nextOrder = staged.order;
|
|
157
199
|
const orderChanged = !haveSameBfcacheSlotEntryOrder(entryOrder, nextOrder);
|
|
158
200
|
React$1.useLayoutEffect(() => {
|
|
159
201
|
snapshotsByStateKey.current = staged.snapshots;
|
|
160
|
-
|
|
202
|
+
for (const stateKey of retainedKeysReportsByStateKey.keys()) if (!staged.snapshots.has(stateKey)) retainedKeysReportsByStateKey.delete(stateKey);
|
|
203
|
+
}, [retainedKeysReportsByStateKey, staged.snapshots]);
|
|
204
|
+
const hiddenKeys = [...new Set(staged.entries.flatMap((entry) => entry.retainedKeys ?? []))];
|
|
205
|
+
const enclosingReports = React$1.useContext(BfcacheRetainedKeysContext);
|
|
206
|
+
const report = {
|
|
207
|
+
activeReports: getRetainedKeysReports(activeEntry.stateKey),
|
|
208
|
+
hiddenKeys,
|
|
209
|
+
keys: staged.entries.map((entry) => entry.stateKey)
|
|
210
|
+
};
|
|
211
|
+
React$1.useLayoutEffect(() => {
|
|
212
|
+
enclosingReports.set(listId, report);
|
|
213
|
+
});
|
|
161
214
|
if (process.env.NODE_ENV !== "production" && !staged.snapshots.has(activeEntry.stateKey)) throw new Error("BFCache Activity slot is missing the active entry snapshot");
|
|
162
215
|
if (orderChanged) setEntryOrder(nextOrder);
|
|
163
|
-
return
|
|
216
|
+
return {
|
|
217
|
+
entries: staged.entries,
|
|
218
|
+
getRetainedKeysReports
|
|
219
|
+
};
|
|
164
220
|
}
|
|
165
221
|
function BfcacheActivitySlotBoundary({ activeStateKey, content, elements, id, SegmentContext, stateKeyMap }) {
|
|
166
|
-
const renderEntries = useBfcacheSlotEntries({
|
|
222
|
+
const { entries: renderEntries, getRetainedKeysReports } = useBfcacheSlotEntries(id, {
|
|
167
223
|
content,
|
|
168
224
|
elements,
|
|
169
225
|
segmentId: id,
|
|
@@ -177,6 +233,7 @@ function BfcacheActivitySlotBoundary({ activeStateKey, content, elements, id, Se
|
|
|
177
233
|
fallbackElements: elements,
|
|
178
234
|
fallbackSegmentId: id,
|
|
179
235
|
fallbackStateKeyMap: stateKeyMap,
|
|
236
|
+
retainedKeysReports: getRetainedKeysReports(entry.stateKey),
|
|
180
237
|
SegmentContext
|
|
181
238
|
})
|
|
182
239
|
}, entry.stateKey)) });
|
|
@@ -228,7 +285,8 @@ function BfcacheChildrenActivityBoundary({ children, id, IdMapContext, SegmentCo
|
|
|
228
285
|
const identityMap = React$1.useContext(BfcacheIdentityMapContext);
|
|
229
286
|
const bfcacheIdMap = React$1.useContext(IdMapContext);
|
|
230
287
|
const segmentId = React$1.useContext(SegmentContext);
|
|
231
|
-
const
|
|
288
|
+
const rebindStateKey = readOptimisticStateKeyRebinder(elements);
|
|
289
|
+
const activeStateKey = stateKey !== void 0 ? rebindStateKey?.(stateKey) ?? stateKey : id === void 0 ? void 0 : resolveBfcacheSegmentStateKey(id, identityMap, bfcacheIdMap);
|
|
232
290
|
if (segmentId === null || activeStateKey === void 0) return /* @__PURE__ */ jsx(Fragment$1, { children });
|
|
233
291
|
return /* @__PURE__ */ jsx(BfcacheActivitySlotBoundary, {
|
|
234
292
|
activeStateKey,
|
|
@@ -375,4 +433,4 @@ function ParallelSlot({ name }) {
|
|
|
375
433
|
return React$1.useContext(ParallelSlotsContext)?.[name] ?? null;
|
|
376
434
|
}
|
|
377
435
|
//#endregion
|
|
378
|
-
export { BfcacheChildrenBoundary, BfcacheIdentityMapContext, BfcacheSegmentBoundary, Children, ChildrenContext, ElementsContext, ParallelSlot, ParallelSlotsContext, RenderedSearchContext, Slot, UNMATCHED_SLOT, bindAppElementsRenderedSearch, getNonCacheComponentsSegmentKey, mergeElements, resolveBfcacheSegmentStateKey, setAppElementsRenderedSearch, stageBfcacheSlotEntryForRender, updateBfcacheSlotEntryOrder };
|
|
436
|
+
export { BfcacheChildrenBoundary, BfcacheIdentityMapContext, BfcacheSegmentBoundary, Children, ChildrenContext, ElementsContext, ParallelSlot, ParallelSlotsContext, RenderedSearchContext, Slot, UNMATCHED_SLOT, bindAppElementsRenderedSearch, getNonCacheComponentsSegmentKey, isBfcacheIdentityRetained, mergeElements, resolveBfcacheSegmentStateKey, setAppElementsRenderedSearch, stageBfcacheSlotEntryForRender, updateBfcacheSlotEntryOrder };
|
package/dist/shims/url-utils.js
CHANGED
|
@@ -115,12 +115,17 @@ function normalizePathTrailingSlash(path, trailingSlash) {
|
|
|
115
115
|
if (!path.startsWith("/") || path.startsWith("//") || process.env.__VINEXT_MANUAL_TRAILING_SLASH === "true") return path;
|
|
116
116
|
const { pathname, query, hash } = parsePath(path);
|
|
117
117
|
if (trailingSlash) {
|
|
118
|
-
if (
|
|
118
|
+
if (hasFileLikeLastSegment(pathname)) return `${removeRouteTrailingSlash(pathname)}${query}${hash}`;
|
|
119
119
|
if (pathname.endsWith("/")) return `${pathname}${query}${hash}`;
|
|
120
120
|
return `${pathname}/${query}${hash}`;
|
|
121
121
|
}
|
|
122
122
|
return `${removeRouteTrailingSlash(pathname)}${query}${hash}`;
|
|
123
123
|
}
|
|
124
|
+
function hasFileLikeLastSegment(pathname) {
|
|
125
|
+
const end = pathname.endsWith("/") ? pathname.length - 1 : pathname.length;
|
|
126
|
+
const dot = pathname.indexOf(".", pathname.lastIndexOf("/", end - 1) + 1);
|
|
127
|
+
return dot !== -1 && dot < end - 1;
|
|
128
|
+
}
|
|
124
129
|
/**
|
|
125
130
|
* Prepend basePath to a local path for browser URLs / fetches.
|
|
126
131
|
*/
|
|
@@ -21,6 +21,13 @@ export declare function stripBasePath(pathname: string, basePath: string): strin
|
|
|
21
21
|
* this pathname-only helper.
|
|
22
22
|
*/
|
|
23
23
|
export declare function addBasePathToPathname(pathname: string, basePath: string | undefined): string;
|
|
24
|
+
/**
|
|
25
|
+
* Re-add a basePath that `stripBasePath` removed. Unlike
|
|
26
|
+
* `addBasePathToPathname`, this always prepends it: a stripped route whose
|
|
27
|
+
* first segment equals the basePath (basePath "/docs", route "/docs/a") still
|
|
28
|
+
* starts with the basePath and must not be mistaken for the original URL.
|
|
29
|
+
*/
|
|
30
|
+
export declare function restoreBasePath(pathname: string, basePath: string | undefined): string;
|
|
24
31
|
/**
|
|
25
32
|
* Remove trailing slashes from a pathname while preserving the root "/".
|
|
26
33
|
* Collapses any number of trailing slashes ("/a//" → "/a"). Used by the
|
package/dist/utils/base-path.js
CHANGED
|
@@ -31,6 +31,16 @@ function addBasePathToPathname(pathname, basePath) {
|
|
|
31
31
|
return pathname === "/" ? basePath : `${basePath}${pathname}`;
|
|
32
32
|
}
|
|
33
33
|
/**
|
|
34
|
+
* Re-add a basePath that `stripBasePath` removed. Unlike
|
|
35
|
+
* `addBasePathToPathname`, this always prepends it: a stripped route whose
|
|
36
|
+
* first segment equals the basePath (basePath "/docs", route "/docs/a") still
|
|
37
|
+
* starts with the basePath and must not be mistaken for the original URL.
|
|
38
|
+
*/
|
|
39
|
+
function restoreBasePath(pathname, basePath) {
|
|
40
|
+
if (!basePath) return pathname;
|
|
41
|
+
return pathname === "/" ? basePath : `${basePath}${pathname}`;
|
|
42
|
+
}
|
|
43
|
+
/**
|
|
34
44
|
* Remove trailing slashes from a pathname while preserving the root "/".
|
|
35
45
|
* Collapses any number of trailing slashes ("/a//" → "/a"). Used by the
|
|
36
46
|
* trailing-slash redirect path and route pattern normalization.
|
|
@@ -42,4 +52,4 @@ function removeTrailingSlash(pathname) {
|
|
|
42
52
|
return end === 0 ? "/" : pathname.slice(0, end);
|
|
43
53
|
}
|
|
44
54
|
//#endregion
|
|
45
|
-
export { addBasePathToPathname, hasBasePath, removeTrailingSlash, stripBasePath };
|
|
55
|
+
export { addBasePathToPathname, hasBasePath, removeTrailingSlash, restoreBasePath, stripBasePath };
|
|
@@ -11,6 +11,11 @@ export declare const VINEXT_CLIENT_REFERENCE_SOURCES = ".vite/vinext-client-refe
|
|
|
11
11
|
export type ClientEntryManifest = {
|
|
12
12
|
pagesClientEntry?: string;
|
|
13
13
|
appBrowserEntry?: string;
|
|
14
|
+
/**
|
|
15
|
+
* The chunk holding the App Router browser runtime, whose evaluation starts
|
|
16
|
+
* hydration. A user chunk group can move it out of `appBrowserEntry`.
|
|
17
|
+
*/
|
|
18
|
+
appBrowserRuntime?: string;
|
|
14
19
|
/** The App Router RouteManifest chunk, which the browser entry imports as it boots. */
|
|
15
20
|
appRouteManifest?: string;
|
|
16
21
|
/** What each App Router client reference loads in the browser. */
|
|
@@ -20,6 +20,7 @@ function readClientEntryManifest(clientDir) {
|
|
|
20
20
|
const manifest = {};
|
|
21
21
|
if (typeof value.pagesClientEntry === "string") manifest.pagesClientEntry = value.pagesClientEntry;
|
|
22
22
|
if (typeof value.appBrowserEntry === "string") manifest.appBrowserEntry = value.appBrowserEntry;
|
|
23
|
+
if (typeof value.appBrowserRuntime === "string") manifest.appBrowserRuntime = value.appBrowserRuntime;
|
|
23
24
|
if (typeof value.appRouteManifest === "string") manifest.appRouteManifest = value.appRouteManifest;
|
|
24
25
|
if (isUnknownRecord(value.appClientReferenceChunks)) manifest.appClientReferenceChunks = value.appClientReferenceChunks;
|
|
25
26
|
return manifest.pagesClientEntry || manifest.appBrowserEntry ? manifest : void 0;
|
|
@@ -3,6 +3,7 @@ import { ClientReferenceChunks } from "./client-reference-chunks.js";
|
|
|
3
3
|
type ClientRuntimeMetadata = {
|
|
4
4
|
clientEntryFile?: string;
|
|
5
5
|
appBootstrapPreinitModules?: string[];
|
|
6
|
+
appBootstrapPreloadModules?: string[];
|
|
6
7
|
appRouteManifestModule?: string;
|
|
7
8
|
appClientReferenceChunks?: ClientReferenceChunks;
|
|
8
9
|
cssGraph?: Record<string, {
|
|
@@ -17,6 +18,10 @@ type ClientRuntimeMetadata = {
|
|
|
17
18
|
* Read the client build manifest and compute runtime metadata used by
|
|
18
19
|
* Cloudflare worker entry injection and Node production server startup.
|
|
19
20
|
*
|
|
21
|
+
* - `appBootstrapPreinitModules` — chunks the App Router browser entry imports,
|
|
22
|
+
* preinitialized during SSR.
|
|
23
|
+
* - `appBootstrapPreloadModules` — those of them that would start hydration if
|
|
24
|
+
* evaluated ahead of the shell, preloaded during SSR instead.
|
|
20
25
|
* - `appRouteManifestModule` — the App Router RouteManifest chunk, which the
|
|
21
26
|
* browser entry imports as it boots, preloaded during SSR.
|
|
22
27
|
* - `appClientReferenceChunks` — what each App Router client reference loads
|
|
@@ -41,11 +41,28 @@ function collectCssGraph(buildManifest, applyBase) {
|
|
|
41
41
|
}
|
|
42
42
|
return Object.keys(cssGraph).length > 0 ? cssGraph : void 0;
|
|
43
43
|
}
|
|
44
|
-
|
|
45
|
-
|
|
44
|
+
/**
|
|
45
|
+
* The chunks the App Router browser entry statically imports, split by whether
|
|
46
|
+
* they can run ahead of the shell. A preinitialized module evaluates as soon as
|
|
47
|
+
* it loads, which on a reload can be before `<body>` has streamed. Evaluating
|
|
48
|
+
* the browser runtime starts hydration, so a chunk that holds or imports it is
|
|
49
|
+
* only preloaded, and runs when React's bootstrap script does. A user chunk
|
|
50
|
+
* group can put the runtime in one of these chunks.
|
|
51
|
+
*/
|
|
52
|
+
function collectAppBootstrapModules(buildManifest, appBrowserEntry, appBrowserRuntime, applyBase) {
|
|
53
|
+
if (!appBrowserEntry) return {};
|
|
46
54
|
const entryKey = Object.keys(buildManifest).find((key) => buildManifest[key].file === appBrowserEntry);
|
|
47
|
-
if (!entryKey) return
|
|
48
|
-
|
|
55
|
+
if (!entryKey) return {};
|
|
56
|
+
function evaluatesRuntime(key, seen = /* @__PURE__ */ new Set()) {
|
|
57
|
+
if (seen.has(key)) return false;
|
|
58
|
+
seen.add(key);
|
|
59
|
+
const chunk = buildManifest[key];
|
|
60
|
+
if (!chunk) return false;
|
|
61
|
+
if (chunk.file === appBrowserRuntime) return true;
|
|
62
|
+
return (chunk.imports ?? []).some((importedKey) => evaluatesRuntime(importedKey, seen));
|
|
63
|
+
}
|
|
64
|
+
const preinit = [];
|
|
65
|
+
const preload = [];
|
|
49
66
|
const seenFiles = /* @__PURE__ */ new Set();
|
|
50
67
|
const visitedChunks = /* @__PURE__ */ new Set();
|
|
51
68
|
function visit(key) {
|
|
@@ -57,18 +74,25 @@ function collectAppBootstrapPreinitModules(buildManifest, appBrowserEntry, apply
|
|
|
57
74
|
const importedChunk = buildManifest[importedKey];
|
|
58
75
|
if (importedChunk?.file.endsWith(".js") && !seenFiles.has(importedChunk.file)) {
|
|
59
76
|
seenFiles.add(importedChunk.file);
|
|
60
|
-
|
|
77
|
+
(evaluatesRuntime(importedKey) ? preload : preinit).push(applyBase(importedChunk.file));
|
|
61
78
|
}
|
|
62
79
|
visit(importedKey);
|
|
63
80
|
}
|
|
64
81
|
}
|
|
65
82
|
visit(entryKey);
|
|
66
|
-
return
|
|
83
|
+
return {
|
|
84
|
+
...preinit.length > 0 ? { preinit } : {},
|
|
85
|
+
...preload.length > 0 ? { preload } : {}
|
|
86
|
+
};
|
|
67
87
|
}
|
|
68
88
|
/**
|
|
69
89
|
* Read the client build manifest and compute runtime metadata used by
|
|
70
90
|
* Cloudflare worker entry injection and Node production server startup.
|
|
71
91
|
*
|
|
92
|
+
* - `appBootstrapPreinitModules` — chunks the App Router browser entry imports,
|
|
93
|
+
* preinitialized during SSR.
|
|
94
|
+
* - `appBootstrapPreloadModules` — those of them that would start hydration if
|
|
95
|
+
* evaluated ahead of the shell, preloaded during SSR instead.
|
|
72
96
|
* - `appRouteManifestModule` — the App Router RouteManifest chunk, which the
|
|
73
97
|
* browser entry imports as it boots, preloaded during SSR.
|
|
74
98
|
* - `appClientReferenceChunks` — what each App Router client reference loads
|
|
@@ -118,7 +142,9 @@ function computeClientRuntimeMetadata(opts) {
|
|
|
118
142
|
metadata.cssGraph = collectCssGraph(buildManifest, (file) => manifestFileWithBase(file, opts.assetBase));
|
|
119
143
|
metadata.sharedChunks = collectSharedChunkFiles(buildManifest, (file) => manifestFileWithBase(file, opts.assetBase));
|
|
120
144
|
}
|
|
121
|
-
|
|
145
|
+
const appBootstrapModules = collectAppBootstrapModules(buildManifest, clientEntryManifest?.appBrowserEntry, clientEntryManifest?.appBrowserRuntime, appAssetUrl);
|
|
146
|
+
metadata.appBootstrapPreinitModules = appBootstrapModules.preinit;
|
|
147
|
+
metadata.appBootstrapPreloadModules = appBootstrapModules.preload;
|
|
122
148
|
if (clientEntryManifest?.appRouteManifest) metadata.appRouteManifestModule = appAssetUrl(clientEntryManifest.appRouteManifest);
|
|
123
149
|
const lazyChunks = computeLazyChunks(buildManifest).map((file) => manifestFileWithBase(file, opts.assetBase));
|
|
124
150
|
if (lazyChunks.length > 0) metadata.lazyChunks = lazyChunks;
|