vinext 0.2.0 → 0.2.1
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/dist/build/css-url-assets.d.ts +3 -1
- package/dist/build/css-url-assets.js +18 -1
- package/dist/build/inject-pregenerated-paths.d.ts +3 -0
- package/dist/build/inject-pregenerated-paths.js +4 -1
- package/dist/build/prerender-server-entry.d.ts +1 -0
- package/dist/build/prerender-server-entry.js +49 -0
- package/dist/build/prerender-server-pool.d.ts +44 -0
- package/dist/build/prerender-server-pool.js +194 -0
- package/dist/build/prerender.js +86 -22
- package/dist/build/run-prerender.js +2 -1
- package/dist/check.d.ts +4 -6
- package/dist/check.js +8 -9
- package/dist/cli.js +1 -1
- package/dist/client/vinext-next-data.d.ts +4 -1
- package/dist/config/config-matchers.js +33 -11
- package/dist/config/next-config.d.ts +36 -6
- package/dist/config/next-config.js +16 -2
- package/dist/entries/app-browser-entry.js +5 -1
- package/dist/entries/app-rsc-entry.d.ts +3 -2
- package/dist/entries/app-rsc-entry.js +4 -0
- package/dist/entries/pages-client-entry.js +14 -3
- package/dist/entries/pages-server-entry.js +18 -4
- package/dist/index.js +320 -25
- package/dist/packages/cloudflare/src/cache/kv-data-adapter.runtime.js +8 -1
- package/dist/packages/cloudflare/src/deploy.js +1 -5
- package/dist/packages/cloudflare/src/tpr.js +26 -5
- package/dist/plugins/fonts.js +1 -1
- package/dist/plugins/ignore-dynamic-requests.js +1 -1
- package/dist/plugins/og-assets.js +2 -1
- package/dist/plugins/optimize-imports.js +1 -1
- package/dist/plugins/rsc-reference-validation-normalizer.d.ts +12 -0
- package/dist/plugins/rsc-reference-validation-normalizer.js +48 -0
- package/dist/plugins/sass.d.ts +17 -1
- package/dist/plugins/sass.js +74 -1
- package/dist/plugins/styled-jsx.d.ts +16 -0
- package/dist/plugins/styled-jsx.js +149 -0
- package/dist/routing/app-route-graph.js +22 -16
- package/dist/routing/file-matcher.d.ts +8 -1
- package/dist/routing/file-matcher.js +15 -3
- package/dist/server/app-browser-entry.js +46 -14
- package/dist/server/app-browser-navigation-controller.js +1 -1
- package/dist/server/app-browser-server-action-client.js +5 -3
- package/dist/server/app-browser-state.d.ts +1 -0
- package/dist/server/app-browser-state.js +2 -2
- package/dist/server/app-browser-visible-commit.js +1 -1
- package/dist/server/app-page-boundary.js +2 -1
- package/dist/server/app-page-cache-finalizer.d.ts +1 -0
- package/dist/server/app-page-cache-finalizer.js +3 -3
- package/dist/server/app-page-cache.js +23 -6
- package/dist/server/app-page-dispatch.d.ts +1 -0
- package/dist/server/app-page-dispatch.js +25 -8
- package/dist/server/app-page-element-builder.js +1 -0
- package/dist/server/app-page-execution.js +2 -1
- package/dist/server/app-page-render-identity.d.ts +1 -0
- package/dist/server/app-page-render-identity.js +2 -1
- package/dist/server/app-page-render.d.ts +2 -0
- package/dist/server/app-page-render.js +67 -16
- package/dist/server/app-page-response.d.ts +7 -0
- package/dist/server/app-page-response.js +16 -4
- package/dist/server/app-page-stream.d.ts +2 -1
- package/dist/server/app-page-stream.js +1 -1
- package/dist/server/app-route-handler-execution.js +1 -1
- package/dist/server/app-route-tree-prefetch.d.ts +43 -0
- package/dist/server/app-route-tree-prefetch.js +187 -0
- package/dist/server/app-router-entry.js +1 -1
- package/dist/server/app-rsc-cache-busting.d.ts +2 -1
- package/dist/server/app-rsc-cache-busting.js +9 -4
- package/dist/server/app-rsc-handler.d.ts +6 -0
- package/dist/server/app-rsc-handler.js +89 -11
- package/dist/server/app-rsc-render-mode.d.ts +3 -2
- package/dist/server/app-rsc-render-mode.js +4 -1
- package/dist/server/app-rsc-request-normalization.d.ts +3 -4
- package/dist/server/app-rsc-request-normalization.js +4 -5
- package/dist/server/app-server-action-execution.js +4 -3
- package/dist/server/app-ssr-entry.js +3 -3
- package/dist/server/cache-control.d.ts +3 -1
- package/dist/server/cache-control.js +13 -1
- package/dist/server/dev-server.d.ts +11 -1
- package/dist/server/dev-server.js +78 -20
- package/dist/server/headers.d.ts +6 -2
- package/dist/server/headers.js +11 -5
- package/dist/server/isr-cache.d.ts +2 -1
- package/dist/server/isr-cache.js +7 -3
- package/dist/server/pages-data-route.d.ts +4 -2
- package/dist/server/pages-data-route.js +18 -4
- package/dist/server/pages-dev-module-url.d.ts +2 -1
- package/dist/server/pages-dev-module-url.js +6 -3
- package/dist/server/pages-node-compat.d.ts +12 -1
- package/dist/server/pages-node-compat.js +50 -1
- package/dist/server/pages-page-data.d.ts +9 -0
- package/dist/server/pages-page-data.js +17 -9
- package/dist/server/pages-page-handler.js +19 -7
- package/dist/server/pages-page-response.d.ts +1 -0
- package/dist/server/pages-page-response.js +3 -2
- package/dist/server/pages-request-pipeline.d.ts +8 -6
- package/dist/server/pages-request-pipeline.js +30 -6
- package/dist/server/pages-router-entry.js +1 -1
- package/dist/server/prod-server.d.ts +4 -2
- package/dist/server/prod-server.js +38 -22
- package/dist/server/request-pipeline.js +1 -1
- package/dist/shims/cache-handler.js +8 -1
- package/dist/shims/cache.js +3 -0
- package/dist/shims/fetch-cache.d.ts +3 -1
- package/dist/shims/fetch-cache.js +77 -52
- package/dist/shims/form.d.ts +1 -1
- package/dist/shims/internal/app-prefetch-fetch-queue.d.ts +10 -0
- package/dist/shims/internal/app-prefetch-fetch-queue.js +61 -0
- package/dist/shims/internal/hybrid-client-route-owner.d.ts +2 -1
- package/dist/shims/internal/hybrid-client-route-owner.js +34 -1
- package/dist/shims/internal/pages-data-fetch-dedup.d.ts +2 -1
- package/dist/shims/internal/pages-data-fetch-dedup.js +13 -2
- package/dist/shims/internal/pages-data-target.d.ts +8 -3
- package/dist/shims/internal/pages-data-target.js +9 -4
- package/dist/shims/link.d.ts +1 -1
- package/dist/shims/link.js +179 -42
- package/dist/shims/navigation.d.ts +15 -3
- package/dist/shims/navigation.js +202 -39
- package/dist/shims/navigation.react-server.js +1 -1
- package/dist/shims/request-context.js +18 -0
- package/dist/shims/router.js +31 -15
- package/dist/shims/unified-request-context.js +1 -0
- package/dist/typegen.js +1 -1
- package/dist/utils/middleware-request-headers.js +1 -1
- package/dist/utils/protocol-headers.d.ts +7 -1
- package/dist/utils/protocol-headers.js +7 -1
- package/dist/utils/vite-version.d.ts +2 -0
- package/dist/utils/vite-version.js +11 -1
- package/package.json +2 -2
package/dist/shims/navigation.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { stripBasePath } from "../utils/base-path.js";
|
|
2
|
-
import { VINEXT_DYNAMIC_STALE_TIME_HEADER, VINEXT_MOUNTED_SLOTS_HEADER, VINEXT_PARAMS_HEADER } from "../server/headers.js";
|
|
2
|
+
import { VINEXT_DYNAMIC_STALE_TIME_HEADER, VINEXT_MOUNTED_SLOTS_HEADER, VINEXT_PARAMS_HEADER, VINEXT_RENDERED_PATH_AND_SEARCH_HEADER } from "../server/headers.js";
|
|
3
3
|
import { assertSafeNavigationUrl } from "./url-safety.js";
|
|
4
4
|
import { AppElementsWire } from "../server/app-elements-wire.js";
|
|
5
5
|
import "../server/app-elements.js";
|
|
@@ -12,7 +12,7 @@ import { BailoutToCSRError, DynamicServerError, HTTP_ERROR_FALLBACK_ERROR_CODE,
|
|
|
12
12
|
import { isBotUserAgent } from "../utils/html-limited-bots.js";
|
|
13
13
|
import { clearAppNavigationFailureTarget, stageAppNavigationFailureTarget } from "../client/app-nav-failure-handler.js";
|
|
14
14
|
import { beginAppRouterScrollIntent, clearAppRouterScrollIntent, consumeAppRouterScrollIntent, getPendingAppRouterScrollIntent } from "./app-router-scroll-state.js";
|
|
15
|
-
import { VINEXT_RSC_COMPATIBILITY_ID_HEADER, createRscRequestHeaders, createRscRequestUrl, stripRscCacheBustingSearchParam } from "../server/app-rsc-cache-busting.js";
|
|
15
|
+
import { VINEXT_RSC_COMPATIBILITY_ID_HEADER, createRscRequestHeaders, createRscRequestUrl, stripRscCacheBustingSearchParam, stripRscSuffix } from "../server/app-rsc-cache-busting.js";
|
|
16
16
|
import { getNavigationRuntime, hasAppNavigationRuntime } from "../client/navigation-runtime.js";
|
|
17
17
|
import { notifyAppRouterTransitionStart } from "../client/instrumentation-client-state.js";
|
|
18
18
|
import { PUBLIC_INITIAL_BFCACHE_ID } from "../server/app-bfcache-id.js";
|
|
@@ -23,6 +23,7 @@ import { navigationPlanner } from "../server/navigation-planner.js";
|
|
|
23
23
|
import { ReadonlyURLSearchParams } from "./readonly-url-search-params.js";
|
|
24
24
|
import { getPagesNavigationContext } from "./internal/pages-router-accessor.js";
|
|
25
25
|
import { resolveHybridClientRouteOwner } from "./internal/hybrid-client-route-owner.js";
|
|
26
|
+
import { releaseAppPrefetchFetchSlot, scheduleAppPrefetchFetch } from "./internal/app-prefetch-fetch-queue.js";
|
|
26
27
|
import { UnrecognizedActionError, unstable_isUnrecognizedActionError } from "./unrecognized-action-error.js";
|
|
27
28
|
import * as React$1 from "react";
|
|
28
29
|
//#region src/shims/navigation.ts
|
|
@@ -54,8 +55,9 @@ const PAGES_NAVIGATION_NOTIFY_KEY = Symbol.for("vinext.navigation.pagesNavigatio
|
|
|
54
55
|
const isServer = typeof window === "undefined";
|
|
55
56
|
/** basePath from next.config.js, injected by the plugin at build time */
|
|
56
57
|
const __basePath = process.env.__NEXT_ROUTER_BASEPATH ?? "";
|
|
57
|
-
/** Maximum
|
|
58
|
-
const MAX_PREFETCH_CACHE_SIZE = 50;
|
|
58
|
+
/** Maximum buffered bytes in the RSC prefetch cache. Mirrors Next.js' 50 MB LRU. */
|
|
59
|
+
const MAX_PREFETCH_CACHE_SIZE = 50 * 1024 * 1024;
|
|
60
|
+
const PREFETCH_CACHE_EVICTION_TARGET_SIZE = MAX_PREFETCH_CACHE_SIZE * .9;
|
|
59
61
|
/**
|
|
60
62
|
* TTL for prefetch cache entries in ms.
|
|
61
63
|
*
|
|
@@ -161,6 +163,13 @@ function normalizeRscCacheLookupUrl(rscUrl) {
|
|
|
161
163
|
return null;
|
|
162
164
|
}
|
|
163
165
|
}
|
|
166
|
+
function normalizeRscCacheLookupPathname(rscUrl) {
|
|
167
|
+
try {
|
|
168
|
+
return stripRscSuffix(new URL(rscUrl, "http://vinext.local").pathname);
|
|
169
|
+
} catch {
|
|
170
|
+
return null;
|
|
171
|
+
}
|
|
172
|
+
}
|
|
164
173
|
function parsePrefetchCacheKey(cacheKey) {
|
|
165
174
|
const separatorIndex = cacheKey.indexOf("\0");
|
|
166
175
|
if (separatorIndex === -1) return {
|
|
@@ -176,22 +185,25 @@ function isPrefetchCacheEntryCompatibleWithMountedSlots(entry, mountedSlotsHeade
|
|
|
176
185
|
if (resolvePrefetchCacheEntryMountedSlotsHeader(entry) === mountedSlotsHeader) return true;
|
|
177
186
|
return (entry.snapshot?.mountedSlotsHeader ?? null) === mountedSlotsHeader;
|
|
178
187
|
}
|
|
179
|
-
function findPrefetchCacheEntryForNavigation(rscUrl, interceptionContext, mountedSlotsHeader) {
|
|
180
|
-
const exactCacheKey = AppElementsWire.encodeCacheKey(rscUrl, interceptionContext);
|
|
188
|
+
function findPrefetchCacheEntryForNavigation(rscUrl, interceptionContext, mountedSlotsHeader, additionalRscUrls = []) {
|
|
181
189
|
const cache = getPrefetchCache();
|
|
182
|
-
const
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
190
|
+
const rscUrls = [rscUrl, ...additionalRscUrls];
|
|
191
|
+
for (const lookupRscUrl of rscUrls) {
|
|
192
|
+
const exactCacheKey = AppElementsWire.encodeCacheKey(lookupRscUrl, interceptionContext);
|
|
193
|
+
const exactEntry = cache.get(exactCacheKey);
|
|
194
|
+
if (exactEntry && exactEntry.cacheForNavigation !== false && isPrefetchCacheEntryCompatibleWithMountedSlots(exactEntry, mountedSlotsHeader)) return {
|
|
195
|
+
cacheKey: exactCacheKey,
|
|
196
|
+
entry: exactEntry
|
|
197
|
+
};
|
|
198
|
+
}
|
|
199
|
+
const normalizedTargets = new Set(rscUrls.map((lookupRscUrl) => normalizeRscCacheLookupUrl(lookupRscUrl)).filter((lookupRscUrl) => lookupRscUrl !== null));
|
|
200
|
+
if (normalizedTargets.size === 0) return null;
|
|
189
201
|
for (const [cacheKey, entry] of cache) {
|
|
190
|
-
if (cacheKey === exactCacheKey) continue;
|
|
191
202
|
if (entry.cacheForNavigation === false) continue;
|
|
192
203
|
const source = parsePrefetchCacheKey(cacheKey);
|
|
193
204
|
if (source.interceptionContext !== interceptionContext) continue;
|
|
194
|
-
|
|
205
|
+
const normalizedSource = normalizeRscCacheLookupUrl(source.rscUrl);
|
|
206
|
+
if (normalizedSource === null || !normalizedTargets.has(normalizedSource)) continue;
|
|
195
207
|
if (!isPrefetchCacheEntryCompatibleWithMountedSlots(entry, mountedSlotsHeader)) continue;
|
|
196
208
|
return {
|
|
197
209
|
cacheKey,
|
|
@@ -201,31 +213,100 @@ function findPrefetchCacheEntryForNavigation(rscUrl, interceptionContext, mounte
|
|
|
201
213
|
return null;
|
|
202
214
|
}
|
|
203
215
|
function hasPrefetchCacheEntryForNavigation(rscUrl, interceptionContext = null, mountedSlotsHeader = null, options = {}) {
|
|
204
|
-
const match = findPrefetchCacheEntryForNavigation(rscUrl, interceptionContext, mountedSlotsHeader);
|
|
216
|
+
const match = findPrefetchCacheEntryForNavigation(rscUrl, interceptionContext, mountedSlotsHeader, options.additionalRscUrls);
|
|
205
217
|
if (match === null) return false;
|
|
206
|
-
if (match.entry.pending !== void 0)
|
|
207
|
-
|
|
218
|
+
if (match.entry.pending !== void 0) {
|
|
219
|
+
touchPrefetchCacheEntry(getPrefetchCache(), match.cacheKey, match.entry);
|
|
220
|
+
return true;
|
|
221
|
+
}
|
|
222
|
+
if (resolvePrefetchCacheEntryExpiresAt(match.entry) > Date.now()) {
|
|
223
|
+
touchPrefetchCacheEntry(getPrefetchCache(), match.cacheKey, match.entry);
|
|
224
|
+
return true;
|
|
225
|
+
}
|
|
208
226
|
deletePrefetchCacheEntry(getPrefetchCache(), getPrefetchedUrls(), match.cacheKey, match.entry, options.notifyInvalidation ?? true);
|
|
209
227
|
return false;
|
|
210
228
|
}
|
|
229
|
+
function hasSearchAgnosticPrefetchShellForRoute(rscUrl, interceptionContext = null, mountedSlotsHeader = null) {
|
|
230
|
+
const normalizedTargetPathname = normalizeRscCacheLookupPathname(rscUrl);
|
|
231
|
+
if (normalizedTargetPathname === null) return false;
|
|
232
|
+
const cache = getPrefetchCache();
|
|
233
|
+
for (const [cacheKey, entry] of cache) {
|
|
234
|
+
if (entry.searchAgnosticShell !== true) continue;
|
|
235
|
+
const source = parsePrefetchCacheKey(cacheKey);
|
|
236
|
+
if (source.interceptionContext !== interceptionContext) continue;
|
|
237
|
+
if (normalizeRscCacheLookupPathname(source.rscUrl) !== normalizedTargetPathname) continue;
|
|
238
|
+
if (!isPrefetchCacheEntryCompatibleWithMountedSlots(entry, mountedSlotsHeader)) continue;
|
|
239
|
+
if (entry.pending !== void 0) return true;
|
|
240
|
+
if (resolvePrefetchCacheEntryExpiresAt(entry) > Date.now()) return true;
|
|
241
|
+
deletePrefetchCacheEntry(cache, getPrefetchedUrls(), cacheKey, entry, true);
|
|
242
|
+
}
|
|
243
|
+
return false;
|
|
244
|
+
}
|
|
245
|
+
function getPrefetchCacheEntrySize(entry) {
|
|
246
|
+
return entry.snapshot?.buffer.byteLength ?? entry.size ?? 0;
|
|
247
|
+
}
|
|
248
|
+
let trackedPrefetchCache = null;
|
|
249
|
+
let trackedPrefetchCacheByteSize = 0;
|
|
250
|
+
function getPrefetchCacheByteSize(cache) {
|
|
251
|
+
if (trackedPrefetchCache === cache) return trackedPrefetchCacheByteSize;
|
|
252
|
+
let total = 0;
|
|
253
|
+
const seen = /* @__PURE__ */ new Set();
|
|
254
|
+
for (const entry of cache.values()) {
|
|
255
|
+
if (seen.has(entry)) continue;
|
|
256
|
+
seen.add(entry);
|
|
257
|
+
total += getPrefetchCacheEntrySize(entry);
|
|
258
|
+
}
|
|
259
|
+
trackedPrefetchCache = cache;
|
|
260
|
+
trackedPrefetchCacheByteSize = total;
|
|
261
|
+
return total;
|
|
262
|
+
}
|
|
263
|
+
function adjustPrefetchCacheByteSize(cache, delta) {
|
|
264
|
+
if (trackedPrefetchCache !== cache) return;
|
|
265
|
+
trackedPrefetchCacheByteSize = Math.max(0, trackedPrefetchCacheByteSize + delta);
|
|
266
|
+
}
|
|
267
|
+
function touchPrefetchCacheEntry(cache, cacheKey, entry) {
|
|
268
|
+
if (cache.get(cacheKey) !== entry) return;
|
|
269
|
+
cache.delete(cacheKey);
|
|
270
|
+
cache.set(cacheKey, entry);
|
|
271
|
+
for (const key of entry.cacheKeys ?? []) {
|
|
272
|
+
if (key === cacheKey || cache.get(key) !== entry) continue;
|
|
273
|
+
cache.delete(key);
|
|
274
|
+
cache.set(key, entry);
|
|
275
|
+
}
|
|
276
|
+
}
|
|
211
277
|
/**
|
|
212
|
-
* Evict prefetch cache entries if
|
|
213
|
-
*
|
|
278
|
+
* Evict prefetch cache entries if buffered payloads exceed the byte budget.
|
|
279
|
+
* Sweeps expired entries only after the cheap byte-budget check says cleanup is
|
|
280
|
+
* needed, then evicts least-recently-used entries down to the target size.
|
|
214
281
|
*/
|
|
215
282
|
function evictPrefetchCacheIfNeeded() {
|
|
216
283
|
const cache = getPrefetchCache();
|
|
217
|
-
|
|
284
|
+
let totalSize = getPrefetchCacheByteSize(cache);
|
|
285
|
+
if (totalSize <= 52428800) return;
|
|
218
286
|
const now = Date.now();
|
|
219
287
|
const prefetched = getPrefetchedUrls();
|
|
220
288
|
for (const [key, entry] of cache) if (resolvePrefetchCacheEntryExpiresAt(entry) <= now) deletePrefetchCacheEntry(cache, prefetched, key, entry, true);
|
|
221
|
-
|
|
289
|
+
totalSize = getPrefetchCacheByteSize(cache);
|
|
290
|
+
if (totalSize <= 52428800) return;
|
|
291
|
+
let inspectedEntries = 0;
|
|
292
|
+
while (totalSize > PREFETCH_CACHE_EVICTION_TARGET_SIZE && inspectedEntries < cache.size) {
|
|
222
293
|
const oldest = cache.keys().next().value;
|
|
223
294
|
if (oldest !== void 0) {
|
|
224
295
|
const entry = cache.get(oldest);
|
|
225
|
-
if (entry)
|
|
226
|
-
|
|
296
|
+
if (entry) {
|
|
297
|
+
const entrySize = getPrefetchCacheEntrySize(entry);
|
|
298
|
+
if (entry.pending !== void 0 && entrySize === 0) {
|
|
299
|
+
touchPrefetchCacheEntry(cache, oldest, entry);
|
|
300
|
+
inspectedEntries += 1;
|
|
301
|
+
continue;
|
|
302
|
+
}
|
|
303
|
+
totalSize -= entrySize;
|
|
304
|
+
deletePrefetchCacheEntry(cache, prefetched, oldest, entry, true);
|
|
305
|
+
inspectedEntries = 0;
|
|
306
|
+
} else {
|
|
227
307
|
cache.delete(oldest);
|
|
228
308
|
prefetched.delete(oldest);
|
|
309
|
+
inspectedEntries += 1;
|
|
229
310
|
}
|
|
230
311
|
} else break;
|
|
231
312
|
}
|
|
@@ -249,8 +330,13 @@ function notifyPrefetchInvalidated(entry) {
|
|
|
249
330
|
}
|
|
250
331
|
}
|
|
251
332
|
function deletePrefetchCacheEntry(cache, prefetched, cacheKey, entry, notify) {
|
|
252
|
-
cache
|
|
253
|
-
|
|
333
|
+
adjustPrefetchCacheByteSize(cache, -getPrefetchCacheEntrySize(entry));
|
|
334
|
+
const cacheKeys = entry.cacheKeys ?? new Set([cacheKey]);
|
|
335
|
+
for (const key of cacheKeys) {
|
|
336
|
+
if (cache.get(key) === entry) cache.delete(key);
|
|
337
|
+
prefetched.delete(key);
|
|
338
|
+
}
|
|
339
|
+
entry.cacheKeys = void 0;
|
|
254
340
|
if (notify) notifyPrefetchInvalidated(entry);
|
|
255
341
|
else {
|
|
256
342
|
clearPrefetchInvalidation(entry);
|
|
@@ -295,19 +381,22 @@ function seedPrefetchResponseSnapshot(rscUrl, snapshot, interceptionContext = nu
|
|
|
295
381
|
const cache = getPrefetchCache();
|
|
296
382
|
const existing = cache.get(cacheKey);
|
|
297
383
|
if (existing) deletePrefetchCacheEntry(cache, getPrefetchedUrls(), cacheKey, existing, false);
|
|
298
|
-
evictPrefetchCacheIfNeeded();
|
|
299
384
|
const timestamp = Date.now();
|
|
300
385
|
const entry = {
|
|
301
386
|
cacheForNavigation: true,
|
|
387
|
+
cacheKeys: new Set([cacheKey]),
|
|
302
388
|
expiresAt: resolveCachedRscResponseExpiresAt(timestamp, snapshot, fallbackTtlMs),
|
|
303
389
|
mountedSlotsHeader,
|
|
304
390
|
outcome: "cache-seeded",
|
|
391
|
+
size: snapshot.buffer.byteLength,
|
|
305
392
|
snapshot,
|
|
306
393
|
timestamp
|
|
307
394
|
};
|
|
308
395
|
cache.set(cacheKey, entry);
|
|
396
|
+
adjustPrefetchCacheByteSize(cache, snapshot.buffer.byteLength);
|
|
309
397
|
getPrefetchedUrls().add(cacheKey);
|
|
310
398
|
schedulePrefetchInvalidation(cacheKey, entry);
|
|
399
|
+
evictPrefetchCacheIfNeeded();
|
|
311
400
|
}
|
|
312
401
|
function deletePrefetchResponseSnapshot(rscUrl, snapshot, interceptionContext = null) {
|
|
313
402
|
const cacheKey = AppElementsWire.encodeCacheKey(rscUrl, interceptionContext);
|
|
@@ -334,27 +423,37 @@ function deletePrefetchResponseSnapshot(rscUrl, snapshot, interceptionContext =
|
|
|
334
423
|
*/
|
|
335
424
|
function storePrefetchResponse(rscUrl, response, interceptionContext = null, options) {
|
|
336
425
|
const cacheKey = AppElementsWire.encodeCacheKey(rscUrl, interceptionContext);
|
|
337
|
-
|
|
426
|
+
const cache = getPrefetchCache();
|
|
427
|
+
const prefetched = getPrefetchedUrls();
|
|
428
|
+
const existing = cache.get(cacheKey);
|
|
429
|
+
if (existing) deletePrefetchCacheEntry(cache, prefetched, cacheKey, existing, false);
|
|
338
430
|
const entry = {
|
|
431
|
+
cacheKeys: new Set([cacheKey]),
|
|
339
432
|
mountedSlotsHeader: null,
|
|
340
433
|
outcome: "pending",
|
|
341
434
|
timestamp: Date.now()
|
|
342
435
|
};
|
|
343
436
|
addPrefetchInvalidationCallback(entry, options?.onInvalidate);
|
|
344
437
|
entry.pending = snapshotRscResponse(response).then((snapshot) => {
|
|
438
|
+
if (cache.get(cacheKey) !== entry) return;
|
|
439
|
+
const previousSize = getPrefetchCacheEntrySize(entry);
|
|
345
440
|
entry.mountedSlotsHeader = snapshot.mountedSlotsHeader ?? null;
|
|
346
441
|
entry.snapshot = snapshot;
|
|
442
|
+
entry.size = snapshot.buffer.byteLength;
|
|
443
|
+
adjustPrefetchCacheByteSize(cache, entry.size - previousSize);
|
|
347
444
|
entry.expiresAt = resolveCachedRscResponseExpiresAt(entry.timestamp, snapshot, PREFETCH_CACHE_TTL);
|
|
445
|
+
evictPrefetchCacheIfNeeded();
|
|
348
446
|
}).catch(() => {
|
|
349
|
-
deletePrefetchCacheEntry(
|
|
447
|
+
deletePrefetchCacheEntry(cache, prefetched, cacheKey, entry, false);
|
|
350
448
|
}).finally(() => {
|
|
449
|
+
if (cache.get(cacheKey) !== entry) return;
|
|
351
450
|
entry.pending = void 0;
|
|
352
451
|
if (entry.snapshot) {
|
|
353
452
|
entry.outcome = "cache-seeded";
|
|
354
453
|
schedulePrefetchInvalidation(cacheKey, entry);
|
|
355
454
|
}
|
|
356
455
|
});
|
|
357
|
-
|
|
456
|
+
cache.set(cacheKey, entry);
|
|
358
457
|
}
|
|
359
458
|
function createCachedRscResponseSnapshot(response, buffer, responseUrl = null) {
|
|
360
459
|
const dynamicStaleTimeSeconds = parseDynamicStaleTimeSeconds(response.headers.get(VINEXT_DYNAMIC_STALE_TIME_HEADER));
|
|
@@ -365,15 +464,29 @@ function createCachedRscResponseSnapshot(response, buffer, responseUrl = null) {
|
|
|
365
464
|
...dynamicStaleTimeSeconds !== void 0 ? { dynamicStaleTimeSeconds } : {},
|
|
366
465
|
mountedSlotsHeader: response.headers.get(VINEXT_MOUNTED_SLOTS_HEADER),
|
|
367
466
|
paramsHeader: response.headers.get(VINEXT_PARAMS_HEADER),
|
|
467
|
+
renderedPathAndSearch: parseRenderedPathAndSearchHeader(response.headers.get(VINEXT_RENDERED_PATH_AND_SEARCH_HEADER)),
|
|
368
468
|
url: responseUrl ?? response.url
|
|
369
469
|
};
|
|
370
470
|
}
|
|
471
|
+
function parseRenderedPathAndSearchHeader(value) {
|
|
472
|
+
if (value === null || value === "") return null;
|
|
473
|
+
try {
|
|
474
|
+
const decoded = decodeURIComponent(value);
|
|
475
|
+
return decoded.startsWith("/") ? decoded : null;
|
|
476
|
+
} catch {
|
|
477
|
+
return null;
|
|
478
|
+
}
|
|
479
|
+
}
|
|
371
480
|
/**
|
|
372
481
|
* Snapshot an RSC response to an ArrayBuffer for caching and replay.
|
|
373
482
|
* Consumes the response body and stores it with content-type and URL metadata.
|
|
374
483
|
*/
|
|
375
484
|
async function snapshotRscResponse(response) {
|
|
376
|
-
|
|
485
|
+
try {
|
|
486
|
+
return createCachedRscResponseSnapshot(response, await response.arrayBuffer());
|
|
487
|
+
} finally {
|
|
488
|
+
releaseAppPrefetchFetchSlot(response);
|
|
489
|
+
}
|
|
377
490
|
}
|
|
378
491
|
/**
|
|
379
492
|
* Reconstruct a Response from a cached RSC snapshot.
|
|
@@ -396,6 +509,7 @@ function restoreRscResponse(cached, copy = true) {
|
|
|
396
509
|
if (cached.compatibilityIdHeader != null) headers.set(VINEXT_RSC_COMPATIBILITY_ID_HEADER, cached.compatibilityIdHeader);
|
|
397
510
|
if (isDynamicStaleTimeSeconds(cached.dynamicStaleTimeSeconds)) headers.set(VINEXT_DYNAMIC_STALE_TIME_HEADER, String(cached.dynamicStaleTimeSeconds));
|
|
398
511
|
if (cached.paramsHeader != null) headers.set(VINEXT_PARAMS_HEADER, cached.paramsHeader);
|
|
512
|
+
if (cached.renderedPathAndSearch != null) headers.set(VINEXT_RENDERED_PATH_AND_SEARCH_HEADER, encodeURIComponent(cached.renderedPathAndSearch));
|
|
399
513
|
return new Response(copy ? cached.buffer.slice(0) : cached.buffer, {
|
|
400
514
|
status: 200,
|
|
401
515
|
headers
|
|
@@ -413,22 +527,38 @@ function prefetchRscResponse(rscUrl, fetchPromise, interceptionContext = null, m
|
|
|
413
527
|
const cache = getPrefetchCache();
|
|
414
528
|
const prefetched = getPrefetchedUrls();
|
|
415
529
|
const now = Date.now();
|
|
530
|
+
const existing = cache.get(cacheKey);
|
|
531
|
+
if (existing) deletePrefetchCacheEntry(cache, prefetched, cacheKey, existing, false);
|
|
416
532
|
const entry = {
|
|
417
533
|
cacheForNavigation: behavior.cacheForNavigation ?? true,
|
|
534
|
+
cacheKeys: new Set([cacheKey]),
|
|
418
535
|
mountedSlotsHeader,
|
|
419
536
|
optimisticRouteShell: behavior.optimisticRouteShell === true,
|
|
420
537
|
outcome: "pending",
|
|
538
|
+
prefetchKind: behavior.prefetchKind ?? (behavior.optimisticRouteShell === true ? "loading-shell" : "navigation"),
|
|
539
|
+
searchAgnosticShell: behavior.searchAgnosticShell === true,
|
|
421
540
|
timestamp: now
|
|
422
541
|
};
|
|
423
542
|
addPrefetchInvalidationCallback(entry, options?.onInvalidate);
|
|
424
543
|
entry.pending = fetchPromise.then(async (response) => {
|
|
425
544
|
if (response.ok) {
|
|
426
|
-
|
|
545
|
+
const snapshot = await snapshotRscResponse(response);
|
|
546
|
+
if (cache.get(cacheKey) !== entry) return;
|
|
547
|
+
const previousSize = getPrefetchCacheEntrySize(entry);
|
|
548
|
+
entry.snapshot = snapshot;
|
|
549
|
+
entry.size = snapshot.buffer.byteLength;
|
|
550
|
+
adjustPrefetchCacheByteSize(cache, entry.size - previousSize);
|
|
427
551
|
entry.expiresAt = resolvePrefetchedRscResponseExpiresAt(entry.timestamp, entry.snapshot, behavior.fallbackTtlMs ?? PREFETCH_CACHE_TTL);
|
|
428
|
-
|
|
552
|
+
addRenderedPathAndSearchPrefetchAlias(cache, prefetched, cacheKey, entry);
|
|
553
|
+
evictPrefetchCacheIfNeeded();
|
|
554
|
+
} else {
|
|
555
|
+
releaseAppPrefetchFetchSlot(response);
|
|
556
|
+
deletePrefetchCacheEntry(cache, prefetched, cacheKey, entry, false);
|
|
557
|
+
}
|
|
429
558
|
}).catch(() => {
|
|
430
559
|
deletePrefetchCacheEntry(cache, prefetched, cacheKey, entry, false);
|
|
431
560
|
}).finally(() => {
|
|
561
|
+
if (cache.get(cacheKey) !== entry) return;
|
|
432
562
|
entry.pending = void 0;
|
|
433
563
|
if (entry.snapshot) {
|
|
434
564
|
entry.outcome = "cache-seeded";
|
|
@@ -438,6 +568,36 @@ function prefetchRscResponse(rscUrl, fetchPromise, interceptionContext = null, m
|
|
|
438
568
|
cache.set(cacheKey, entry);
|
|
439
569
|
evictPrefetchCacheIfNeeded();
|
|
440
570
|
}
|
|
571
|
+
function addRenderedPathAndSearchPrefetchAlias(cache, prefetched, primaryCacheKey, entry) {
|
|
572
|
+
if (entry.cacheForNavigation === false) return;
|
|
573
|
+
const renderedPathAndSearch = entry.snapshot?.renderedPathAndSearch;
|
|
574
|
+
if (!renderedPathAndSearch) return;
|
|
575
|
+
const source = parsePrefetchCacheKey(primaryCacheKey);
|
|
576
|
+
const aliasCacheKey = AppElementsWire.encodeCacheKey(renderedPathAndSearch, source.interceptionContext);
|
|
577
|
+
if (aliasCacheKey === primaryCacheKey) return;
|
|
578
|
+
const existing = cache.get(aliasCacheKey);
|
|
579
|
+
if (existing && existing !== entry) deletePrefetchCacheEntry(cache, prefetched, aliasCacheKey, existing, false);
|
|
580
|
+
entry.cacheKeys ??= new Set([primaryCacheKey]);
|
|
581
|
+
entry.cacheKeys.add(aliasCacheKey);
|
|
582
|
+
cache.set(aliasCacheKey, entry);
|
|
583
|
+
prefetched.add(aliasCacheKey);
|
|
584
|
+
}
|
|
585
|
+
function peekPrefetchResponseForNavigation(rscUrl, interceptionContext = null, mountedSlotsHeader = null) {
|
|
586
|
+
const match = findPrefetchCacheEntryForNavigation(rscUrl, interceptionContext, mountedSlotsHeader);
|
|
587
|
+
if (!match) return null;
|
|
588
|
+
const { cacheKey, entry } = match;
|
|
589
|
+
if (entry.pending || entry.outcome !== "cache-seeded") return null;
|
|
590
|
+
if (entry.cacheForNavigation === false || !entry.snapshot) return null;
|
|
591
|
+
if (resolvePrefetchCacheEntryExpiresAt(entry) <= Date.now()) {
|
|
592
|
+
deletePrefetchCacheEntry(getPrefetchCache(), getPrefetchedUrls(), cacheKey, entry, true);
|
|
593
|
+
return null;
|
|
594
|
+
}
|
|
595
|
+
if (entry.expiresAt !== void 0 || entry.snapshot.expiresAt !== void 0) return {
|
|
596
|
+
...entry.snapshot,
|
|
597
|
+
expiresAt: resolvePrefetchCacheEntryExpiresAt(entry)
|
|
598
|
+
};
|
|
599
|
+
return entry.snapshot;
|
|
600
|
+
}
|
|
441
601
|
/**
|
|
442
602
|
* Consume a prefetched response for a given rscUrl.
|
|
443
603
|
* Only returns settled (non-pending) snapshots synchronously.
|
|
@@ -451,9 +611,12 @@ function consumePrefetchResponse(rscUrl, interceptionContext = null, mountedSlot
|
|
|
451
611
|
const match = findPrefetchCacheEntryForNavigation(rscUrl, interceptionContext, mountedSlotsHeader);
|
|
452
612
|
if (!match) return null;
|
|
453
613
|
const { cacheKey, entry } = match;
|
|
614
|
+
return consumeMatchedPrefetchResponse(cacheKey, entry, mountedSlotsHeader);
|
|
615
|
+
}
|
|
616
|
+
function consumeMatchedPrefetchResponse(cacheKey, entry, mountedSlotsHeader) {
|
|
454
617
|
if (entry.pending || entry.outcome !== "cache-seeded") return null;
|
|
455
618
|
if (entry.cacheForNavigation === false) return null;
|
|
456
|
-
deletePrefetchCacheEntry(
|
|
619
|
+
deletePrefetchCacheEntry(getPrefetchCache(), getPrefetchedUrls(), cacheKey, entry, false);
|
|
457
620
|
if (entry.snapshot) {
|
|
458
621
|
if (!isPrefetchCacheEntryCompatibleWithMountedSlots(entry, mountedSlotsHeader)) return null;
|
|
459
622
|
if (resolvePrefetchCacheEntryExpiresAt(entry) <= Date.now()) return null;
|
|
@@ -467,7 +630,7 @@ function consumePrefetchResponse(rscUrl, interceptionContext = null, mountedSlot
|
|
|
467
630
|
}
|
|
468
631
|
async function consumePrefetchResponseForNavigation(rscUrl, interceptionContext = null, mountedSlotsHeader = null, options) {
|
|
469
632
|
const cache = getPrefetchCache();
|
|
470
|
-
const match = findPrefetchCacheEntryForNavigation(rscUrl, interceptionContext, mountedSlotsHeader);
|
|
633
|
+
const match = findPrefetchCacheEntryForNavigation(rscUrl, interceptionContext, mountedSlotsHeader, options?.additionalRscUrls);
|
|
471
634
|
if (!match) return null;
|
|
472
635
|
const { cacheKey, entry } = match;
|
|
473
636
|
if (entry.pending !== void 0) {
|
|
@@ -475,7 +638,7 @@ async function consumePrefetchResponseForNavigation(rscUrl, interceptionContext
|
|
|
475
638
|
if (cache.get(cacheKey) !== entry) return null;
|
|
476
639
|
}
|
|
477
640
|
if (options?.shouldConsume?.() === false) return null;
|
|
478
|
-
return
|
|
641
|
+
return consumeMatchedPrefetchResponse(cacheKey, entry, mountedSlotsHeader);
|
|
479
642
|
}
|
|
480
643
|
const _CLIENT_NAV_STATE_KEY = Symbol.for("vinext.clientNavigationState");
|
|
481
644
|
const _MOUNTED_SLOTS_HEADER_KEY = Symbol.for("vinext.mountedSlotsHeader");
|
|
@@ -1095,11 +1258,11 @@ const _appRouter = {
|
|
|
1095
1258
|
return;
|
|
1096
1259
|
}
|
|
1097
1260
|
prefetched.add(cacheKey);
|
|
1098
|
-
prefetchRscResponse(rscUrl, fetch(rscUrl, {
|
|
1261
|
+
prefetchRscResponse(rscUrl, scheduleAppPrefetchFetch(() => fetch(rscUrl, {
|
|
1099
1262
|
headers,
|
|
1100
1263
|
credentials: "include",
|
|
1101
1264
|
priority: "low"
|
|
1102
|
-
}), interceptionContext, mountedSlotsHeader, options);
|
|
1265
|
+
}), "low"), interceptionContext, mountedSlotsHeader, options);
|
|
1103
1266
|
})().catch((error) => {
|
|
1104
1267
|
console.error("[vinext] RSC prefetch setup error:", error);
|
|
1105
1268
|
});
|
|
@@ -1238,4 +1401,4 @@ if (!isServer) {
|
|
|
1238
1401
|
}
|
|
1239
1402
|
}
|
|
1240
1403
|
//#endregion
|
|
1241
|
-
export { BailoutToCSRError, DYNAMIC_NAVIGATION_CACHE_TTL, DynamicServerError, GLOBAL_ACCESSORS_KEY, HTTP_ERROR_FALLBACK_ERROR_CODE, MAX_PREFETCH_CACHE_SIZE, PREFETCH_CACHE_TTL, ReadonlyURLSearchParams, RedirectType, ServerInsertedHTMLContext, UnrecognizedActionError, __basePath, _registerStateAccessors, activateNavigationSnapshot, appRouterInstance, applyAppRouterScrollFallback, clearPendingPathname, clearServerInsertedHTML, commitClientNavigationState, consumePrefetchResponse, consumePrefetchResponseForNavigation, createCachedRscResponseSnapshot, createClientNavigationRenderSnapshot, createSnapshotPathAndSearch, decodeRedirectError, deletePrefetchResponseSnapshot, flushServerInsertedHTML, forbidden, getAccessFallbackHTTPStatus, getBfcacheIdMapContext, getBfcacheSegmentIdContext, getClientNavigationRenderContext, getClientNavigationState, getClientParams, getCurrentInterceptionContext, getCurrentNextUrl, getLayoutSegmentContext, getMountedSlotsHeader, getNavigationContext, getPrefetchCache, getPrefetchInterceptionContext, getPrefetchedUrls, hasPrefetchCacheEntryForNavigation, invalidatePrefetchCache, isBailoutToCSRError, isDynamicServerError, isHTTPAccessFallbackError, isNextRouterError, isRedirectError, navigateClientSide, notFound, permanentRedirect, prefetchRscResponse, pushHistoryStateWithoutNotify, redirect, renderServerInsertedHTML, replaceClientParamsWithoutNotify, replaceHistoryStateWithoutNotify, resolveCachedRscResponseExpiresAt, resolveCachedRscResponseTtlMs, resolvePrefetchCacheEntryMountedSlotsHeader, restoreRscResponse, saveScrollPosition, seedPrefetchResponseSnapshot, setClientParams, setMountedSlotsHeader, setNavigationContext, setPendingPathname, snapshotRscResponse, storePrefetchResponse, unauthorized, unstable_isUnrecognizedActionError, unstable_rethrow, useClientNavigationRenderSnapshot, useParams, usePathname, useRouter, useSearchParams, useSelectedLayoutSegment, useSelectedLayoutSegments, useServerInsertedHTML };
|
|
1404
|
+
export { BailoutToCSRError, DYNAMIC_NAVIGATION_CACHE_TTL, DynamicServerError, GLOBAL_ACCESSORS_KEY, HTTP_ERROR_FALLBACK_ERROR_CODE, MAX_PREFETCH_CACHE_SIZE, PREFETCH_CACHE_TTL, ReadonlyURLSearchParams, RedirectType, ServerInsertedHTMLContext, UnrecognizedActionError, __basePath, _registerStateAccessors, activateNavigationSnapshot, appRouterInstance, applyAppRouterScrollFallback, clearPendingPathname, clearServerInsertedHTML, commitClientNavigationState, consumePrefetchResponse, consumePrefetchResponseForNavigation, createCachedRscResponseSnapshot, createClientNavigationRenderSnapshot, createSnapshotPathAndSearch, decodeRedirectError, deletePrefetchResponseSnapshot, flushServerInsertedHTML, forbidden, getAccessFallbackHTTPStatus, getBfcacheIdMapContext, getBfcacheSegmentIdContext, getClientNavigationRenderContext, getClientNavigationState, getClientParams, getCurrentInterceptionContext, getCurrentNextUrl, getLayoutSegmentContext, getMountedSlotsHeader, getNavigationContext, getPrefetchCache, getPrefetchInterceptionContext, getPrefetchedUrls, hasPrefetchCacheEntryForNavigation, hasSearchAgnosticPrefetchShellForRoute, invalidatePrefetchCache, isBailoutToCSRError, isDynamicServerError, isHTTPAccessFallbackError, isNextRouterError, isRedirectError, navigateClientSide, notFound, peekPrefetchResponseForNavigation, permanentRedirect, prefetchRscResponse, pushHistoryStateWithoutNotify, redirect, renderServerInsertedHTML, replaceClientParamsWithoutNotify, replaceHistoryStateWithoutNotify, resolveCachedRscResponseExpiresAt, resolveCachedRscResponseTtlMs, resolvePrefetchCacheEntryMountedSlotsHeader, restoreRscResponse, saveScrollPosition, seedPrefetchResponseSnapshot, setClientParams, setMountedSlotsHeader, setNavigationContext, setPendingPathname, snapshotRscResponse, storePrefetchResponse, unauthorized, unstable_isUnrecognizedActionError, unstable_rethrow, useClientNavigationRenderSnapshot, useParams, usePathname, useRouter, useSearchParams, useSelectedLayoutSegment, useSelectedLayoutSegments, useServerInsertedHTML };
|
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
import { GLOBAL_ACCESSORS_KEY, ServerInsertedHTMLContext, _registerStateAccessors, clearServerInsertedHTML, flushServerInsertedHTML, getLayoutSegmentContext, getNavigationContext, renderServerInsertedHTML, setNavigationContext } from "./navigation-context-state.js";
|
|
2
2
|
import { BailoutToCSRError, DynamicServerError, HTTP_ERROR_FALLBACK_ERROR_CODE, RedirectType, forbidden, getAccessFallbackHTTPStatus, isBailoutToCSRError, isDynamicServerError, isHTTPAccessFallbackError, isNextRouterError, isRedirectError, notFound, permanentRedirect, redirect, unauthorized, unstable_rethrow } from "./navigation-errors.js";
|
|
3
3
|
import "./navigation-server.js";
|
|
4
|
-
import { ReadonlyURLSearchParams } from "./readonly-url-search-params.js";
|
|
5
4
|
import { throwClientHookError } from "./client-hook-error.js";
|
|
5
|
+
import { ReadonlyURLSearchParams } from "./readonly-url-search-params.js";
|
|
6
6
|
//#region src/shims/navigation.react-server.ts
|
|
7
7
|
function usePathname() {
|
|
8
8
|
throwClientHookError("usePathname()");
|
|
@@ -24,6 +24,24 @@ import { getRequestContext, isInsideUnifiedScope, runWithUnifiedStateMutation }
|
|
|
24
24
|
* ctx?.waitUntil(somePromise);
|
|
25
25
|
*/
|
|
26
26
|
const _als = getOrCreateAls("vinext.requestContext.als");
|
|
27
|
+
const OPEN_NEXT_CLOUDFLARE_CONTEXT_SYMBOL = Symbol.for("__cloudflare-context__");
|
|
28
|
+
let openNextCloudflareContextFallback;
|
|
29
|
+
function installOpenNextCloudflareContextBridge() {
|
|
30
|
+
const descriptor = Object.getOwnPropertyDescriptor(globalThis, OPEN_NEXT_CLOUDFLARE_CONTEXT_SYMBOL);
|
|
31
|
+
if (descriptor && !descriptor.configurable) return;
|
|
32
|
+
openNextCloudflareContextFallback = descriptor && "value" in descriptor ? descriptor.value : descriptor?.get?.call(globalThis);
|
|
33
|
+
Object.defineProperty(globalThis, OPEN_NEXT_CLOUDFLARE_CONTEXT_SYMBOL, {
|
|
34
|
+
configurable: true,
|
|
35
|
+
get() {
|
|
36
|
+
const ctx = getRequestExecutionContext();
|
|
37
|
+
return ctx ? { ctx } : openNextCloudflareContextFallback;
|
|
38
|
+
},
|
|
39
|
+
set(value) {
|
|
40
|
+
openNextCloudflareContextFallback = value;
|
|
41
|
+
}
|
|
42
|
+
});
|
|
43
|
+
}
|
|
44
|
+
installOpenNextCloudflareContextBridge();
|
|
27
45
|
function runWithExecutionContext(ctx, fn) {
|
|
28
46
|
if (isInsideUnifiedScope()) return runWithUnifiedStateMutation((uCtx) => {
|
|
29
47
|
uCtx.executionContext = ctx;
|
package/dist/shims/router.js
CHANGED
|
@@ -22,7 +22,7 @@ import { scrollToHashTarget } from "./hash-scroll.js";
|
|
|
22
22
|
import { installPagesRouterRuntime, setPagesRouterPopStateHandler, setStampInitialHistoryState } from "./pages-router-runtime.js";
|
|
23
23
|
import { interpolateDynamicRouteHref } from "./internal/interpolate-as.js";
|
|
24
24
|
import { getCurrentBrowserLocale } from "./client-locale.js";
|
|
25
|
-
import { Component, Fragment, createElement, useContext, useEffect, useLayoutEffect, useMemo, useState } from "react";
|
|
25
|
+
import { Component, Fragment, StrictMode, createElement, useContext, useEffect, useLayoutEffect, useMemo, useState } from "react";
|
|
26
26
|
//#region src/shims/router.ts
|
|
27
27
|
/**
|
|
28
28
|
* next/router shim
|
|
@@ -1002,8 +1002,11 @@ async function resolveClientConfigRewrite(href) {
|
|
|
1002
1002
|
kind: "rewrite"
|
|
1003
1003
|
} : null;
|
|
1004
1004
|
}
|
|
1005
|
-
function getMiddlewarePagesDataFetchUrl(browserUrl) {
|
|
1006
|
-
|
|
1005
|
+
function getMiddlewarePagesDataFetchUrl(browserUrl, dataTarget) {
|
|
1006
|
+
const middlewareDataHref = getPagesMiddlewareDataHref(browserUrl, __basePath);
|
|
1007
|
+
if (!middlewareDataHref) return null;
|
|
1008
|
+
if (dataTarget?.dataKind === "static" && dataTarget.middlewareDataHref === middlewareDataHref && dataTarget.prefetchDataHref) return dataTarget.prefetchDataHref;
|
|
1009
|
+
return middlewareDataHref;
|
|
1007
1010
|
}
|
|
1008
1011
|
function getPagesDataCacheHref(dataHref) {
|
|
1009
1012
|
try {
|
|
@@ -1015,8 +1018,8 @@ function getPagesDataCacheHref(dataHref) {
|
|
|
1015
1018
|
function shouldEvictMiddlewareDataCache(middlewareEffect, dataTarget) {
|
|
1016
1019
|
return middlewareEffect?.redirectLocation != null || dataTarget?.dataKind !== "static";
|
|
1017
1020
|
}
|
|
1018
|
-
async function resolveMiddlewareDataEffect(browserUrl, signal) {
|
|
1019
|
-
const dataUrl = getMiddlewarePagesDataFetchUrl(browserUrl);
|
|
1021
|
+
async function resolveMiddlewareDataEffect(browserUrl, signal, dataTarget) {
|
|
1022
|
+
const dataUrl = getMiddlewarePagesDataFetchUrl(browserUrl, dataTarget);
|
|
1020
1023
|
if (!dataUrl) return null;
|
|
1021
1024
|
if (signal.aborted) throw new DOMException("Aborted", "AbortError");
|
|
1022
1025
|
try {
|
|
@@ -1209,14 +1212,18 @@ async function navigateClientData(url, initialTarget, controller, navId, assertS
|
|
|
1209
1212
|
await navigateClientHtml(redirectedUrl, redirectedUrl, controller, navId, assertStillCurrent);
|
|
1210
1213
|
return;
|
|
1211
1214
|
}
|
|
1212
|
-
if (!res.ok)
|
|
1215
|
+
if (!res.ok) {
|
|
1216
|
+
if (options.isHydrationQueryUpdate) return;
|
|
1217
|
+
scheduleHardNavigationAndThrow(url, `Data navigation failed: ${res.status} ${res.statusText}`);
|
|
1218
|
+
}
|
|
1213
1219
|
const rewriteTarget = res.headers.get("x-nextjs-rewrite");
|
|
1214
|
-
const target = rewriteTarget ? resolvePagesDataNavigationTarget(rewriteTarget, __basePath) : initialTarget;
|
|
1220
|
+
const target = rewriteTarget ? resolvePagesDataNavigationTarget(rewriteTarget, __basePath, { locale: initialTarget.prefetchLocale }) : initialTarget;
|
|
1215
1221
|
if (!target) scheduleHardNavigationAndThrow(url, "Data navigation failed: rewrite target has no page loader");
|
|
1216
1222
|
let body;
|
|
1217
1223
|
try {
|
|
1218
1224
|
body = await res.json();
|
|
1219
1225
|
} catch {
|
|
1226
|
+
if (options.isHydrationQueryUpdate) return;
|
|
1220
1227
|
scheduleHardNavigationAndThrow(url, "Data navigation failed: invalid JSON response");
|
|
1221
1228
|
}
|
|
1222
1229
|
assertStillCurrent();
|
|
@@ -1382,20 +1389,21 @@ async function navigateClient(url, fetchUrl = url, options = {}, routeUrl = url)
|
|
|
1382
1389
|
htmlFetchUrl = configRewrite.href;
|
|
1383
1390
|
}
|
|
1384
1391
|
}
|
|
1385
|
-
|
|
1392
|
+
const pagesDataTargetOptions = { locale: options.locale };
|
|
1393
|
+
let dataTarget = resolvePagesDataNavigationTarget(routeLookupUrl, __basePath, pagesDataTargetOptions);
|
|
1386
1394
|
let middlewareDataResponse;
|
|
1387
1395
|
let middlewareEffect = null;
|
|
1388
1396
|
let middlewareRewrittenTarget;
|
|
1389
|
-
const middlewareProbeDataHref = getMiddlewarePagesDataFetchUrl(browserUrl);
|
|
1397
|
+
const middlewareProbeDataHref = getMiddlewarePagesDataFetchUrl(browserUrl, dataTarget);
|
|
1390
1398
|
if (middlewareProbeDataHref !== null) {
|
|
1391
1399
|
middlewareDataCacheEvictHref = getPagesDataCacheHref(middlewareProbeDataHref);
|
|
1392
1400
|
try {
|
|
1393
|
-
middlewareEffect = await resolveMiddlewareDataEffect(browserUrl, controller.signal);
|
|
1401
|
+
middlewareEffect = await resolveMiddlewareDataEffect(browserUrl, controller.signal, dataTarget);
|
|
1394
1402
|
} catch (err) {
|
|
1395
1403
|
if (err instanceof DOMException && err.name === "AbortError") throw new NavigationCancelledError(browserUrl);
|
|
1396
1404
|
throw err;
|
|
1397
1405
|
}
|
|
1398
|
-
if (middlewareEffect?.rewriteTarget) middlewareRewrittenTarget = resolvePagesDataNavigationTarget(middlewareEffect.rewriteTarget, __basePath);
|
|
1406
|
+
if (middlewareEffect?.rewriteTarget) middlewareRewrittenTarget = resolvePagesDataNavigationTarget(middlewareEffect.rewriteTarget, __basePath, pagesDataTargetOptions);
|
|
1399
1407
|
if (middlewareEffect) if (shouldEvictMiddlewareDataCache(middlewareEffect, middlewareRewrittenTarget !== void 0 ? middlewareRewrittenTarget : dataTarget)) middlewareDataCacheEvictHref = middlewareEffect.dataHref;
|
|
1400
1408
|
else middlewareDataCacheEvictHref = null;
|
|
1401
1409
|
assertStillCurrent();
|
|
@@ -1412,7 +1420,9 @@ async function navigateClient(url, fetchUrl = url, options = {}, routeUrl = url)
|
|
|
1412
1420
|
} else if (middlewareEffect) {
|
|
1413
1421
|
if (middlewareEffect.rewriteTarget || routeUrl === url) middlewareDataResponse = middlewareEffect.response;
|
|
1414
1422
|
if (middlewareEffect.rewriteTarget) {
|
|
1415
|
-
const
|
|
1423
|
+
const rewrittenOwner = resolveDirectHybridClientRouteOwner(middlewareEffect.rewriteTarget, __basePath);
|
|
1424
|
+
if (rewrittenOwner === "app" || rewrittenOwner === "document") scheduleHardNavigationAndThrow(browserUrl, "Navigation rewritten to a non-Pages route");
|
|
1425
|
+
const rewrittenTarget = middlewareRewrittenTarget ?? resolvePagesDataNavigationTarget(middlewareEffect.rewriteTarget, __basePath, pagesDataTargetOptions);
|
|
1416
1426
|
if (!rewrittenTarget) scheduleHardNavigationAndThrow(browserUrl, "Navigation rewritten to a non-Pages route");
|
|
1417
1427
|
dataTarget = rewrittenTarget;
|
|
1418
1428
|
}
|
|
@@ -1618,11 +1628,15 @@ async function performNavigation(url, as, options, mode, onStateUpdate) {
|
|
|
1618
1628
|
} : null;
|
|
1619
1629
|
const navigateOptions = errorRouteHtmlFetchUrl ? {
|
|
1620
1630
|
allowNotFoundResponse: true,
|
|
1631
|
+
locale: navigationLocale,
|
|
1621
1632
|
mode,
|
|
1622
|
-
scroll: scrollTarget
|
|
1633
|
+
scroll: scrollTarget,
|
|
1634
|
+
isHydrationQueryUpdate: options?._h === 1
|
|
1623
1635
|
} : {
|
|
1636
|
+
locale: navigationLocale,
|
|
1624
1637
|
mode,
|
|
1625
|
-
scroll: scrollTarget
|
|
1638
|
+
scroll: scrollTarget,
|
|
1639
|
+
isHydrationQueryUpdate: options?._h === 1
|
|
1626
1640
|
};
|
|
1627
1641
|
const currentLocale = getCurrentUrlLocale();
|
|
1628
1642
|
if (mode === "push" && interpolatedRoute !== resolved && stripHash(full) === routerRuntimeState.lastPathnameAndSearch && navigationLocale === currentLocale) mode = "replace";
|
|
@@ -1882,10 +1896,12 @@ setPagesRouterPopStateHandler(handlePagesRouterPopState);
|
|
|
1882
1896
|
*/
|
|
1883
1897
|
function wrapWithRouterContext(element, onCommit = noopCommit, onError = noopCommit) {
|
|
1884
1898
|
const { CommitBoundary, Provider } = getPagesRouterRuntimeComponents();
|
|
1899
|
+
let inner = createElement(Provider, null, element);
|
|
1900
|
+
if (typeof window !== "undefined" && window.__VINEXT_REACT_STRICT_MODE__ === true) inner = createElement(StrictMode, null, inner);
|
|
1885
1901
|
return createElement(CommitBoundary, {
|
|
1886
1902
|
onCommit,
|
|
1887
1903
|
onError
|
|
1888
|
-
},
|
|
1904
|
+
}, inner);
|
|
1889
1905
|
}
|
|
1890
1906
|
/**
|
|
1891
1907
|
* Higher-order component that injects the Pages Router `router` instance as
|
|
@@ -36,6 +36,7 @@ function createRequestContext(opts) {
|
|
|
36
36
|
currentFetchCacheMode: null,
|
|
37
37
|
currentForceDynamicFetchDefault: false,
|
|
38
38
|
dynamicFetchUrls: /* @__PURE__ */ new Set(),
|
|
39
|
+
refreshStaleFetchesInForeground: false,
|
|
39
40
|
isFetchDedupeActive: false,
|
|
40
41
|
currentFetchDedupeEntries: /* @__PURE__ */ new Map(),
|
|
41
42
|
executionContext: _getInheritedExecutionContext(),
|
package/dist/typegen.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { findDir } from "./utils/project.js";
|
|
2
|
-
import { decodeRouteSegment, isInvisibleSegment } from "./routing/utils.js";
|
|
3
2
|
import { normalizePathSeparators } from "./utils/path.js";
|
|
3
|
+
import { decodeRouteSegment, isInvisibleSegment } from "./routing/utils.js";
|
|
4
4
|
import { patternToNextFormat } from "./routing/route-validation.js";
|
|
5
5
|
import { compareStrings } from "./utils/compare.js";
|
|
6
6
|
import "./routing/app-route-graph.js";
|
|
@@ -59,7 +59,7 @@ function buildRequestHeadersFromMiddlewareResponse(baseHeaders, middlewareHeader
|
|
|
59
59
|
return nextHeaders;
|
|
60
60
|
}
|
|
61
61
|
function shouldKeepMiddlewareHeader(key) {
|
|
62
|
-
return key === "x-middleware-override-headers" || key === "x-middleware-set-cookie" || key.startsWith("x-middleware-request-");
|
|
62
|
+
return key === "x-middleware-override-headers" || key === "x-middleware-cache" || key === "x-middleware-set-cookie" || key.startsWith("x-middleware-request-");
|
|
63
63
|
}
|
|
64
64
|
//#endregion
|
|
65
65
|
export { buildRequestHeadersFromMiddlewareResponse, encodeMiddlewareRequestHeaders, shouldKeepMiddlewareHeader };
|