vinext 0.1.0 → 0.1.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/assets-ignore.d.ts +32 -0
- package/dist/build/assets-ignore.js +48 -0
- package/dist/build/client-build-config.d.ts +27 -1
- package/dist/build/client-build-config.js +58 -1
- package/dist/cli.js +2 -0
- package/dist/client/navigation-runtime.d.ts +8 -0
- package/dist/client/navigation-runtime.js +1 -1
- package/dist/client/vinext-next-data.d.ts +2 -1
- package/dist/config/config-matchers.d.ts +20 -1
- package/dist/config/config-matchers.js +35 -1
- package/dist/config/next-config.d.ts +16 -3
- package/dist/config/next-config.js +30 -2
- package/dist/deploy.js +40 -304
- package/dist/entries/app-rsc-entry.d.ts +8 -2
- package/dist/entries/app-rsc-entry.js +54 -4
- package/dist/entries/app-rsc-manifest.js +20 -2
- package/dist/entries/pages-server-entry.js +9 -1
- package/dist/index.js +162 -217
- package/dist/plugins/postcss.js +18 -14
- package/dist/plugins/require-context.d.ts +6 -0
- package/dist/plugins/require-context.js +184 -0
- package/dist/routing/app-route-graph.d.ts +12 -1
- package/dist/routing/app-route-graph.js +137 -5
- package/dist/routing/route-pattern.d.ts +2 -1
- package/dist/routing/route-pattern.js +16 -1
- package/dist/server/api-handler.js +4 -0
- package/dist/server/app-browser-entry.js +84 -39
- package/dist/server/app-browser-interception-context.d.ts +2 -1
- package/dist/server/app-browser-interception-context.js +15 -2
- package/dist/server/app-browser-navigation-controller.d.ts +11 -1
- package/dist/server/app-browser-navigation-controller.js +77 -1
- package/dist/server/app-browser-popstate.d.ts +12 -3
- package/dist/server/app-browser-popstate.js +19 -4
- package/dist/server/app-browser-state.d.ts +3 -0
- package/dist/server/app-browser-state.js +6 -3
- package/dist/server/app-browser-visible-commit.js +9 -7
- package/dist/server/app-history-state.d.ts +45 -1
- package/dist/server/app-history-state.js +109 -1
- package/dist/server/app-page-boundary-render.js +41 -19
- package/dist/server/app-page-dispatch.d.ts +6 -0
- package/dist/server/app-page-dispatch.js +3 -1
- package/dist/server/app-page-element-builder.d.ts +1 -0
- package/dist/server/app-page-element-builder.js +22 -10
- package/dist/server/app-page-render.d.ts +6 -0
- package/dist/server/app-page-render.js +5 -3
- package/dist/server/app-page-request.d.ts +8 -6
- package/dist/server/app-page-request.js +12 -9
- package/dist/server/app-page-response.d.ts +2 -2
- package/dist/server/app-page-response.js +1 -1
- package/dist/server/app-page-route-wiring.js +2 -1
- package/dist/server/app-page-stream.d.ts +37 -2
- package/dist/server/app-page-stream.js +36 -3
- package/dist/server/app-pages-bridge.d.ts +16 -0
- package/dist/server/app-pages-bridge.js +23 -3
- package/dist/server/app-route-handler-cache.d.ts +1 -0
- package/dist/server/app-route-handler-cache.js +1 -0
- package/dist/server/app-route-handler-dispatch.d.ts +1 -0
- package/dist/server/app-route-handler-dispatch.js +2 -0
- package/dist/server/app-route-handler-execution.d.ts +1 -0
- package/dist/server/app-route-handler-execution.js +1 -0
- package/dist/server/app-route-handler-runtime.d.ts +1 -0
- package/dist/server/app-route-handler-runtime.js +3 -2
- package/dist/server/app-rsc-handler.d.ts +1 -0
- package/dist/server/app-rsc-handler.js +4 -3
- package/dist/server/app-rsc-route-matching.d.ts +20 -1
- package/dist/server/app-rsc-route-matching.js +29 -4
- package/dist/server/app-server-action-execution.d.ts +11 -1
- package/dist/server/app-server-action-execution.js +68 -10
- package/dist/server/app-ssr-entry.d.ts +6 -0
- package/dist/server/app-ssr-entry.js +17 -1
- package/dist/server/dev-server.d.ts +1 -1
- package/dist/server/dev-server.js +54 -31
- package/dist/server/isr-cache.d.ts +37 -1
- package/dist/server/isr-cache.js +85 -1
- package/dist/server/navigation-planner.js +5 -3
- package/dist/server/navigation-trace.d.ts +1 -1
- package/dist/server/pages-node-compat.d.ts +2 -0
- package/dist/server/pages-node-compat.js +4 -0
- package/dist/server/pages-page-data.d.ts +10 -7
- package/dist/server/pages-page-data.js +4 -2
- package/dist/server/pages-page-handler.d.ts +9 -2
- package/dist/server/pages-page-handler.js +29 -16
- package/dist/server/pages-page-response.d.ts +11 -2
- package/dist/server/pages-page-response.js +8 -1
- package/dist/server/pages-readiness.d.ts +36 -0
- package/dist/server/pages-readiness.js +21 -0
- package/dist/server/pages-request-pipeline.d.ts +99 -0
- package/dist/server/pages-request-pipeline.js +209 -0
- package/dist/server/pages-revalidate.d.ts +15 -0
- package/dist/server/pages-revalidate.js +19 -0
- package/dist/server/prod-server.d.ts +6 -2
- package/dist/server/prod-server.js +101 -217
- package/dist/server/socket-error-backstop.d.ts +19 -1
- package/dist/server/socket-error-backstop.js +77 -4
- package/dist/shims/app-router-scroll.js +22 -4
- package/dist/shims/cache-runtime.js +31 -1
- package/dist/shims/error-boundary.d.ts +21 -11
- package/dist/shims/error-boundary.js +8 -1
- package/dist/shims/fetch-cache.d.ts +14 -1
- package/dist/shims/fetch-cache.js +18 -1
- package/dist/shims/hash-scroll.d.ts +1 -0
- package/dist/shims/hash-scroll.js +3 -1
- package/dist/shims/internal/link-status-registry.d.ts +43 -0
- package/dist/shims/internal/link-status-registry.js +42 -0
- package/dist/shims/internal/route-pattern-for-warning.d.ts +27 -0
- package/dist/shims/internal/route-pattern-for-warning.js +40 -0
- package/dist/shims/internal/utils.d.ts +1 -0
- package/dist/shims/link.js +20 -6
- package/dist/shims/navigation.d.ts +2 -2
- package/dist/shims/navigation.js +63 -7
- package/dist/shims/router-state.d.ts +1 -0
- package/dist/shims/router-state.js +2 -0
- package/dist/shims/router.d.ts +6 -3
- package/dist/shims/router.js +128 -21
- package/dist/utils/client-build-manifest.d.ts +8 -1
- package/dist/utils/client-build-manifest.js +30 -5
- package/dist/utils/client-entry-manifest.d.ts +11 -0
- package/dist/utils/client-entry-manifest.js +29 -0
- package/package.json +5 -1
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
//#region src/build/assets-ignore.d.ts
|
|
2
|
+
/**
|
|
3
|
+
* Build metadata that must never be served by the Cloudflare ASSETS binding.
|
|
4
|
+
*
|
|
5
|
+
* On Cloudflare Workers the ASSETS binding serves any uploaded file whose path
|
|
6
|
+
* matches the request BEFORE the Worker runs, so anything written into the
|
|
7
|
+
* client output directory (`dist/client`) is publicly fetchable unless excluded.
|
|
8
|
+
* Vite writes its build/SSR manifests under `dist/client/.vite/` (enabled for
|
|
9
|
+
* Cloudflare builds so the worker entry can compute lazy chunks), which would
|
|
10
|
+
* otherwise expose the full source-file → chunk mapping — including the paths of
|
|
11
|
+
* routes that are never linked from the UI.
|
|
12
|
+
*
|
|
13
|
+
* The Node production server already blocks `/.vite/` explicitly
|
|
14
|
+
* (see `server/static-file-cache.ts`); `.assetsignore` is the equivalent guard
|
|
15
|
+
* for the Cloudflare deployment target. wrangler matches `.assetsignore`
|
|
16
|
+
* patterns with `.gitignore` semantics (via the `ignore` package), so the bare
|
|
17
|
+
* `.vite` entry excludes the directory and everything beneath it.
|
|
18
|
+
*/
|
|
19
|
+
declare const DEFAULT_VINEXT_ASSET_IGNORE_PATTERNS: readonly string[];
|
|
20
|
+
/**
|
|
21
|
+
* Ensure a `.assetsignore` in `clientDir` contains every pattern in `patterns`.
|
|
22
|
+
*
|
|
23
|
+
* Any pre-existing (user-authored) content is preserved verbatim and only the
|
|
24
|
+
* missing patterns are appended, so the result is idempotent across rebuilds
|
|
25
|
+
* and never clobbers a `.assetsignore` the developer wrote themselves.
|
|
26
|
+
*
|
|
27
|
+
* @returns `true` when the file was created or modified, `false` when it already
|
|
28
|
+
* covered every requested pattern.
|
|
29
|
+
*/
|
|
30
|
+
declare function ensureAssetsIgnore(clientDir: string, patterns?: readonly string[]): boolean;
|
|
31
|
+
//#endregion
|
|
32
|
+
export { DEFAULT_VINEXT_ASSET_IGNORE_PATTERNS, ensureAssetsIgnore };
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
import fs from "node:fs";
|
|
2
|
+
import path from "node:path";
|
|
3
|
+
//#region src/build/assets-ignore.ts
|
|
4
|
+
/**
|
|
5
|
+
* Build metadata that must never be served by the Cloudflare ASSETS binding.
|
|
6
|
+
*
|
|
7
|
+
* On Cloudflare Workers the ASSETS binding serves any uploaded file whose path
|
|
8
|
+
* matches the request BEFORE the Worker runs, so anything written into the
|
|
9
|
+
* client output directory (`dist/client`) is publicly fetchable unless excluded.
|
|
10
|
+
* Vite writes its build/SSR manifests under `dist/client/.vite/` (enabled for
|
|
11
|
+
* Cloudflare builds so the worker entry can compute lazy chunks), which would
|
|
12
|
+
* otherwise expose the full source-file → chunk mapping — including the paths of
|
|
13
|
+
* routes that are never linked from the UI.
|
|
14
|
+
*
|
|
15
|
+
* The Node production server already blocks `/.vite/` explicitly
|
|
16
|
+
* (see `server/static-file-cache.ts`); `.assetsignore` is the equivalent guard
|
|
17
|
+
* for the Cloudflare deployment target. wrangler matches `.assetsignore`
|
|
18
|
+
* patterns with `.gitignore` semantics (via the `ignore` package), so the bare
|
|
19
|
+
* `.vite` entry excludes the directory and everything beneath it.
|
|
20
|
+
*/
|
|
21
|
+
const DEFAULT_VINEXT_ASSET_IGNORE_PATTERNS = [".vite"];
|
|
22
|
+
/** wrangler reads asset-exclusion patterns from this file in the assets dir. */
|
|
23
|
+
const ASSETS_IGNORE_FILENAME = ".assetsignore";
|
|
24
|
+
const GENERATED_HEADER = "# Keep build metadata out of the deployed asset bundle (generated by vinext)";
|
|
25
|
+
/**
|
|
26
|
+
* Ensure a `.assetsignore` in `clientDir` contains every pattern in `patterns`.
|
|
27
|
+
*
|
|
28
|
+
* Any pre-existing (user-authored) content is preserved verbatim and only the
|
|
29
|
+
* missing patterns are appended, so the result is idempotent across rebuilds
|
|
30
|
+
* and never clobbers a `.assetsignore` the developer wrote themselves.
|
|
31
|
+
*
|
|
32
|
+
* @returns `true` when the file was created or modified, `false` when it already
|
|
33
|
+
* covered every requested pattern.
|
|
34
|
+
*/
|
|
35
|
+
function ensureAssetsIgnore(clientDir, patterns = DEFAULT_VINEXT_ASSET_IGNORE_PATTERNS) {
|
|
36
|
+
const assetsIgnorePath = path.join(clientDir, ASSETS_IGNORE_FILENAME);
|
|
37
|
+
const existing = fs.existsSync(assetsIgnorePath) ? fs.readFileSync(assetsIgnorePath, "utf-8") : null;
|
|
38
|
+
const present = new Set((existing ?? "").split(/\r?\n/).map((line) => line.trim()).filter(Boolean));
|
|
39
|
+
const missing = patterns.filter((pattern) => !present.has(pattern));
|
|
40
|
+
if (missing.length === 0) return false;
|
|
41
|
+
const lines = existing && existing.trim().length > 0 ? [existing.replace(/\s*$/, "")] : [GENERATED_HEADER];
|
|
42
|
+
lines.push(...missing, "");
|
|
43
|
+
fs.mkdirSync(clientDir, { recursive: true });
|
|
44
|
+
fs.writeFileSync(assetsIgnorePath, lines.join("\n"));
|
|
45
|
+
return true;
|
|
46
|
+
}
|
|
47
|
+
//#endregion
|
|
48
|
+
export { DEFAULT_VINEXT_ASSET_IGNORE_PATTERNS, ensureAssetsIgnore };
|
|
@@ -62,6 +62,32 @@ declare function createClientCodeSplittingConfig(clientManualChunks: (id: string
|
|
|
62
62
|
name(moduleId: string): string | null;
|
|
63
63
|
}[];
|
|
64
64
|
};
|
|
65
|
+
/**
|
|
66
|
+
* Regex matching any {@link FRAMEWORK_PACKAGES} package inside `node_modules`.
|
|
67
|
+
* Derived from the package list so the regex and {@link isRscFrameworkModule}
|
|
68
|
+
* predicate can't drift.
|
|
69
|
+
*/
|
|
70
|
+
declare const RSC_FRAMEWORK_CHUNK_TEST: RegExp;
|
|
71
|
+
declare function isRscFrameworkModule(id: string): boolean;
|
|
72
|
+
/**
|
|
73
|
+
* Output config that isolates React (and the RSC flight runtime) into a
|
|
74
|
+
* dedicated "framework" chunk in the RSC server build. Returns the bundler-
|
|
75
|
+
* appropriate shape: rolldown's `codeSplitting` for Vite 8+, Rollup's
|
|
76
|
+
* `manualChunks` for Vite 7. See {@link RSC_FRAMEWORK_CHUNK_TEST} for the
|
|
77
|
+
* motivation (issue #1549).
|
|
78
|
+
*/
|
|
79
|
+
declare function createRscFrameworkChunkOutputConfig(viteMajorVersion: number): {
|
|
80
|
+
codeSplitting: {
|
|
81
|
+
groups: {
|
|
82
|
+
name: string;
|
|
83
|
+
test: RegExp;
|
|
84
|
+
}[];
|
|
85
|
+
};
|
|
86
|
+
manualChunks?: undefined;
|
|
87
|
+
} | {
|
|
88
|
+
manualChunks(id: string): string | undefined;
|
|
89
|
+
codeSplitting?: undefined;
|
|
90
|
+
};
|
|
65
91
|
/**
|
|
66
92
|
* Rollup treeshake configuration for production client builds.
|
|
67
93
|
*
|
|
@@ -129,4 +155,4 @@ type VinextBuildConfigWithLegacy = VinextBuildConfig & {
|
|
|
129
155
|
declare function getBuildBundlerOptions(build: UserConfig["build"] | undefined): VinextBuildBundlerOptions | undefined;
|
|
130
156
|
declare function withBuildBundlerOptions(viteMajorVersion: number, bundlerOptions: VinextBuildBundlerOptions): Partial<VinextBuildConfigWithLegacy>;
|
|
131
157
|
//#endregion
|
|
132
|
-
export { clientTreeshakeConfig, createClientAssetFileNames, createClientCodeSplittingConfig, createClientManualChunks, createClientOutputConfig, getBuildBundlerOptions, getClientTreeshakeConfigForVite, withBuildBundlerOptions };
|
|
158
|
+
export { RSC_FRAMEWORK_CHUNK_TEST, clientTreeshakeConfig, createClientAssetFileNames, createClientCodeSplittingConfig, createClientManualChunks, createClientOutputConfig, createRscFrameworkChunkOutputConfig, getBuildBundlerOptions, getClientTreeshakeConfigForVite, isRscFrameworkModule, withBuildBundlerOptions };
|
|
@@ -105,6 +105,63 @@ function createClientCodeSplittingConfig(clientManualChunks) {
|
|
|
105
105
|
};
|
|
106
106
|
}
|
|
107
107
|
/**
|
|
108
|
+
* Matches React framework packages (and the RSC flight runtime) inside
|
|
109
|
+
* `node_modules`. Used to split them into a dedicated "framework" chunk in the
|
|
110
|
+
* RSC server build.
|
|
111
|
+
*
|
|
112
|
+
* Why the RSC build needs this: without an explicit framework chunk, the
|
|
113
|
+
* bundler colocates React into whichever chunk first reaches it — typically the
|
|
114
|
+
* RSC entry chunk, which also carries the root layout's CSS. Modules that only
|
|
115
|
+
* import React for runtime helpers (notably `app/global-not-found.tsx`, which
|
|
116
|
+
* replaces the root layout for route-miss 404s) then import that entry chunk
|
|
117
|
+
* and inherit the root layout's CSS in their `serverResources` metadata. The
|
|
118
|
+
* 404 document ends up linking the layout's stylesheet last, so the layout's
|
|
119
|
+
* rules win the cascade over global-not-found's — the bug tracked in
|
|
120
|
+
* https://github.com/cloudflare/vinext/issues/1549.
|
|
121
|
+
*
|
|
122
|
+
* Splitting React into its own (CSS-free) chunk means global-not-found imports
|
|
123
|
+
* the framework chunk instead of the layout-bearing entry chunk, so it no
|
|
124
|
+
* longer inherits the root layout's CSS. The match list mirrors the client
|
|
125
|
+
* build's `framework` chunk, plus `react-server-dom-webpack` for the RSC flight
|
|
126
|
+
* runtime that the server environment bundles.
|
|
127
|
+
*
|
|
128
|
+
* Uses `[\\/]` rather than `/` for the path separator so it matches on Windows
|
|
129
|
+
* too, per the rolldown `codeSplitting` docs.
|
|
130
|
+
*/
|
|
131
|
+
const FRAMEWORK_PACKAGES = [
|
|
132
|
+
"react",
|
|
133
|
+
"react-dom",
|
|
134
|
+
"scheduler",
|
|
135
|
+
"react-server-dom-webpack"
|
|
136
|
+
];
|
|
137
|
+
/**
|
|
138
|
+
* Regex matching any {@link FRAMEWORK_PACKAGES} package inside `node_modules`.
|
|
139
|
+
* Derived from the package list so the regex and {@link isRscFrameworkModule}
|
|
140
|
+
* predicate can't drift.
|
|
141
|
+
*/
|
|
142
|
+
const RSC_FRAMEWORK_CHUNK_TEST = new RegExp(`[\\\\/]node_modules[\\\\/](${FRAMEWORK_PACKAGES.join("|")})[\\\\/]`);
|
|
143
|
+
function isRscFrameworkModule(id) {
|
|
144
|
+
if (!id.includes("node_modules")) return false;
|
|
145
|
+
const pkg = getPackageName(id);
|
|
146
|
+
return pkg !== null && FRAMEWORK_PACKAGES.includes(pkg);
|
|
147
|
+
}
|
|
148
|
+
/**
|
|
149
|
+
* Output config that isolates React (and the RSC flight runtime) into a
|
|
150
|
+
* dedicated "framework" chunk in the RSC server build. Returns the bundler-
|
|
151
|
+
* appropriate shape: rolldown's `codeSplitting` for Vite 8+, Rollup's
|
|
152
|
+
* `manualChunks` for Vite 7. See {@link RSC_FRAMEWORK_CHUNK_TEST} for the
|
|
153
|
+
* motivation (issue #1549).
|
|
154
|
+
*/
|
|
155
|
+
function createRscFrameworkChunkOutputConfig(viteMajorVersion) {
|
|
156
|
+
if (viteMajorVersion >= 8) return { codeSplitting: { groups: [{
|
|
157
|
+
name: "framework",
|
|
158
|
+
test: RSC_FRAMEWORK_CHUNK_TEST
|
|
159
|
+
}] } };
|
|
160
|
+
return { manualChunks(id) {
|
|
161
|
+
return isRscFrameworkModule(id) ? "framework" : void 0;
|
|
162
|
+
} };
|
|
163
|
+
}
|
|
164
|
+
/**
|
|
108
165
|
* Rollup treeshake configuration for production client builds.
|
|
109
166
|
*
|
|
110
167
|
* Uses the 'recommended' preset as a safe base, then overrides
|
|
@@ -171,4 +228,4 @@ function withBuildBundlerOptions(viteMajorVersion, bundlerOptions) {
|
|
|
171
228
|
return viteMajorVersion >= 8 ? { rolldownOptions: bundlerOptions } : { rollupOptions: bundlerOptions };
|
|
172
229
|
}
|
|
173
230
|
//#endregion
|
|
174
|
-
export { clientTreeshakeConfig, createClientAssetFileNames, createClientCodeSplittingConfig, createClientManualChunks, createClientOutputConfig, getBuildBundlerOptions, getClientTreeshakeConfigForVite, withBuildBundlerOptions };
|
|
231
|
+
export { RSC_FRAMEWORK_CHUNK_TEST, clientTreeshakeConfig, createClientAssetFileNames, createClientCodeSplittingConfig, createClientManualChunks, createClientOutputConfig, createRscFrameworkChunkOutputConfig, getBuildBundlerOptions, getClientTreeshakeConfigForVite, isRscFrameworkModule, withBuildBundlerOptions };
|
package/dist/cli.js
CHANGED
|
@@ -18,6 +18,7 @@ import { createRequire } from "node:module";
|
|
|
18
18
|
import fs from "node:fs";
|
|
19
19
|
import path from "node:path";
|
|
20
20
|
import { pathToFileURL } from "node:url";
|
|
21
|
+
import { randomBytes } from "node:crypto";
|
|
21
22
|
import { execFileSync } from "node:child_process";
|
|
22
23
|
//#region src/cli.ts
|
|
23
24
|
/**
|
|
@@ -263,6 +264,7 @@ async function buildApp() {
|
|
|
263
264
|
const resolvedNextConfig = await resolveNextConfig(await loadNextConfig(root, PHASE_PRODUCTION_BUILD), root);
|
|
264
265
|
process.env.__VINEXT_SHARED_BUILD_ID = resolvedNextConfig.buildId;
|
|
265
266
|
process.env.__VINEXT_SHARED_RSC_COMPATIBILITY_ID = createRscCompatibilityId(resolvedNextConfig);
|
|
267
|
+
if (!process.env.__VINEXT_SHARED_REVALIDATE_SECRET) process.env.__VINEXT_SHARED_REVALIDATE_SECRET = randomBytes(32).toString("hex");
|
|
266
268
|
const outputMode = resolvedNextConfig.output;
|
|
267
269
|
const distDir = path.resolve(root, "dist");
|
|
268
270
|
if (outputMode === "standalone") {
|
|
@@ -26,6 +26,14 @@ type NavigationRuntimeFunctions = {
|
|
|
26
26
|
commitHashNavigation?: (href: string, historyUpdateMode: NavigationRuntimeHistoryUpdateMode, scroll: boolean) => void;
|
|
27
27
|
navigateExternal?: (href: string, historyUpdateMode: NavigationRuntimeHistoryUpdateMode) => Promise<void>;
|
|
28
28
|
navigate?: NavigationRuntimeNavigate;
|
|
29
|
+
/**
|
|
30
|
+
* Called at the start of every App Router navigation so the <Link> shim can
|
|
31
|
+
* reset any link that is still showing a `useLinkStatus()` pending state but
|
|
32
|
+
* is not the one driving this navigation (e.g. a programmatic router.push or
|
|
33
|
+
* a shallow-routing transition). Registered by shims/link.tsx; decoupled
|
|
34
|
+
* through the runtime to avoid a circular import with shims/navigation.ts.
|
|
35
|
+
*/
|
|
36
|
+
notifyLinkNavigationStart?: () => void;
|
|
29
37
|
pingVisibleLinks?: () => void;
|
|
30
38
|
};
|
|
31
39
|
type NavigationRuntimeBootstrap = {
|
|
@@ -31,7 +31,7 @@ function readRuntimeWindow() {
|
|
|
31
31
|
}
|
|
32
32
|
function isNavigationRuntimeFunctions(value) {
|
|
33
33
|
if (!isUnknownRecord(value)) return false;
|
|
34
|
-
return isOptionalRuntimeFunction(Reflect.get(value, "clearNavigationCaches")) && isOptionalRuntimeFunction(Reflect.get(value, "commitHashNavigation")) && isOptionalRuntimeFunction(Reflect.get(value, "navigateExternal")) && isOptionalRuntimeFunction(Reflect.get(value, "navigate")) && isOptionalRuntimeFunction(Reflect.get(value, "pingVisibleLinks"));
|
|
34
|
+
return isOptionalRuntimeFunction(Reflect.get(value, "clearNavigationCaches")) && isOptionalRuntimeFunction(Reflect.get(value, "commitHashNavigation")) && isOptionalRuntimeFunction(Reflect.get(value, "navigateExternal")) && isOptionalRuntimeFunction(Reflect.get(value, "navigate")) && isOptionalRuntimeFunction(Reflect.get(value, "notifyLinkNavigationStart")) && isOptionalRuntimeFunction(Reflect.get(value, "pingVisibleLinks"));
|
|
35
35
|
}
|
|
36
36
|
function isNavigationRuntimeRscChunk(value) {
|
|
37
37
|
if (typeof value === "string") return true;
|
|
@@ -10,7 +10,8 @@ type VinextNextData = {
|
|
|
10
10
|
/** vinext-specific additions (not part of Next.js upstream). */__vinext?: {
|
|
11
11
|
/** Absolute URL of the page module for dynamic import. */pageModuleUrl?: string; /** Absolute URL of the `_app` module for dynamic import. */
|
|
12
12
|
appModuleUrl?: string; /** True when the Pages Router server has middleware/proxy configured. */
|
|
13
|
-
hasMiddleware?: boolean;
|
|
13
|
+
hasMiddleware?: boolean; /** True when build-time rewrites can affect the initial Pages Router ready state. */
|
|
14
|
+
hasRewrites?: boolean;
|
|
14
15
|
};
|
|
15
16
|
} & NEXT_DATA;
|
|
16
17
|
type BrowserVinextNextData = NonNullable<Window["__NEXT_DATA__"]> & VinextNextData;
|
|
@@ -159,6 +159,25 @@ declare function sanitizeDestination(dest: string): string;
|
|
|
159
159
|
* per RFC 3986, plus protocol-relative URLs (//).
|
|
160
160
|
*/
|
|
161
161
|
declare function isExternalUrl(url: string): boolean;
|
|
162
|
+
/**
|
|
163
|
+
* Merge the original request's query params into a config-redirect
|
|
164
|
+
* destination, preserving them on the resulting `Location`.
|
|
165
|
+
*
|
|
166
|
+
* Next.js carries the original request query across config redirects
|
|
167
|
+
* (`prepareDestination({ query: parsedUrl.query })` →
|
|
168
|
+
* `stringifyQuery(...)` in resolve-routes.ts). This matters for App Router
|
|
169
|
+
* RSC client navigations: the cache-busting `_rsc` query must survive the
|
|
170
|
+
* redirect so the browser's auto-followed request to the destination is
|
|
171
|
+
* still treated as an RSC fetch. Dropping it breaks RSC fetch semantics
|
|
172
|
+
* (issue #1529).
|
|
173
|
+
*
|
|
174
|
+
* Destination query params win — a request param is only carried over when
|
|
175
|
+
* the destination does not already specify that key. Mirrors the merge
|
|
176
|
+
* semantics in `proxyExternalRequest`. External destinations are returned
|
|
177
|
+
* untouched (a config redirect to another origin should not leak the
|
|
178
|
+
* original request's query).
|
|
179
|
+
*/
|
|
180
|
+
declare function preserveRedirectDestinationQuery(destination: string, requestSearch: string): string;
|
|
162
181
|
/**
|
|
163
182
|
* Proxy an incoming request to an external URL and return the upstream response.
|
|
164
183
|
*
|
|
@@ -218,4 +237,4 @@ declare function applyLocaleToRoutes<T extends NextRedirect | NextRewrite>(route
|
|
|
218
237
|
trailingSlash?: boolean;
|
|
219
238
|
}): T[];
|
|
220
239
|
//#endregion
|
|
221
|
-
export { BasePathMatchState, RequestContext, applyLocaleToRoutes, applyMiddlewareRequestHeaders, checkHasConditions, escapeHeaderSource, isExternalUrl, isSafeRegex, matchConfigPattern, matchHeaders, matchRedirect, matchRewrite, normalizeHost, parseCookies, proxyExternalRequest, requestContextFromRequest, safeRegExp, sanitizeDestination };
|
|
240
|
+
export { BasePathMatchState, RequestContext, applyLocaleToRoutes, applyMiddlewareRequestHeaders, checkHasConditions, escapeHeaderSource, isExternalUrl, isSafeRegex, matchConfigPattern, matchHeaders, matchRedirect, matchRewrite, normalizeHost, parseCookies, preserveRedirectDestinationQuery, proxyExternalRequest, requestContextFromRequest, safeRegExp, sanitizeDestination };
|
|
@@ -764,6 +764,40 @@ function isExternalUrl(url) {
|
|
|
764
764
|
return /^[a-z][a-z0-9+.-]*:/i.test(url) || url.startsWith("//");
|
|
765
765
|
}
|
|
766
766
|
/**
|
|
767
|
+
* Merge the original request's query params into a config-redirect
|
|
768
|
+
* destination, preserving them on the resulting `Location`.
|
|
769
|
+
*
|
|
770
|
+
* Next.js carries the original request query across config redirects
|
|
771
|
+
* (`prepareDestination({ query: parsedUrl.query })` →
|
|
772
|
+
* `stringifyQuery(...)` in resolve-routes.ts). This matters for App Router
|
|
773
|
+
* RSC client navigations: the cache-busting `_rsc` query must survive the
|
|
774
|
+
* redirect so the browser's auto-followed request to the destination is
|
|
775
|
+
* still treated as an RSC fetch. Dropping it breaks RSC fetch semantics
|
|
776
|
+
* (issue #1529).
|
|
777
|
+
*
|
|
778
|
+
* Destination query params win — a request param is only carried over when
|
|
779
|
+
* the destination does not already specify that key. Mirrors the merge
|
|
780
|
+
* semantics in `proxyExternalRequest`. External destinations are returned
|
|
781
|
+
* untouched (a config redirect to another origin should not leak the
|
|
782
|
+
* original request's query).
|
|
783
|
+
*/
|
|
784
|
+
function preserveRedirectDestinationQuery(destination, requestSearch) {
|
|
785
|
+
if (requestSearch === "" || requestSearch === "?" || isExternalUrl(destination)) return destination;
|
|
786
|
+
const requestParams = new URLSearchParams(requestSearch);
|
|
787
|
+
if ([...requestParams.keys()].length === 0) return destination;
|
|
788
|
+
const hashIndex = destination.indexOf("#");
|
|
789
|
+
const hash = hashIndex === -1 ? "" : destination.slice(hashIndex);
|
|
790
|
+
const beforeHash = hashIndex === -1 ? destination : destination.slice(0, hashIndex);
|
|
791
|
+
const queryIndex = beforeHash.indexOf("?");
|
|
792
|
+
const pathPart = queryIndex === -1 ? beforeHash : beforeHash.slice(0, queryIndex);
|
|
793
|
+
const destQuery = queryIndex === -1 ? "" : beforeHash.slice(queryIndex + 1);
|
|
794
|
+
const merged = new URLSearchParams(destQuery);
|
|
795
|
+
const destKeys = new Set(merged.keys());
|
|
796
|
+
for (const [key, value] of requestParams) if (!destKeys.has(key)) merged.append(key, value);
|
|
797
|
+
const mergedQuery = merged.toString();
|
|
798
|
+
return mergedQuery === "" ? `${pathPart}${hash}` : `${pathPart}?${mergedQuery}${hash}`;
|
|
799
|
+
}
|
|
800
|
+
/**
|
|
767
801
|
* Proxy an incoming request to an external URL and return the upstream response.
|
|
768
802
|
*
|
|
769
803
|
* Used for external rewrites (e.g. `/ph/:path*` → `https://us.i.posthog.com/:path*`).
|
|
@@ -925,4 +959,4 @@ function applyLocaleToRoutes(routes, i18n, type, options = {}) {
|
|
|
925
959
|
return out;
|
|
926
960
|
}
|
|
927
961
|
//#endregion
|
|
928
|
-
export { applyLocaleToRoutes, applyMiddlewareRequestHeaders, checkHasConditions, escapeHeaderSource, isExternalUrl, isSafeRegex, matchConfigPattern, matchHeaders, matchRedirect, matchRewrite, normalizeHost, parseCookies, proxyExternalRequest, requestContextFromRequest, safeRegExp, sanitizeDestination };
|
|
962
|
+
export { applyLocaleToRoutes, applyMiddlewareRequestHeaders, checkHasConditions, escapeHeaderSource, isExternalUrl, isSafeRegex, matchConfigPattern, matchHeaders, matchRedirect, matchRewrite, normalizeHost, parseCookies, preserveRedirectDestinationQuery, proxyExternalRequest, requestContextFromRequest, safeRegExp, sanitizeDestination };
|
|
@@ -132,7 +132,14 @@ type NextConfig = {
|
|
|
132
132
|
*/
|
|
133
133
|
instrumentationClientInject?: string[]; /** Extra origins allowed to access the dev server. */
|
|
134
134
|
allowedDevOrigins?: string[]; /** Maximum age in seconds for stale ISR entries before blocking regeneration. */
|
|
135
|
-
expireTime?: number;
|
|
135
|
+
expireTime?: number;
|
|
136
|
+
/**
|
|
137
|
+
* Maximum total length (in characters) of the preload `Link` header emitted
|
|
138
|
+
* during App Router SSR. React drops whole entries once the limit is
|
|
139
|
+
* exceeded; `0` disables emission entirely. Defaults to 6000.
|
|
140
|
+
* @see https://nextjs.org/docs/app/api-reference/config/next-config-js/reactMaxHeadersLength
|
|
141
|
+
*/
|
|
142
|
+
reactMaxHeadersLength?: number; /** User agents that require blocking metadata in the initial head. */
|
|
136
143
|
htmlLimitedBots?: RegExp | string;
|
|
137
144
|
/**
|
|
138
145
|
* Enable Cache Components (Next.js 16).
|
|
@@ -244,8 +251,14 @@ type ResolvedNextConfig = {
|
|
|
244
251
|
serverActionsAllowedOrigins: string[]; /** Packages whose barrel imports should be optimized (from experimental.optimizePackageImports). */
|
|
245
252
|
optimizePackageImports: string[]; /** Inline app CSS into production HTML (from experimental.inlineCss). */
|
|
246
253
|
inlineCss: boolean; /** Parsed body size limit for server actions in bytes (from experimental.serverActions.bodySizeLimit). Defaults to 1MB. */
|
|
247
|
-
serverActionsBodySizeLimit: number; /**
|
|
248
|
-
|
|
254
|
+
serverActionsBodySizeLimit: number; /** Verbatim body size limit config value (e.g. "2mb") for the "Body exceeded {limit} limit" error. Defaults to "1 MB". */
|
|
255
|
+
serverActionsBodySizeLimitLabel: string; /** Route-level expire fallback in seconds for ISR entries with numeric revalidate. */
|
|
256
|
+
expireTime: number;
|
|
257
|
+
/**
|
|
258
|
+
* Maximum total length (in characters) of the preload `Link` header emitted
|
|
259
|
+
* during App Router SSR. `0` disables emission. Defaults to 6000.
|
|
260
|
+
*/
|
|
261
|
+
reactMaxHeadersLength: number; /** Serialized htmlLimitedBots regexp source from next.config. */
|
|
249
262
|
htmlLimitedBots: string | undefined;
|
|
250
263
|
/**
|
|
251
264
|
* Packages that should be treated as server-external (not bundled by Vite).
|
|
@@ -72,6 +72,12 @@ const CONFIG_FILES = [
|
|
|
72
72
|
];
|
|
73
73
|
const DEFAULT_EXPIRE_TIME = 31536e3;
|
|
74
74
|
/**
|
|
75
|
+
* Default cap for the App Router preload `Link` header length, matching the
|
|
76
|
+
* Next.js `defaultConfig.reactMaxHeadersLength`.
|
|
77
|
+
* @see https://nextjs.org/docs/app/api-reference/config/next-config-js/reactMaxHeadersLength
|
|
78
|
+
*/
|
|
79
|
+
const DEFAULT_REACT_MAX_HEADERS_LENGTH = 6e3;
|
|
80
|
+
/**
|
|
75
81
|
* Check whether an error indicates a CJS module was loaded in an ESM context
|
|
76
82
|
* (i.e. the file uses `require()` which is not available in ESM).
|
|
77
83
|
*/
|
|
@@ -523,7 +529,9 @@ async function resolveNextConfig(config, root = process.cwd()) {
|
|
|
523
529
|
optimizePackageImports: [],
|
|
524
530
|
inlineCss: false,
|
|
525
531
|
serverActionsBodySizeLimit: 1 * 1024 * 1024,
|
|
532
|
+
serverActionsBodySizeLimitLabel: "1 MB",
|
|
526
533
|
expireTime: DEFAULT_EXPIRE_TIME,
|
|
534
|
+
reactMaxHeadersLength: DEFAULT_REACT_MAX_HEADERS_LENGTH,
|
|
527
535
|
htmlLimitedBots: void 0,
|
|
528
536
|
serverExternalPackages: [],
|
|
529
537
|
cacheHandler: void 0,
|
|
@@ -588,7 +596,9 @@ async function resolveNextConfig(config, root = process.cwd()) {
|
|
|
588
596
|
const experimental = readOptionalRecord(config.experimental);
|
|
589
597
|
const serverActionsConfig = readOptionalRecord(experimental?.serverActions);
|
|
590
598
|
const serverActionsAllowedOrigins = readStringArray(serverActionsConfig?.allowedOrigins);
|
|
591
|
-
const
|
|
599
|
+
const serverActionsBodySizeLimitConfig = readOptionalBodySizeLimit(serverActionsConfig?.bodySizeLimit);
|
|
600
|
+
const serverActionsBodySizeLimit = parseBodySizeLimit(serverActionsBodySizeLimitConfig);
|
|
601
|
+
const serverActionsBodySizeLimitLabel = serverActionsBodySizeLimitConfig === void 0 ? "1 MB" : String(serverActionsBodySizeLimitConfig);
|
|
592
602
|
const hashSalt = (readOptionalString(experimental?.outputHashSalt) ?? "") + (process.env.NEXT_HASH_SALT ?? "");
|
|
593
603
|
const htmlLimitedBots = resolveHtmlLimitedBots(config.htmlLimitedBots);
|
|
594
604
|
const rawOptimize = experimental?.optimizePackageImports;
|
|
@@ -658,7 +668,9 @@ async function resolveNextConfig(config, root = process.cwd()) {
|
|
|
658
668
|
optimizePackageImports,
|
|
659
669
|
inlineCss,
|
|
660
670
|
serverActionsBodySizeLimit,
|
|
671
|
+
serverActionsBodySizeLimitLabel,
|
|
661
672
|
expireTime: typeof config.expireTime === "number" ? config.expireTime : DEFAULT_EXPIRE_TIME,
|
|
673
|
+
reactMaxHeadersLength: typeof config.reactMaxHeadersLength === "number" ? config.reactMaxHeadersLength : DEFAULT_REACT_MAX_HEADERS_LENGTH,
|
|
662
674
|
htmlLimitedBots,
|
|
663
675
|
serverExternalPackages,
|
|
664
676
|
cacheHandler,
|
|
@@ -680,12 +692,28 @@ async function resolveNextConfig(config, root = process.cwd()) {
|
|
|
680
692
|
if (resolved.basePath !== "" && resolved.basePath !== "/" && resolved.assetPrefix === "") resolved.assetPrefix = resolved.basePath;
|
|
681
693
|
return resolved;
|
|
682
694
|
}
|
|
695
|
+
/**
|
|
696
|
+
* Whether an alias target is a relative filesystem path (`./foo`, `../foo`,
|
|
697
|
+
* or a bare `.`/`..`) that should be resolved against the project root.
|
|
698
|
+
*
|
|
699
|
+
* Both Next.js Turbopack `resolveAlias` and webpack `resolve.alias` accept two
|
|
700
|
+
* kinds of values: relative/absolute file paths AND bare package specifiers
|
|
701
|
+
* (e.g. `react`, `preact/compat`, `@scope/pkg`). Bare specifiers must be left
|
|
702
|
+
* verbatim so Vite/Rolldown re-resolves them through node_modules — resolving
|
|
703
|
+
* them against `root` mangles them into bogus `<root>/react` paths and breaks
|
|
704
|
+
* the build with "No such file or directory". See cloudflare/vinext#1507.
|
|
705
|
+
*/
|
|
706
|
+
function isRelativeAliasTarget(value) {
|
|
707
|
+
return value === "." || value === ".." || value.startsWith("./") || value.startsWith("../");
|
|
708
|
+
}
|
|
683
709
|
function normalizeAliasEntries(aliases, root) {
|
|
684
710
|
if (!aliases) return {};
|
|
685
711
|
const normalized = {};
|
|
686
712
|
for (const [key, value] of Object.entries(aliases)) {
|
|
687
713
|
if (typeof value !== "string") continue;
|
|
688
|
-
|
|
714
|
+
if (path.isAbsolute(value)) normalized[key] = value;
|
|
715
|
+
else if (isRelativeAliasTarget(value)) normalized[key] = path.resolve(root, value);
|
|
716
|
+
else normalized[key] = value;
|
|
689
717
|
}
|
|
690
718
|
return normalized;
|
|
691
719
|
}
|