vinext 0.1.1 → 0.1.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +2 -5
- package/dist/build/client-build-config.d.ts +7 -1
- package/dist/build/client-build-config.js +9 -1
- package/dist/check.js +4 -3
- package/dist/client/navigation-runtime.d.ts +3 -2
- package/dist/client/window-next.d.ts +6 -4
- package/dist/config/config-matchers.d.ts +11 -4
- package/dist/config/config-matchers.js +15 -2
- package/dist/config/next-config.d.ts +13 -0
- package/dist/config/next-config.js +2 -0
- package/dist/deploy.js +9 -2
- package/dist/entries/app-rsc-entry.js +7 -1
- package/dist/entries/pages-client-entry.js +1 -1
- package/dist/entries/pages-server-entry.js +7 -6
- package/dist/index.d.ts +0 -2
- package/dist/index.js +86 -78
- package/dist/plugins/dynamic-preload-metadata.d.ts +13 -0
- package/dist/plugins/dynamic-preload-metadata.js +415 -0
- package/dist/plugins/og-assets.js +2 -2
- package/dist/plugins/optimize-imports.d.ts +8 -4
- package/dist/plugins/optimize-imports.js +16 -12
- package/dist/plugins/sass.d.ts +53 -24
- package/dist/plugins/sass.js +249 -1
- package/dist/plugins/wasm-module-import.d.ts +15 -0
- package/dist/plugins/wasm-module-import.js +50 -0
- package/dist/routing/app-route-graph.d.ts +23 -1
- package/dist/routing/app-route-graph.js +47 -8
- package/dist/routing/file-matcher.js +1 -1
- package/dist/server/app-browser-entry.js +108 -213
- package/dist/server/app-browser-error.d.ts +4 -1
- package/dist/server/app-browser-error.js +7 -1
- package/dist/server/app-browser-history-controller.d.ts +104 -0
- package/dist/server/app-browser-history-controller.js +210 -0
- package/dist/server/app-browser-navigation-controller.d.ts +3 -2
- package/dist/server/app-browser-navigation-controller.js +10 -7
- package/dist/server/app-browser-rsc-redirect.d.ts +11 -2
- package/dist/server/app-browser-rsc-redirect.js +30 -8
- package/dist/server/app-browser-state.js +4 -7
- package/dist/server/app-browser-visible-commit.js +1 -1
- package/dist/server/app-fallback-renderer.d.ts +2 -1
- package/dist/server/app-fallback-renderer.js +3 -1
- package/dist/server/app-middleware.js +1 -0
- package/dist/server/app-optimistic-routing.js +22 -1
- package/dist/server/app-page-boundary-render.d.ts +2 -1
- package/dist/server/app-page-boundary-render.js +4 -2
- package/dist/server/app-page-cache.js +9 -7
- package/dist/server/app-page-dispatch.d.ts +8 -0
- package/dist/server/app-page-dispatch.js +18 -5
- package/dist/server/app-page-element-builder.d.ts +22 -2
- package/dist/server/app-page-element-builder.js +37 -8
- package/dist/server/app-page-execution.d.ts +1 -1
- package/dist/server/app-page-execution.js +32 -17
- package/dist/server/app-page-render.d.ts +1 -1
- package/dist/server/app-page-render.js +7 -14
- package/dist/server/app-page-request.d.ts +1 -0
- package/dist/server/app-page-request.js +3 -2
- package/dist/server/app-page-response.js +1 -1
- package/dist/server/app-page-route-wiring.d.ts +3 -1
- package/dist/server/app-page-route-wiring.js +8 -7
- package/dist/server/app-page-stream.d.ts +1 -6
- package/dist/server/app-page-stream.js +1 -4
- package/dist/server/app-route-handler-response.js +11 -10
- package/dist/server/app-route-handler-runtime.js +12 -1
- package/dist/server/app-rsc-handler.js +1 -1
- package/dist/server/app-rsc-response-finalizer.js +1 -1
- package/dist/server/app-server-action-execution.d.ts +11 -0
- package/dist/server/app-server-action-execution.js +5 -2
- package/dist/server/app-ssr-entry.js +2 -2
- package/dist/server/app-ssr-stream.js +9 -1
- package/dist/server/dev-lockfile.js +2 -1
- package/dist/server/dev-server.js +43 -12
- package/dist/server/headers.d.ts +8 -1
- package/dist/server/headers.js +8 -1
- package/dist/server/instrumentation-runtime.d.ts +6 -0
- package/dist/server/instrumentation-runtime.js +8 -0
- package/dist/server/isr-decision.d.ts +79 -0
- package/dist/server/isr-decision.js +70 -0
- package/dist/server/metadata-route-response.js +5 -3
- package/dist/server/middleware-runtime.d.ts +13 -0
- package/dist/server/middleware-runtime.js +11 -7
- package/dist/server/middleware.js +1 -0
- package/dist/server/navigation-planner.d.ts +62 -1
- package/dist/server/navigation-planner.js +188 -0
- package/dist/server/navigation-trace.d.ts +11 -1
- package/dist/server/navigation-trace.js +11 -1
- package/dist/server/normalize-path.d.ts +0 -8
- package/dist/server/normalize-path.js +3 -1
- package/dist/server/otel-tracer-extension.d.ts +45 -0
- package/dist/server/otel-tracer-extension.js +89 -0
- package/dist/server/pages-api-route.d.ts +14 -3
- package/dist/server/pages-api-route.js +6 -1
- package/dist/server/pages-asset-tags.d.ts +15 -4
- package/dist/server/pages-asset-tags.js +18 -12
- package/dist/server/pages-data-route.js +5 -1
- package/dist/server/pages-node-compat.d.ts +3 -11
- package/dist/server/pages-node-compat.js +174 -121
- package/dist/server/pages-page-data.d.ts +28 -0
- package/dist/server/pages-page-data.js +61 -17
- package/dist/server/pages-page-handler.d.ts +1 -0
- package/dist/server/pages-page-handler.js +22 -6
- package/dist/server/pages-page-response.d.ts +45 -1
- package/dist/server/pages-page-response.js +66 -5
- package/dist/server/pages-readiness.d.ts +1 -1
- package/dist/server/pages-request-pipeline.d.ts +15 -1
- package/dist/server/pages-request-pipeline.js +23 -2
- package/dist/server/prod-server.d.ts +39 -1
- package/dist/server/prod-server.js +98 -34
- package/dist/shims/cache-runtime.js +9 -2
- package/dist/shims/dynamic-preload-chunks.d.ts +8 -0
- package/dist/shims/dynamic-preload-chunks.js +77 -0
- package/dist/shims/dynamic.d.ts +4 -0
- package/dist/shims/dynamic.js +4 -2
- package/dist/shims/error-boundary.d.ts +4 -4
- package/dist/shims/error.js +37 -11
- package/dist/shims/fetch-cache.d.ts +9 -1
- package/dist/shims/fetch-cache.js +11 -1
- package/dist/shims/head.js +6 -1
- package/dist/shims/headers.d.ts +16 -2
- package/dist/shims/headers.js +37 -1
- package/dist/shims/image-config.js +7 -1
- package/dist/shims/internal/app-route-detection.d.ts +6 -3
- package/dist/shims/internal/app-route-detection.js +10 -6
- package/dist/shims/internal/app-router-context.d.ts +5 -0
- package/dist/shims/metadata.d.ts +6 -2
- package/dist/shims/metadata.js +32 -14
- package/dist/shims/navigation.d.ts +7 -16
- package/dist/shims/navigation.js +33 -16
- package/dist/shims/router.js +28 -1
- package/dist/shims/script-nonce-context.d.ts +1 -1
- package/dist/shims/script-nonce-context.js +11 -3
- package/dist/shims/server.d.ts +17 -1
- package/dist/shims/server.js +31 -6
- package/dist/shims/slot.js +1 -1
- package/dist/shims/unified-request-context.js +1 -0
- package/dist/typegen.js +1 -0
- package/dist/utils/client-build-manifest.js +15 -5
- package/dist/utils/client-runtime-metadata.d.ts +45 -0
- package/dist/utils/client-runtime-metadata.js +63 -0
- package/dist/utils/hash.d.ts +17 -1
- package/dist/utils/hash.js +36 -1
- package/dist/utils/lazy-chunks.d.ts +27 -1
- package/dist/utils/lazy-chunks.js +65 -1
- package/dist/utils/manifest-paths.d.ts +20 -2
- package/dist/utils/manifest-paths.js +38 -3
- package/dist/utils/path.d.ts +2 -1
- package/dist/utils/path.js +5 -1
- package/package.json +2 -2
|
@@ -1,4 +1,5 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { NavigationRuntimeVisibleCommitMode } from "../client/navigation-runtime.js";
|
|
2
|
+
import { AppRouterInstance, NavigateOptions, PrefetchOptions as PrefetchOptions$1 } from "./internal/app-router-context.js";
|
|
2
3
|
import { ReadonlyURLSearchParams } from "./readonly-url-search-params.js";
|
|
3
4
|
import { UnrecognizedActionError, unstable_isUnrecognizedActionError } from "./unrecognized-action-error.js";
|
|
4
5
|
import * as React$1 from "react";
|
|
@@ -205,6 +206,7 @@ type ClientNavigationRenderSnapshot = {
|
|
|
205
206
|
};
|
|
206
207
|
declare function getClientNavigationRenderContext(): React$1.Context<ClientNavigationRenderSnapshot | null> | null;
|
|
207
208
|
declare function createClientNavigationRenderSnapshot(href: string, params: Record<string, string | string[]>): ClientNavigationRenderSnapshot;
|
|
209
|
+
declare function createSnapshotPathAndSearch(snapshot: ClientNavigationRenderSnapshot): string;
|
|
208
210
|
declare function setClientParams(params: Record<string, string | string[]>): void;
|
|
209
211
|
declare function replaceClientParamsWithoutNotify(params: Record<string, string | string[]>): void;
|
|
210
212
|
/** Get the current client params (for testing referential stability). */
|
|
@@ -256,7 +258,7 @@ declare function saveScrollPosition(): void;
|
|
|
256
258
|
/**
|
|
257
259
|
* Navigate to a URL, handling external URLs, hash-only changes, and RSC navigation.
|
|
258
260
|
*/
|
|
259
|
-
declare function navigateClientSide(href: string, mode: "push" | "replace", scroll: boolean, programmaticTransition?: boolean): Promise<void>;
|
|
261
|
+
declare function navigateClientSide(href: string, mode: "push" | "replace", scroll: boolean, programmaticTransition?: boolean, visibleCommitMode?: NavigationRuntimeVisibleCommitMode): Promise<void>;
|
|
260
262
|
/**
|
|
261
263
|
* Public App Router instance, exposed for the browser entry so it can wire
|
|
262
264
|
* `window.next.router` to the same singleton returned from `useRouter()`.
|
|
@@ -264,19 +266,7 @@ declare function navigateClientSide(href: string, mode: "push" | "replace", scro
|
|
|
264
266
|
* Mirrors `publicAppRouterInstance` from Next.js's
|
|
265
267
|
* `packages/next/src/client/components/app-router-instance.ts` (line 392).
|
|
266
268
|
*/
|
|
267
|
-
declare const appRouterInstance:
|
|
268
|
-
bfcacheId: string;
|
|
269
|
-
push(href: string, options?: {
|
|
270
|
-
scroll?: boolean;
|
|
271
|
-
}): void;
|
|
272
|
-
replace(href: string, options?: {
|
|
273
|
-
scroll?: boolean;
|
|
274
|
-
}): void;
|
|
275
|
-
back(): void;
|
|
276
|
-
forward(): void;
|
|
277
|
-
refresh(): void;
|
|
278
|
-
prefetch(href: string, options?: PrefetchOptions): void;
|
|
279
|
-
};
|
|
269
|
+
declare const appRouterInstance: AppRouterInstance;
|
|
280
270
|
/**
|
|
281
271
|
* App Router's useRouter — returns push/replace/back/forward/refresh.
|
|
282
272
|
* Different from Pages Router's useRouter (next/router).
|
|
@@ -292,6 +282,7 @@ declare function useRouter(): {
|
|
|
292
282
|
push(href: string, options?: NavigateOptions): void;
|
|
293
283
|
replace(href: string, options?: NavigateOptions): void;
|
|
294
284
|
prefetch(href: string, options?: PrefetchOptions$1): void;
|
|
285
|
+
experimental_gesturePush?(href: string, options?: NavigateOptions): void;
|
|
295
286
|
};
|
|
296
287
|
/**
|
|
297
288
|
* Returns the active child segment one level below the layout where it's called.
|
|
@@ -574,4 +565,4 @@ declare function isDynamicServerError(error: unknown): error is DynamicServerErr
|
|
|
574
565
|
*/
|
|
575
566
|
declare function unstable_rethrow(error: unknown): void;
|
|
576
567
|
//#endregion
|
|
577
|
-
export { BailoutToCSRError, CachedRscResponse, ClientNavigationRenderSnapshot, DynamicServerError, GLOBAL_ACCESSORS_KEY, HTTP_ERROR_FALLBACK_ERROR_CODE, MAX_PREFETCH_CACHE_SIZE, NavigationContext, PREFETCH_CACHE_TTL, PrefetchCacheEntry, PrefetchOptions, ReadonlyURLSearchParams, RedirectType, SegmentMap, ServerInsertedHTMLContext, UnrecognizedActionError, __basePath, _registerStateAccessors, activateNavigationSnapshot, appRouterInstance, clearPendingPathname, clearServerInsertedHTML, commitClientNavigationState, consumePrefetchResponse, consumePrefetchResponseForNavigation, createCachedRscResponseSnapshot, createClientNavigationRenderSnapshot, decodeRedirectError, 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, setClientParams, setMountedSlotsHeader, setNavigationContext, setPendingPathname, snapshotRscResponse, storePrefetchResponse, unauthorized, unstable_isUnrecognizedActionError, unstable_rethrow, useParams, usePathname, useRouter, useSearchParams, useSelectedLayoutSegment, useSelectedLayoutSegments, useServerInsertedHTML };
|
|
568
|
+
export { BailoutToCSRError, CachedRscResponse, ClientNavigationRenderSnapshot, DynamicServerError, GLOBAL_ACCESSORS_KEY, HTTP_ERROR_FALLBACK_ERROR_CODE, MAX_PREFETCH_CACHE_SIZE, NavigationContext, PREFETCH_CACHE_TTL, PrefetchCacheEntry, PrefetchOptions, ReadonlyURLSearchParams, RedirectType, SegmentMap, ServerInsertedHTMLContext, UnrecognizedActionError, __basePath, _registerStateAccessors, activateNavigationSnapshot, appRouterInstance, clearPendingPathname, clearServerInsertedHTML, commitClientNavigationState, consumePrefetchResponse, consumePrefetchResponseForNavigation, createCachedRscResponseSnapshot, createClientNavigationRenderSnapshot, createSnapshotPathAndSearch, decodeRedirectError, 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, setClientParams, setMountedSlotsHeader, setNavigationContext, setPendingPathname, snapshotRscResponse, storePrefetchResponse, unauthorized, unstable_isUnrecognizedActionError, unstable_rethrow, useParams, usePathname, useRouter, useSearchParams, useSelectedLayoutSegment, useSelectedLayoutSegments, useServerInsertedHTML };
|
package/dist/shims/navigation.js
CHANGED
|
@@ -4,7 +4,7 @@ import { assertSafeNavigationUrl } from "./url-safety.js";
|
|
|
4
4
|
import { AppElementsWire } from "../server/app-elements-wire.js";
|
|
5
5
|
import "../server/app-elements.js";
|
|
6
6
|
import { AppRouterContext } from "./internal/app-router-context.js";
|
|
7
|
-
import { isAbsoluteOrProtocolRelativeUrl,
|
|
7
|
+
import { isAbsoluteOrProtocolRelativeUrl, toBrowserNavigationHref, toSameOriginAppPath, withBasePath } from "./url-utils.js";
|
|
8
8
|
import { retryScrollTo, scrollToHashTarget } from "./hash-scroll.js";
|
|
9
9
|
import { getNavigationRuntime, hasAppNavigationRuntime } from "../client/navigation-runtime.js";
|
|
10
10
|
import { notifyAppRouterTransitionStart } from "../client/instrumentation-client-state.js";
|
|
@@ -13,6 +13,7 @@ import { resolveManifestNavigationInterceptionContext } from "../server/app-brow
|
|
|
13
13
|
import { createExternalHistoryStatePreservingMetadata, createHashOnlyHistoryStatePreservingNavigationMetadata } from "../server/app-history-state.js";
|
|
14
14
|
import { VINEXT_RSC_COMPATIBILITY_ID_HEADER, createRscRequestHeaders, createRscRequestUrl, stripRscCacheBustingSearchParam } from "../server/app-rsc-cache-busting.js";
|
|
15
15
|
import { hasPendingAppRouterPageRedirect } from "../server/app-browser-mpa-navigation.js";
|
|
16
|
+
import { navigationPlanner } from "../server/navigation-planner.js";
|
|
16
17
|
import { ReadonlyURLSearchParams } from "./readonly-url-search-params.js";
|
|
17
18
|
import { beginAppRouterScrollIntent, clearAppRouterScrollIntent, consumeAppRouterScrollIntent } from "./app-router-scroll-state.js";
|
|
18
19
|
import { UnrecognizedActionError, unstable_isUnrecognizedActionError } from "./unrecognized-action-error.js";
|
|
@@ -715,6 +716,10 @@ function createClientNavigationRenderSnapshot(href, params) {
|
|
|
715
716
|
params
|
|
716
717
|
};
|
|
717
718
|
}
|
|
719
|
+
function createSnapshotPathAndSearch(snapshot) {
|
|
720
|
+
const query = snapshot.searchParams.toString();
|
|
721
|
+
return query === "" ? snapshot.pathname : `${snapshot.pathname}?${query}`;
|
|
722
|
+
}
|
|
718
723
|
let _fallbackClientParams = _EMPTY_PARAMS;
|
|
719
724
|
let _fallbackClientParamsJson = "{}";
|
|
720
725
|
function setClientParams(params) {
|
|
@@ -844,14 +849,6 @@ function useParams() {
|
|
|
844
849
|
function isExternalUrl(href) {
|
|
845
850
|
return isAbsoluteOrProtocolRelativeUrl(href);
|
|
846
851
|
}
|
|
847
|
-
/**
|
|
848
|
-
* Check if a href is only a hash change relative to the current URL.
|
|
849
|
-
*/
|
|
850
|
-
function isHashOnlyChange(href) {
|
|
851
|
-
if (typeof window === "undefined") return false;
|
|
852
|
-
if (href.startsWith("#")) return true;
|
|
853
|
-
return isHashOnlyBrowserUrlChange(href, window.location.href, __basePath);
|
|
854
|
-
}
|
|
855
852
|
function withSuppressedUrlNotifications(fn) {
|
|
856
853
|
const state = getClientNavigationState();
|
|
857
854
|
if (!state) return fn();
|
|
@@ -963,7 +960,7 @@ function restoreScrollPosition(state) {
|
|
|
963
960
|
/**
|
|
964
961
|
* Navigate to a URL, handling external URLs, hash-only changes, and RSC navigation.
|
|
965
962
|
*/
|
|
966
|
-
async function navigateClientSide(href, mode, scroll, programmaticTransition = false) {
|
|
963
|
+
async function navigateClientSide(href, mode, scroll, programmaticTransition = false, visibleCommitMode = "transition") {
|
|
967
964
|
getNavigationRuntime()?.functions.notifyLinkNavigationStart?.();
|
|
968
965
|
let normalizedHref = href;
|
|
969
966
|
if (isExternalUrl(href)) {
|
|
@@ -985,11 +982,17 @@ async function navigateClientSide(href, mode, scroll, programmaticTransition = f
|
|
|
985
982
|
const fullHref = toBrowserNavigationHref(normalizedHref, window.location.href, __basePath);
|
|
986
983
|
notifyAppRouterTransitionStart(fullHref, mode);
|
|
987
984
|
if (mode === "push") saveScrollPosition();
|
|
988
|
-
|
|
989
|
-
|
|
990
|
-
|
|
985
|
+
const earlyIntent = navigationPlanner.classifyEarlyNavigationIntent({
|
|
986
|
+
basePath: __basePath,
|
|
987
|
+
currentHref: window.location.href,
|
|
988
|
+
mode,
|
|
989
|
+
scroll,
|
|
990
|
+
targetHref: fullHref
|
|
991
|
+
});
|
|
992
|
+
if (earlyIntent.kind === "sameDocumentScroll") {
|
|
993
|
+
commitHashOnlyHistoryState(fullHref, earlyIntent.mode, earlyIntent.scroll);
|
|
991
994
|
commitClientNavigationState();
|
|
992
|
-
if (scroll) scrollToHashTarget(hash);
|
|
995
|
+
if (earlyIntent.scroll) scrollToHashTarget(earlyIntent.hash);
|
|
993
996
|
return;
|
|
994
997
|
}
|
|
995
998
|
if (hasPendingAppRouterPageRedirect(typeof document === "undefined" ? void 0 : document)) {
|
|
@@ -1009,7 +1012,7 @@ async function navigateClientSide(href, mode, scroll, programmaticTransition = f
|
|
|
1009
1012
|
if (!scroll) clearAppRouterScrollIntent();
|
|
1010
1013
|
const appNavigate = getNavigationRuntime()?.functions.navigate;
|
|
1011
1014
|
try {
|
|
1012
|
-
if (appNavigate) await appNavigate(fullHref, 0, "navigate", mode, void 0, programmaticTransition, void 0, scrollIntent);
|
|
1015
|
+
if (appNavigate) await appNavigate(fullHref, 0, "navigate", mode, void 0, programmaticTransition, void 0, scrollIntent, visibleCommitMode);
|
|
1013
1016
|
else {
|
|
1014
1017
|
if (mode === "replace") replaceHistoryStateWithoutNotify(null, "", fullHref);
|
|
1015
1018
|
else pushHistoryStateWithoutNotify(null, "", fullHref);
|
|
@@ -1137,6 +1140,20 @@ const _appRouter = {
|
|
|
1137
1140
|
});
|
|
1138
1141
|
}
|
|
1139
1142
|
};
|
|
1143
|
+
if (process.env.__NEXT_GESTURE_TRANSITION) _appRouter.experimental_gesturePush = (href, options) => {
|
|
1144
|
+
assertSafeNavigationUrl(href);
|
|
1145
|
+
if (isServer) return;
|
|
1146
|
+
if (!getNavigationRuntime()?.functions.navigate) return;
|
|
1147
|
+
let appHref = href;
|
|
1148
|
+
if (isAbsoluteOrProtocolRelativeUrl(href)) {
|
|
1149
|
+
const localPath = toSameOriginAppPath(href, __basePath);
|
|
1150
|
+
if (localPath === null) return;
|
|
1151
|
+
appHref = localPath;
|
|
1152
|
+
}
|
|
1153
|
+
const releaseNavigation = trackScheduledAppRouterNavigation();
|
|
1154
|
+
navigateClientSide(appHref, "push", options?.scroll !== false, false, "synchronous");
|
|
1155
|
+
releaseScheduledAppRouterNavigationAfterCurrentTask(releaseNavigation);
|
|
1156
|
+
};
|
|
1140
1157
|
function formatPublicBfcacheId(value) {
|
|
1141
1158
|
if (!value || value === "0") return PUBLIC_INITIAL_BFCACHE_ID;
|
|
1142
1159
|
return value;
|
|
@@ -1585,4 +1602,4 @@ if (!isServer) {
|
|
|
1585
1602
|
}
|
|
1586
1603
|
}
|
|
1587
1604
|
//#endregion
|
|
1588
|
-
export { BailoutToCSRError, DynamicServerError, GLOBAL_ACCESSORS_KEY, HTTP_ERROR_FALLBACK_ERROR_CODE, MAX_PREFETCH_CACHE_SIZE, PREFETCH_CACHE_TTL, ReadonlyURLSearchParams, RedirectType, ServerInsertedHTMLContext, UnrecognizedActionError, __basePath, _registerStateAccessors, activateNavigationSnapshot, appRouterInstance, clearPendingPathname, clearServerInsertedHTML, commitClientNavigationState, consumePrefetchResponse, consumePrefetchResponseForNavigation, createCachedRscResponseSnapshot, createClientNavigationRenderSnapshot, decodeRedirectError, 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, setClientParams, setMountedSlotsHeader, setNavigationContext, setPendingPathname, snapshotRscResponse, storePrefetchResponse, unauthorized, unstable_isUnrecognizedActionError, unstable_rethrow, useParams, usePathname, useRouter, useSearchParams, useSelectedLayoutSegment, useSelectedLayoutSegments, useServerInsertedHTML };
|
|
1605
|
+
export { BailoutToCSRError, DynamicServerError, GLOBAL_ACCESSORS_KEY, HTTP_ERROR_FALLBACK_ERROR_CODE, MAX_PREFETCH_CACHE_SIZE, PREFETCH_CACHE_TTL, ReadonlyURLSearchParams, RedirectType, ServerInsertedHTMLContext, UnrecognizedActionError, __basePath, _registerStateAccessors, activateNavigationSnapshot, appRouterInstance, clearPendingPathname, clearServerInsertedHTML, commitClientNavigationState, consumePrefetchResponse, consumePrefetchResponseForNavigation, createCachedRscResponseSnapshot, createClientNavigationRenderSnapshot, createSnapshotPathAndSearch, decodeRedirectError, 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, setClientParams, setMountedSlotsHeader, setNavigationContext, setPendingPathname, snapshotRscResponse, storePrefetchResponse, unauthorized, unstable_isUnrecognizedActionError, unstable_rethrow, useParams, usePathname, useRouter, useSearchParams, useSelectedLayoutSegment, useSelectedLayoutSegments, useServerInsertedHTML };
|
package/dist/shims/router.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { splitPathSegments } from "../routing/utils.js";
|
|
2
|
-
import { stripBasePath } from "../utils/base-path.js";
|
|
2
|
+
import { removeTrailingSlash, stripBasePath } from "../utils/base-path.js";
|
|
3
3
|
import { assertSafeNavigationUrl } from "./url-safety.js";
|
|
4
4
|
import { matchRoutePattern, routePatternParts } from "../routing/route-pattern.js";
|
|
5
5
|
import { isUnknownRecord } from "../utils/record.js";
|
|
@@ -1017,6 +1017,14 @@ async function performNavigation(url, as, options, mode, onStateUpdate) {
|
|
|
1017
1017
|
dispatchNavigateEvent();
|
|
1018
1018
|
return true;
|
|
1019
1019
|
}
|
|
1020
|
+
const appPath = getLocalPathname(resolved);
|
|
1021
|
+
const appPathNorm = appPath !== null ? removeTrailingSlash(appPath) : null;
|
|
1022
|
+
const appPathEntry = appPathNorm !== null ? getPagesRouterComponentsMap()[appPathNorm] : void 0;
|
|
1023
|
+
if (appPathEntry !== void 0 && "__appRouter" in appPathEntry && appPathEntry.__appRouter) {
|
|
1024
|
+
if (mode === "push") window.location.assign(full);
|
|
1025
|
+
else window.location.replace(full);
|
|
1026
|
+
return new Promise(() => {});
|
|
1027
|
+
}
|
|
1020
1028
|
if (mode === "push") saveScrollPosition();
|
|
1021
1029
|
routerEvents.emit("routeChangeStart", resolved, { shallow });
|
|
1022
1030
|
routerEvents.emit("beforeHistoryChange", resolved, { shallow });
|
|
@@ -1338,6 +1346,25 @@ const Router = Object.defineProperties(RouterMethods, {
|
|
|
1338
1346
|
}
|
|
1339
1347
|
}
|
|
1340
1348
|
});
|
|
1349
|
+
for (const event of [
|
|
1350
|
+
"routeChangeStart",
|
|
1351
|
+
"beforeHistoryChange",
|
|
1352
|
+
"routeChangeComplete",
|
|
1353
|
+
"routeChangeError",
|
|
1354
|
+
"hashChangeStart",
|
|
1355
|
+
"hashChangeComplete"
|
|
1356
|
+
]) {
|
|
1357
|
+
const eventField = `on${event.charAt(0).toUpperCase()}${event.substring(1)}`;
|
|
1358
|
+
routerEvents.on(event, (...args) => {
|
|
1359
|
+
const handler = Router[eventField];
|
|
1360
|
+
if (typeof handler === "function") try {
|
|
1361
|
+
handler(...args);
|
|
1362
|
+
} catch (err) {
|
|
1363
|
+
console.error(`Error when running the Router event: ${eventField}`);
|
|
1364
|
+
console.error(err instanceof Error ? `${err.message}\n${err.stack}` : String(err));
|
|
1365
|
+
}
|
|
1366
|
+
});
|
|
1367
|
+
}
|
|
1341
1368
|
if (typeof window !== "undefined") installWindowNext({ router: Router });
|
|
1342
1369
|
const _PAGES_NAVIGATION_ACCESSOR_KEY = Symbol.for("vinext.navigation.pagesNavigationContextAccessor");
|
|
1343
1370
|
globalThis[_PAGES_NAVIGATION_ACCESSOR_KEY] = getPagesNavigationContext;
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import React from "react";
|
|
2
2
|
|
|
3
3
|
//#region src/shims/script-nonce-context.d.ts
|
|
4
|
-
declare const ScriptNonceContext: React.Context<string | undefined
|
|
4
|
+
declare const ScriptNonceContext: React.Context<string | undefined> | null;
|
|
5
5
|
declare function ScriptNonceProvider(props: React.PropsWithChildren<{
|
|
6
6
|
nonce?: string;
|
|
7
7
|
}>): React.ReactElement;
|
|
@@ -1,15 +1,23 @@
|
|
|
1
1
|
import React from "react";
|
|
2
2
|
//#region src/shims/script-nonce-context.tsx
|
|
3
|
-
const ScriptNonceContext = React.createContext(void 0);
|
|
3
|
+
const ScriptNonceContext = typeof React.createContext === "function" ? React.createContext(void 0) : null;
|
|
4
4
|
function ScriptNonceProvider(props) {
|
|
5
|
+
if (!ScriptNonceContext) return React.createElement(React.Fragment, null, props.children);
|
|
5
6
|
return React.createElement(ScriptNonceContext.Provider, { value: props.nonce }, props.children);
|
|
6
7
|
}
|
|
7
8
|
function withScriptNonce(element, nonce) {
|
|
8
|
-
if (!nonce) return element;
|
|
9
|
+
if (!nonce || !ScriptNonceContext) return element;
|
|
9
10
|
return React.createElement(ScriptNonceProvider, { nonce }, element);
|
|
10
11
|
}
|
|
12
|
+
function createScriptNonceHook(context) {
|
|
13
|
+
if (!context || typeof React.useContext !== "function") return function useScriptNonceFromContext() {};
|
|
14
|
+
return function useScriptNonceFromContext() {
|
|
15
|
+
return React.useContext(context);
|
|
16
|
+
};
|
|
17
|
+
}
|
|
18
|
+
const useScriptNonceFromContext = createScriptNonceHook(ScriptNonceContext);
|
|
11
19
|
function useScriptNonce() {
|
|
12
|
-
return
|
|
20
|
+
return useScriptNonceFromContext();
|
|
13
21
|
}
|
|
14
22
|
//#endregion
|
|
15
23
|
export { ScriptNonceContext, ScriptNonceProvider, useScriptNonce, withScriptNonce };
|
package/dist/shims/server.d.ts
CHANGED
|
@@ -91,13 +91,29 @@ type NextURLConfig = {
|
|
|
91
91
|
declare class NextURL {
|
|
92
92
|
/** Internal URL stores the pathname WITHOUT basePath or locale prefix. */
|
|
93
93
|
private _url;
|
|
94
|
+
/**
|
|
95
|
+
* The configured basePath (from nextConfig). May differ from the active
|
|
96
|
+
* `_basePath`: parsing only activates basePath when the URL's pathname
|
|
97
|
+
* actually carries the configured prefix.
|
|
98
|
+
*/
|
|
99
|
+
private _configBasePath;
|
|
94
100
|
private _basePath;
|
|
95
101
|
private _trailingSlash;
|
|
96
102
|
private _locale;
|
|
97
103
|
private _defaultLocale;
|
|
98
104
|
private _locales;
|
|
99
105
|
constructor(input: string | URL, base?: string | URL, config?: NextURLConfig);
|
|
100
|
-
/** Strip basePath prefix from the internal pathname.
|
|
106
|
+
/** Strip basePath prefix from the internal pathname.
|
|
107
|
+
* Mirrors Next.js's getNextPathnameInfo (re-run by NextURL.analyze() on
|
|
108
|
+
* every parse, including `href` reassignment): basePath is only considered
|
|
109
|
+
* active when the URL's pathname actually starts with the configured
|
|
110
|
+
* basePath prefix. If the pathname is outside the basePath, the active
|
|
111
|
+
* basePath is cleared to "" so that request.nextUrl.basePath reflects the
|
|
112
|
+
* actual URL rather than the config value; if a later `href` assignment
|
|
113
|
+
* moves the URL back inside the basePath, it is re-activated from the
|
|
114
|
+
* configured value. This matches the Next.js behavior tested by
|
|
115
|
+
* middleware-base-path's "should execute from absolute paths" case.
|
|
116
|
+
*/
|
|
101
117
|
private _stripBasePath;
|
|
102
118
|
/** Extract locale from pathname, stripping it from the internal URL. */
|
|
103
119
|
private _analyzeLocale;
|
package/dist/shims/server.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { stripBasePath } from "../utils/base-path.js";
|
|
1
|
+
import { hasBasePath, stripBasePath } from "../utils/base-path.js";
|
|
2
2
|
import { getRequestExecutionContext } from "./request-context.js";
|
|
3
3
|
import { MIDDLEWARE_NEXT_HEADER, MIDDLEWARE_REWRITE_HEADER, MIDDLEWARE_SET_COOKIE_HEADER } from "../server/headers.js";
|
|
4
4
|
import { encodeMiddlewareRequestHeaders } from "../server/middleware-request-headers.js";
|
|
@@ -183,6 +183,12 @@ var NextResponse = class NextResponse extends Response {
|
|
|
183
183
|
var NextURL = class NextURL {
|
|
184
184
|
/** Internal URL stores the pathname WITHOUT basePath or locale prefix. */
|
|
185
185
|
_url;
|
|
186
|
+
/**
|
|
187
|
+
* The configured basePath (from nextConfig). May differ from the active
|
|
188
|
+
* `_basePath`: parsing only activates basePath when the URL's pathname
|
|
189
|
+
* actually carries the configured prefix.
|
|
190
|
+
*/
|
|
191
|
+
_configBasePath;
|
|
186
192
|
_basePath;
|
|
187
193
|
_trailingSlash;
|
|
188
194
|
_locale;
|
|
@@ -190,7 +196,8 @@ var NextURL = class NextURL {
|
|
|
190
196
|
_locales;
|
|
191
197
|
constructor(input, base, config) {
|
|
192
198
|
this._url = new URL(input.toString(), base);
|
|
193
|
-
this.
|
|
199
|
+
this._configBasePath = config?.basePath ?? "";
|
|
200
|
+
this._basePath = this._configBasePath;
|
|
194
201
|
this._trailingSlash = config?.nextConfig?.trailingSlash ?? false;
|
|
195
202
|
this._stripBasePath();
|
|
196
203
|
const i18n = config?.nextConfig?.i18n;
|
|
@@ -200,10 +207,25 @@ var NextURL = class NextURL {
|
|
|
200
207
|
this._analyzeLocale(this._locales);
|
|
201
208
|
}
|
|
202
209
|
}
|
|
203
|
-
/** Strip basePath prefix from the internal pathname.
|
|
210
|
+
/** Strip basePath prefix from the internal pathname.
|
|
211
|
+
* Mirrors Next.js's getNextPathnameInfo (re-run by NextURL.analyze() on
|
|
212
|
+
* every parse, including `href` reassignment): basePath is only considered
|
|
213
|
+
* active when the URL's pathname actually starts with the configured
|
|
214
|
+
* basePath prefix. If the pathname is outside the basePath, the active
|
|
215
|
+
* basePath is cleared to "" so that request.nextUrl.basePath reflects the
|
|
216
|
+
* actual URL rather than the config value; if a later `href` assignment
|
|
217
|
+
* moves the URL back inside the basePath, it is re-activated from the
|
|
218
|
+
* configured value. This matches the Next.js behavior tested by
|
|
219
|
+
* middleware-base-path's "should execute from absolute paths" case.
|
|
220
|
+
*/
|
|
204
221
|
_stripBasePath() {
|
|
205
|
-
if (!this.
|
|
206
|
-
|
|
222
|
+
if (!this._configBasePath) return;
|
|
223
|
+
if (!hasBasePath(this._url.pathname, this._configBasePath)) {
|
|
224
|
+
this._basePath = "";
|
|
225
|
+
return;
|
|
226
|
+
}
|
|
227
|
+
this._basePath = this._configBasePath;
|
|
228
|
+
this._url.pathname = stripBasePath(this._url.pathname, this._configBasePath);
|
|
207
229
|
}
|
|
208
230
|
/** Extract locale from pathname, stripping it from the internal URL. */
|
|
209
231
|
_analyzeLocale(locales) {
|
|
@@ -655,10 +677,13 @@ function after(task) {
|
|
|
655
677
|
* and sets Cache-Control: no-store on the response.
|
|
656
678
|
*/
|
|
657
679
|
async function connection() {
|
|
658
|
-
const { markDynamicUsage, markRenderRequestApiUsage, throwIfInsideCacheScope } = await import("./headers.js");
|
|
680
|
+
const { getHeadersContext, markDynamicUsage, markRenderRequestApiUsage, suspendConnectionProbe, throwIfInsideCacheScope } = await import("./headers.js");
|
|
681
|
+
if (getHeadersContext()?.forceStatic) return;
|
|
659
682
|
markRenderRequestApiUsage("connection");
|
|
660
683
|
throwIfInsideCacheScope("connection()");
|
|
661
684
|
markDynamicUsage();
|
|
685
|
+
const pendingProbe = suspendConnectionProbe();
|
|
686
|
+
if (pendingProbe) await pendingProbe;
|
|
662
687
|
}
|
|
663
688
|
/**
|
|
664
689
|
* URLPattern re-export — used in middleware for route matching.
|
package/dist/shims/slot.js
CHANGED
|
@@ -23,7 +23,7 @@ const MAX_BFCACHE_SLOT_ENTRIES_WITH_CACHE_COMPONENTS = 3;
|
|
|
23
23
|
const MAX_BFCACHE_SLOT_ENTRIES_WITHOUT_CACHE_COMPONENTS = 1;
|
|
24
24
|
const BfcacheStateKeyMapContext = React$1.createContext(EMPTY_BFCACHE_STATE_KEYS);
|
|
25
25
|
function isCacheComponentsEnabled() {
|
|
26
|
-
return process.env.__NEXT_CACHE_COMPONENTS === "true";
|
|
26
|
+
return String(process.env.__NEXT_CACHE_COMPONENTS) === "true";
|
|
27
27
|
}
|
|
28
28
|
function getBfcacheSlotEntryLimit() {
|
|
29
29
|
return isCacheComponentsEnabled() ? MAX_BFCACHE_SLOT_ENTRIES_WITH_CACHE_COMPONENTS : MAX_BFCACHE_SLOT_ENTRIES_WITHOUT_CACHE_COMPONENTS;
|
|
@@ -18,6 +18,7 @@ function createRequestContext(opts) {
|
|
|
18
18
|
actionRevalidationKind: 0,
|
|
19
19
|
dynamicUsageDetected: false,
|
|
20
20
|
renderRequestApiUsage: /* @__PURE__ */ new Set(),
|
|
21
|
+
connectionProbe: null,
|
|
21
22
|
invalidDynamicUsageError: null,
|
|
22
23
|
pendingSetCookies: [],
|
|
23
24
|
draftModeCookieHeader: null,
|
package/dist/typegen.js
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { decodeRouteSegment, isInvisibleSegment } from "./routing/utils.js";
|
|
2
2
|
import { patternToNextFormat } from "./routing/route-validation.js";
|
|
3
3
|
import { compareStrings } from "./utils/compare.js";
|
|
4
|
+
import "./routing/app-route-graph.js";
|
|
4
5
|
import { appRouteGraph } from "./routing/app-router.js";
|
|
5
6
|
import path from "node:path";
|
|
6
7
|
import fs from "node:fs/promises";
|
|
@@ -47,16 +47,26 @@ function findEntryFileFromManifest(buildManifest, assetBase, markers, fallbackTo
|
|
|
47
47
|
const chosen = fallbackToFirstEntry ? entries[0] : void 0;
|
|
48
48
|
return chosen ? manifestFileWithBase(chosen.file, assetBase) : void 0;
|
|
49
49
|
}
|
|
50
|
+
function listFilesRecursive(dir) {
|
|
51
|
+
const out = [];
|
|
52
|
+
for (const entry of fs.readdirSync(dir, { withFileTypes: true })) {
|
|
53
|
+
const full = path.join(dir, entry.name);
|
|
54
|
+
if (entry.isDirectory()) out.push(...listFilesRecursive(full));
|
|
55
|
+
else if (entry.isFile()) out.push(full);
|
|
56
|
+
}
|
|
57
|
+
return out;
|
|
58
|
+
}
|
|
50
59
|
function findClientEntryFileInAssetsDir(options) {
|
|
51
60
|
const assetsDir = path.join(options.clientDir, options.assetsSubdir);
|
|
52
61
|
if (!fs.existsSync(assetsDir)) return void 0;
|
|
53
|
-
const files =
|
|
54
|
-
let
|
|
62
|
+
const files = listFilesRecursive(assetsDir);
|
|
63
|
+
let entryFull;
|
|
55
64
|
for (const marker of options.markers) {
|
|
56
|
-
|
|
57
|
-
if (
|
|
65
|
+
entryFull = files.find((file) => path.basename(file).includes(marker) && file.endsWith(".js"));
|
|
66
|
+
if (entryFull) break;
|
|
58
67
|
}
|
|
59
|
-
|
|
68
|
+
if (!entryFull) return void 0;
|
|
69
|
+
return manifestFileWithBase(path.relative(options.clientDir, entryFull).split(path.sep).join("/"), options.assetBase);
|
|
60
70
|
}
|
|
61
71
|
function findClientEntryFile(options) {
|
|
62
72
|
return (options.buildManifest ? findClientEntryFileFromManifest(options.buildManifest, options.assetBase) : void 0) ?? findClientEntryFileInAssetsDir({
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
//#region src/utils/client-runtime-metadata.d.ts
|
|
2
|
+
type ClientRuntimeMetadata = {
|
|
3
|
+
clientEntryFile?: string;
|
|
4
|
+
lazyChunks?: string[];
|
|
5
|
+
dynamicPreloads?: Record<string, string[]>;
|
|
6
|
+
};
|
|
7
|
+
/**
|
|
8
|
+
* Read the client build manifest and compute runtime metadata used by
|
|
9
|
+
* Cloudflare worker entry injection and Node production server startup.
|
|
10
|
+
*
|
|
11
|
+
* - `lazyChunks` — chunks only reachable through dynamic `import()`, excluded
|
|
12
|
+
* from modulepreload hints.
|
|
13
|
+
* - `dynamicPreloads` — per-module JS/CSS files for rendered `next/dynamic()`
|
|
14
|
+
* boundaries, injected as preload links during SSR.
|
|
15
|
+
* - `clientEntryFile` — the client entry chunk filename (optional, only
|
|
16
|
+
* needed for Pages Router).
|
|
17
|
+
*
|
|
18
|
+
* All file paths are normalised with the configured `assetBase` (basePath)
|
|
19
|
+
* and `assetPrefix`.
|
|
20
|
+
*/
|
|
21
|
+
declare function computeClientRuntimeMetadata(opts: {
|
|
22
|
+
clientDir: string;
|
|
23
|
+
assetBase: string;
|
|
24
|
+
assetPrefix: string;
|
|
25
|
+
includeClientEntry?: boolean | "pages-client-entry";
|
|
26
|
+
}): ClientRuntimeMetadata;
|
|
27
|
+
/**
|
|
28
|
+
* Serialize runtime metadata into the `globalThis.__VINEXT_*` assignment script
|
|
29
|
+
* that the Cloudflare `closeBundle` hook prepends to the worker entry. Returns
|
|
30
|
+
* `""` when there is nothing to inject.
|
|
31
|
+
*
|
|
32
|
+
* Both the App Router and Pages Router closeBundle paths call this (and the
|
|
33
|
+
* deploy tests mirror it), so the injection shape stays in one place. The caller
|
|
34
|
+
* decides which fields to pass — e.g. App Router only forwards `clientEntryFile`
|
|
35
|
+
* for mixed app+pages builds (where `computeClientRuntimeMetadata` was asked for
|
|
36
|
+
* the Pages client entry); pure App Router leaves it undefined.
|
|
37
|
+
*/
|
|
38
|
+
declare function buildRuntimeGlobalsScript(input: {
|
|
39
|
+
clientEntryFile?: string | null;
|
|
40
|
+
ssrManifest?: Record<string, string[]> | null;
|
|
41
|
+
lazyChunks?: string[] | null;
|
|
42
|
+
dynamicPreloads?: Record<string, string[]> | null;
|
|
43
|
+
}): string;
|
|
44
|
+
//#endregion
|
|
45
|
+
export { buildRuntimeGlobalsScript, computeClientRuntimeMetadata };
|
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
import { resolveAssetsDir } from "./asset-prefix.js";
|
|
2
|
+
import { manifestFileWithAssetPrefix, manifestFileWithBase } from "./manifest-paths.js";
|
|
3
|
+
import { findClientEntryFile, findPagesClientEntryFile, readClientBuildManifest } from "./client-build-manifest.js";
|
|
4
|
+
import { findClientEntryFileFromVinextManifest, findPagesClientEntryFileFromVinextManifest, readClientEntryManifest } from "./client-entry-manifest.js";
|
|
5
|
+
import { computeDynamicImportPreloads, computeLazyChunks, dynamicImportPreloadsWithBase } from "./lazy-chunks.js";
|
|
6
|
+
import path from "node:path";
|
|
7
|
+
//#region src/utils/client-runtime-metadata.ts
|
|
8
|
+
/**
|
|
9
|
+
* Read the client build manifest and compute runtime metadata used by
|
|
10
|
+
* Cloudflare worker entry injection and Node production server startup.
|
|
11
|
+
*
|
|
12
|
+
* - `lazyChunks` — chunks only reachable through dynamic `import()`, excluded
|
|
13
|
+
* from modulepreload hints.
|
|
14
|
+
* - `dynamicPreloads` — per-module JS/CSS files for rendered `next/dynamic()`
|
|
15
|
+
* boundaries, injected as preload links during SSR.
|
|
16
|
+
* - `clientEntryFile` — the client entry chunk filename (optional, only
|
|
17
|
+
* needed for Pages Router).
|
|
18
|
+
*
|
|
19
|
+
* All file paths are normalised with the configured `assetBase` (basePath)
|
|
20
|
+
* and `assetPrefix`.
|
|
21
|
+
*/
|
|
22
|
+
function computeClientRuntimeMetadata(opts) {
|
|
23
|
+
const buildManifest = readClientBuildManifest(path.join(opts.clientDir, ".vite", "manifest.json"));
|
|
24
|
+
const metadata = {};
|
|
25
|
+
if (opts.includeClientEntry) {
|
|
26
|
+
const clientEntryManifest = readClientEntryManifest(opts.clientDir);
|
|
27
|
+
const entryOptions = {
|
|
28
|
+
buildManifest,
|
|
29
|
+
clientDir: opts.clientDir,
|
|
30
|
+
assetsSubdir: resolveAssetsDir(opts.assetPrefix),
|
|
31
|
+
assetBase: opts.assetBase
|
|
32
|
+
};
|
|
33
|
+
const entry = opts.includeClientEntry === "pages-client-entry" ? findPagesClientEntryFileFromVinextManifest(clientEntryManifest, opts.assetBase) ?? findPagesClientEntryFile(entryOptions) : findClientEntryFileFromVinextManifest(clientEntryManifest, opts.assetBase) ?? findClientEntryFile(entryOptions);
|
|
34
|
+
if (entry) metadata.clientEntryFile = entry;
|
|
35
|
+
}
|
|
36
|
+
if (!buildManifest) return metadata;
|
|
37
|
+
const lazyChunks = computeLazyChunks(buildManifest).map((file) => manifestFileWithBase(file, opts.assetBase));
|
|
38
|
+
if (lazyChunks.length > 0) metadata.lazyChunks = lazyChunks;
|
|
39
|
+
const dynamicPreloads = dynamicImportPreloadsWithBase(computeDynamicImportPreloads(buildManifest), (file) => manifestFileWithAssetPrefix(file, opts.assetBase, opts.assetPrefix));
|
|
40
|
+
if (Object.keys(dynamicPreloads).length > 0) metadata.dynamicPreloads = dynamicPreloads;
|
|
41
|
+
return metadata;
|
|
42
|
+
}
|
|
43
|
+
/**
|
|
44
|
+
* Serialize runtime metadata into the `globalThis.__VINEXT_*` assignment script
|
|
45
|
+
* that the Cloudflare `closeBundle` hook prepends to the worker entry. Returns
|
|
46
|
+
* `""` when there is nothing to inject.
|
|
47
|
+
*
|
|
48
|
+
* Both the App Router and Pages Router closeBundle paths call this (and the
|
|
49
|
+
* deploy tests mirror it), so the injection shape stays in one place. The caller
|
|
50
|
+
* decides which fields to pass — e.g. App Router only forwards `clientEntryFile`
|
|
51
|
+
* for mixed app+pages builds (where `computeClientRuntimeMetadata` was asked for
|
|
52
|
+
* the Pages client entry); pure App Router leaves it undefined.
|
|
53
|
+
*/
|
|
54
|
+
function buildRuntimeGlobalsScript(input) {
|
|
55
|
+
const globals = [];
|
|
56
|
+
if (input.clientEntryFile) globals.push(`globalThis.__VINEXT_CLIENT_ENTRY__ = ${JSON.stringify(input.clientEntryFile)};`);
|
|
57
|
+
if (input.ssrManifest && Object.keys(input.ssrManifest).length > 0) globals.push(`globalThis.__VINEXT_SSR_MANIFEST__ = ${JSON.stringify(input.ssrManifest)};`);
|
|
58
|
+
if (input.lazyChunks && input.lazyChunks.length > 0) globals.push(`globalThis.__VINEXT_LAZY_CHUNKS__ = ${JSON.stringify(input.lazyChunks)};`);
|
|
59
|
+
if (input.dynamicPreloads && Object.keys(input.dynamicPreloads).length > 0) globals.push(`globalThis.__VINEXT_DYNAMIC_PRELOADS__ = ${JSON.stringify(input.dynamicPreloads)};`);
|
|
60
|
+
return globals.join("\n");
|
|
61
|
+
}
|
|
62
|
+
//#endregion
|
|
63
|
+
export { buildRuntimeGlobalsScript, computeClientRuntimeMetadata };
|
package/dist/utils/hash.d.ts
CHANGED
|
@@ -2,7 +2,23 @@
|
|
|
2
2
|
/**
|
|
3
3
|
* FNV-1a hash producing a 64-bit result (two 32-bit rounds with different seeds).
|
|
4
4
|
* Used for deterministic key generation where collisions must be rare.
|
|
5
|
+
*
|
|
6
|
+
* This is a vinext-internal format: nothing outside vinext ever compares
|
|
7
|
+
* these values, so the algorithm only needs to be deterministic. For values
|
|
8
|
+
* that must be byte-for-byte identical to what Next.js emits (ETags), use
|
|
9
|
+
* `fnv1a52` below instead — the two are NOT interchangeable.
|
|
5
10
|
*/
|
|
6
11
|
declare function fnv1a64(input: string): string;
|
|
12
|
+
/**
|
|
13
|
+
* FNV-1a hash producing a 52-bit result, a byte-for-byte port of Next.js's
|
|
14
|
+
* `fnv1a52` in packages/next/src/server/lib/etag.ts (itself derived from
|
|
15
|
+
* fnv-plus). Used for ETag generation, where matching Next.js's exact output
|
|
16
|
+
* matters: clients and CDNs holding `If-None-Match` values from a Next.js
|
|
17
|
+
* deployment keep revalidating (304) against vinext for unchanged payloads.
|
|
18
|
+
*
|
|
19
|
+
* Deliberately separate from `fnv1a64` above — that one is a vinext-internal
|
|
20
|
+
* key format and produces different values. Do not swap one for the other.
|
|
21
|
+
*/
|
|
22
|
+
declare function fnv1a52(str: string): number;
|
|
7
23
|
//#endregion
|
|
8
|
-
export { fnv1a64 };
|
|
24
|
+
export { fnv1a52, fnv1a64 };
|
package/dist/utils/hash.js
CHANGED
|
@@ -2,6 +2,11 @@
|
|
|
2
2
|
/**
|
|
3
3
|
* FNV-1a hash producing a 64-bit result (two 32-bit rounds with different seeds).
|
|
4
4
|
* Used for deterministic key generation where collisions must be rare.
|
|
5
|
+
*
|
|
6
|
+
* This is a vinext-internal format: nothing outside vinext ever compares
|
|
7
|
+
* these values, so the algorithm only needs to be deterministic. For values
|
|
8
|
+
* that must be byte-for-byte identical to what Next.js emits (ETags), use
|
|
9
|
+
* `fnv1a52` below instead — the two are NOT interchangeable.
|
|
5
10
|
*/
|
|
6
11
|
function fnv1a64(input) {
|
|
7
12
|
let h1 = 2166136261;
|
|
@@ -16,5 +21,35 @@ function fnv1a64(input) {
|
|
|
16
21
|
}
|
|
17
22
|
return h1.toString(16).padStart(8, "0") + h2.toString(16).padStart(8, "0");
|
|
18
23
|
}
|
|
24
|
+
/**
|
|
25
|
+
* FNV-1a hash producing a 52-bit result, a byte-for-byte port of Next.js's
|
|
26
|
+
* `fnv1a52` in packages/next/src/server/lib/etag.ts (itself derived from
|
|
27
|
+
* fnv-plus). Used for ETag generation, where matching Next.js's exact output
|
|
28
|
+
* matters: clients and CDNs holding `If-None-Match` values from a Next.js
|
|
29
|
+
* deployment keep revalidating (304) against vinext for unchanged payloads.
|
|
30
|
+
*
|
|
31
|
+
* Deliberately separate from `fnv1a64` above — that one is a vinext-internal
|
|
32
|
+
* key format and produces different values. Do not swap one for the other.
|
|
33
|
+
*/
|
|
34
|
+
function fnv1a52(str) {
|
|
35
|
+
const len = str.length;
|
|
36
|
+
let i = 0, t0 = 0, v0 = 8997, t1 = 0, v1 = 33826, t2 = 0, v2 = 40164, t3 = 0, v3 = 52210;
|
|
37
|
+
while (i < len) {
|
|
38
|
+
v0 ^= str.charCodeAt(i++);
|
|
39
|
+
t0 = v0 * 435;
|
|
40
|
+
t1 = v1 * 435;
|
|
41
|
+
t2 = v2 * 435;
|
|
42
|
+
t3 = v3 * 435;
|
|
43
|
+
t2 += v0 << 8;
|
|
44
|
+
t3 += v1 << 8;
|
|
45
|
+
t1 += t0 >>> 16;
|
|
46
|
+
v0 = t0 & 65535;
|
|
47
|
+
t2 += t1 >>> 16;
|
|
48
|
+
v1 = t1 & 65535;
|
|
49
|
+
v3 = t3 + (t2 >>> 16) & 65535;
|
|
50
|
+
v2 = t2 & 65535;
|
|
51
|
+
}
|
|
52
|
+
return (v3 & 15) * 281474976710656 + v2 * 4294967296 + v1 * 65536 + (v0 ^ v3 >> 4);
|
|
53
|
+
}
|
|
19
54
|
//#endregion
|
|
20
|
-
export { fnv1a64 };
|
|
55
|
+
export { fnv1a52, fnv1a64 };
|
|
@@ -29,5 +29,31 @@ type BuildManifestChunk = {
|
|
|
29
29
|
* should be excluded from modulepreload hints.
|
|
30
30
|
*/
|
|
31
31
|
declare function computeLazyChunks(buildManifest: Record<string, BuildManifestChunk>): string[];
|
|
32
|
+
/**
|
|
33
|
+
* Compute the production preload files for each module referenced by a
|
|
34
|
+
* `next/dynamic()` boundary.
|
|
35
|
+
*
|
|
36
|
+
* Next.js records module IDs during compilation, then resolves those IDs
|
|
37
|
+
* against its react-loadable manifest at render time. Vinext's equivalent
|
|
38
|
+
* source of truth is Vite's build manifest: each chunk lists the modules it
|
|
39
|
+
* reaches through `dynamicImports`, and each dynamic entry lists the JS/CSS
|
|
40
|
+
* files required to evaluate it.
|
|
41
|
+
*
|
|
42
|
+
* Note on shared chunks: a boundary's static-import tree (`collectStaticChunkFiles`)
|
|
43
|
+
* can include chunks that the page entry ALSO loads eagerly (a shared vendor
|
|
44
|
+
* chunk imported by both). Those files are intentionally NOT subtracted here, so
|
|
45
|
+
* a rendered boundary may emit a `<link rel="preload">` / `<link rel="stylesheet">`
|
|
46
|
+
* for a chunk the page already `<link rel="modulepreload">`s. This is harmless —
|
|
47
|
+
* the browser dedupes preloads by URL, `ReactDOM.preload()` dedupes script hints,
|
|
48
|
+
* and React's stylesheet resource model dedupes by href + precedence — and it
|
|
49
|
+
* mirrors Next.js listing a module's full file set in its react-loadable
|
|
50
|
+
* manifest. Subtracting the eager set would couple this to the entry's import
|
|
51
|
+
* closure for no correctness gain.
|
|
52
|
+
*
|
|
53
|
+
* @returns A map keyed by root-relative module ID, with JS/CSS files that
|
|
54
|
+
* should be preloaded when that dynamic boundary is rendered.
|
|
55
|
+
*/
|
|
56
|
+
declare function computeDynamicImportPreloads(buildManifest: Record<string, BuildManifestChunk>): Record<string, string[]>;
|
|
57
|
+
declare function dynamicImportPreloadsWithBase(preloads: Record<string, string[]>, applyBase: (file: string) => string): Record<string, string[]>;
|
|
32
58
|
//#endregion
|
|
33
|
-
export { BuildManifestChunk, computeLazyChunks };
|
|
59
|
+
export { BuildManifestChunk, computeDynamicImportPreloads, computeLazyChunks, dynamicImportPreloadsWithBase };
|