vinext 0.1.0 → 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/assets-ignore.d.ts +32 -0
- package/dist/build/assets-ignore.js +48 -0
- package/dist/build/client-build-config.d.ts +33 -1
- package/dist/build/client-build-config.js +66 -1
- package/dist/check.js +4 -3
- package/dist/cli.js +2 -0
- package/dist/client/navigation-runtime.d.ts +11 -2
- package/dist/client/navigation-runtime.js +1 -1
- package/dist/client/vinext-next-data.d.ts +2 -1
- package/dist/client/window-next.d.ts +6 -4
- package/dist/config/config-matchers.d.ts +31 -5
- package/dist/config/config-matchers.js +50 -3
- package/dist/config/next-config.d.ts +29 -3
- package/dist/config/next-config.js +32 -2
- package/dist/deploy.js +47 -304
- package/dist/entries/app-rsc-entry.d.ts +8 -2
- package/dist/entries/app-rsc-entry.js +61 -5
- package/dist/entries/app-rsc-manifest.js +20 -2
- package/dist/entries/pages-client-entry.js +1 -1
- package/dist/entries/pages-server-entry.js +16 -7
- package/dist/index.d.ts +0 -2
- package/dist/index.js +233 -280
- 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/postcss.js +18 -14
- package/dist/plugins/require-context.d.ts +6 -0
- package/dist/plugins/require-context.js +184 -0
- 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 +35 -2
- package/dist/routing/app-route-graph.js +179 -8
- package/dist/routing/file-matcher.js +1 -1
- 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 +155 -215
- 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-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 +13 -2
- package/dist/server/app-browser-navigation-controller.js +83 -4
- package/dist/server/app-browser-popstate.d.ts +12 -3
- package/dist/server/app-browser-popstate.js +19 -4
- 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.d.ts +3 -0
- package/dist/server/app-browser-state.js +10 -10
- package/dist/server/app-browser-visible-commit.js +10 -8
- package/dist/server/app-fallback-renderer.d.ts +2 -1
- package/dist/server/app-fallback-renderer.js +3 -1
- package/dist/server/app-history-state.d.ts +45 -1
- package/dist/server/app-history-state.js +109 -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 +45 -21
- package/dist/server/app-page-cache.js +9 -7
- package/dist/server/app-page-dispatch.d.ts +14 -0
- package/dist/server/app-page-dispatch.js +21 -6
- package/dist/server/app-page-element-builder.d.ts +23 -2
- package/dist/server/app-page-element-builder.js +58 -17
- 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 +7 -1
- package/dist/server/app-page-render.js +11 -16
- package/dist/server/app-page-request.d.ts +9 -6
- package/dist/server/app-page-request.js +14 -10
- package/dist/server/app-page-response.d.ts +2 -2
- package/dist/server/app-page-response.js +2 -2
- package/dist/server/app-page-route-wiring.d.ts +3 -1
- package/dist/server/app-page-route-wiring.js +10 -8
- package/dist/server/app-page-stream.d.ts +37 -7
- package/dist/server/app-page-stream.js +36 -6
- 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-response.js +11 -10
- package/dist/server/app-route-handler-runtime.d.ts +1 -0
- package/dist/server/app-route-handler-runtime.js +15 -3
- package/dist/server/app-rsc-handler.d.ts +1 -0
- package/dist/server/app-rsc-handler.js +5 -4
- package/dist/server/app-rsc-response-finalizer.js +1 -1
- 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 +22 -1
- package/dist/server/app-server-action-execution.js +73 -12
- package/dist/server/app-ssr-entry.d.ts +6 -0
- package/dist/server/app-ssr-entry.js +19 -3
- package/dist/server/app-ssr-stream.js +9 -1
- package/dist/server/dev-lockfile.js +2 -1
- package/dist/server/dev-server.d.ts +1 -1
- package/dist/server/dev-server.js +97 -43
- 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-cache.d.ts +37 -1
- package/dist/server/isr-cache.js +85 -1
- 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 +193 -3
- package/dist/server/navigation-trace.d.ts +12 -2
- 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 +5 -11
- package/dist/server/pages-node-compat.js +175 -118
- package/dist/server/pages-page-data.d.ts +38 -7
- package/dist/server/pages-page-data.js +64 -18
- package/dist/server/pages-page-handler.d.ts +10 -2
- package/dist/server/pages-page-handler.js +49 -20
- package/dist/server/pages-page-response.d.ts +55 -2
- package/dist/server/pages-page-response.js +74 -6
- 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 +113 -0
- package/dist/server/pages-request-pipeline.js +230 -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 +45 -3
- package/dist/server/prod-server.js +182 -234
- 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 +39 -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 +17 -7
- package/dist/shims/error-boundary.js +8 -1
- package/dist/shims/error.js +37 -11
- package/dist/shims/fetch-cache.d.ts +22 -1
- package/dist/shims/fetch-cache.js +28 -1
- package/dist/shims/hash-scroll.d.ts +1 -0
- package/dist/shims/hash-scroll.js +3 -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/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/metadata.d.ts +6 -2
- package/dist/shims/metadata.js +32 -14
- package/dist/shims/navigation.d.ts +9 -18
- package/dist/shims/navigation.js +96 -23
- 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 +156 -22
- 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.d.ts +8 -1
- package/dist/utils/client-build-manifest.js +41 -6
- package/dist/utils/client-entry-manifest.d.ts +11 -0
- package/dist/utils/client-entry-manifest.js +29 -0
- 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 +6 -2
|
@@ -2,22 +2,20 @@ import { normalizePathnameForRouteMatchStrict } from "../routing/utils.js";
|
|
|
2
2
|
import { hasBasePath, stripBasePath } from "../utils/base-path.js";
|
|
3
3
|
import { VINEXT_PRERENDER_ROUTE_PARAMS_HEADER, VINEXT_PRERENDER_SECRET_HEADER, VINEXT_STATIC_FILE_HEADER } from "./headers.js";
|
|
4
4
|
import { normalizePath } from "./normalize-path.js";
|
|
5
|
-
import { applyMiddlewareRequestHeaders, isExternalUrl, matchRedirect, matchRewrite, proxyExternalRequest, requestContextFromRequest, sanitizeDestination } from "../config/config-matchers.js";
|
|
6
5
|
import { notFoundResponse } from "./http-error-responses.js";
|
|
7
|
-
import {
|
|
8
|
-
import {
|
|
9
|
-
import { normalizeDefaultLocalePathname, stripI18nLocaleForApiRoute } from "./pages-i18n.js";
|
|
6
|
+
import { filterInternalHeaders, isOpenRedirectShaped } from "./request-pipeline.js";
|
|
7
|
+
import { isUnknownRecord } from "../utils/record.js";
|
|
10
8
|
import { resolveRequestHost, resolveRequestProtocol, trustProxy, trustedHosts } from "./proxy-trust.js";
|
|
11
9
|
import { DEFAULT_DEVICE_SIZES, DEFAULT_IMAGE_SIZES, isImageOptimizationPath, isSafeImageContentType, parseImageParams } from "./image-optimization.js";
|
|
12
10
|
import { installSocketErrorBackstop } from "./socket-error-backstop.js";
|
|
13
|
-
import { ASSET_PREFIX_URL_DIR, assetPrefixPathname, isAbsoluteAssetPrefix
|
|
11
|
+
import { ASSET_PREFIX_URL_DIR, assetPrefixPathname, isAbsoluteAssetPrefix } from "../utils/asset-prefix.js";
|
|
14
12
|
import { CONTENT_TYPES, StaticFileCache, etagFromFilenameHash } from "./static-file-cache.js";
|
|
15
13
|
import { buildNextDataNotFoundResponse, isNextDataPathname, parseNextDataPathname } from "./pages-data-route.js";
|
|
16
14
|
import { collectInlineCssManifest } from "../build/inline-css.js";
|
|
17
|
-
import {
|
|
15
|
+
import { mergeHeaders } from "./worker-utils.js";
|
|
16
|
+
import { runPagesRequest, wrapMiddlewareWithBasePath } from "./pages-request-pipeline.js";
|
|
18
17
|
import { readTrustedPrerenderRouteParamsFromHeaders, serializePrerenderRouteParamsHeader } from "./prerender-route-params.js";
|
|
19
|
-
import {
|
|
20
|
-
import { findClientEntryFile, readClientBuildManifest } from "../utils/client-build-manifest.js";
|
|
18
|
+
import { computeClientRuntimeMetadata } from "../utils/client-runtime-metadata.js";
|
|
21
19
|
import { readPrerenderSecret } from "../build/server-manifest.js";
|
|
22
20
|
import { seedMemoryCacheFromPrerender } from "./seed-cache.js";
|
|
23
21
|
import fs from "node:fs";
|
|
@@ -47,6 +45,68 @@ import { Readable, pipeline } from "node:stream";
|
|
|
47
45
|
* - dist/server/index.js — RSC entry (default export: handler(Request) → Response)
|
|
48
46
|
* - dist/server/ssr/index.js — SSR entry (imported by RSC entry at runtime)
|
|
49
47
|
*/
|
|
48
|
+
/**
|
|
49
|
+
* mtime of the build each bare (query-less) server-entry URL was first
|
|
50
|
+
* imported from in this process. Node's ESM cache pins a bare URL to that
|
|
51
|
+
* build forever, so rebuilds to the same path must be detected and loaded
|
|
52
|
+
* through a cache-busted URL instead.
|
|
53
|
+
*/
|
|
54
|
+
const bareServerEntryMtimes = /* @__PURE__ */ new Map();
|
|
55
|
+
/**
|
|
56
|
+
* Import a built server entry module (App Router RSC entry or Pages Router
|
|
57
|
+
* server entry) by absolute file path.
|
|
58
|
+
*
|
|
59
|
+
* The first import of a given path uses the plain file:// URL with NO query
|
|
60
|
+
* string. This is load-bearing: code-split builds emit lazy chunks that
|
|
61
|
+
* import the entry back by bare specifier (default Vite builds on both
|
|
62
|
+
* supported majors — Rollup on Vite 7 and Rolldown on Vite 8 — hoist modules
|
|
63
|
+
* shared between the entry's static graph and lazy route chunks into the
|
|
64
|
+
* entry chunk, which the chunks then import as e.g. "../../index.js").
|
|
65
|
+
* Node keys its ESM cache on the full URL including the query string, so if
|
|
66
|
+
* the server imported the entry as `index.js?t=<mtime>`, a chunk's bare
|
|
67
|
+
* back-import would evaluate the entire server bundle a second time and
|
|
68
|
+
* module-level singletons (db pools, service registries) would silently
|
|
69
|
+
* diverge between the two copies. See
|
|
70
|
+
* https://github.com/cloudflare/vinext/issues/1923.
|
|
71
|
+
*
|
|
72
|
+
* A `?t=<mtime>` query string is appended only when the same path is
|
|
73
|
+
* imported again after a rebuild (different mtime) — e.g. test suites that
|
|
74
|
+
* rebuild a fixture to the same output path within one process — where the
|
|
75
|
+
* bare URL's cache entry would return the stale previous build. Note this
|
|
76
|
+
* rebuild branch trades the single-instance guarantee back: chunks that
|
|
77
|
+
* import the entry by bare path still resolve to the FIRST build's cache
|
|
78
|
+
* entry, so freshness and single-instance only hold together on the first
|
|
79
|
+
* import of a path. Production processes import each entry path exactly
|
|
80
|
+
* once and always get both.
|
|
81
|
+
*
|
|
82
|
+
* The entry is imported via its canonical real path: the bundler
|
|
83
|
+
* canonicalizes module ids with fs.realpathSync.native, so chunks evaluate
|
|
84
|
+
* under realpath-based URLs and their relative imports resolve to realpath
|
|
85
|
+
* URLs too. Importing the entry through a symlinked path (macOS /var/...
|
|
86
|
+
* tmpdirs, symlinked deploy directories) would otherwise create a second
|
|
87
|
+
* instance keyed on the symlinked URL.
|
|
88
|
+
*
|
|
89
|
+
* Exported for direct unit testing of the URL choice.
|
|
90
|
+
*/
|
|
91
|
+
function resolveServerEntryImportUrl(entryPath) {
|
|
92
|
+
let canonicalEntryPath;
|
|
93
|
+
try {
|
|
94
|
+
canonicalEntryPath = fs.realpathSync.native(entryPath);
|
|
95
|
+
} catch {
|
|
96
|
+
canonicalEntryPath = entryPath;
|
|
97
|
+
}
|
|
98
|
+
const href = pathToFileURL(canonicalEntryPath).href;
|
|
99
|
+
const mtime = fs.statSync(canonicalEntryPath).mtimeMs;
|
|
100
|
+
const bareMtime = bareServerEntryMtimes.get(href);
|
|
101
|
+
if (bareMtime === void 0 || bareMtime === mtime) {
|
|
102
|
+
bareServerEntryMtimes.set(href, mtime);
|
|
103
|
+
return href;
|
|
104
|
+
}
|
|
105
|
+
return `${href}?t=${mtime}`;
|
|
106
|
+
}
|
|
107
|
+
async function importServerEntryModule(entryPath) {
|
|
108
|
+
return import(resolveServerEntryImportUrl(entryPath));
|
|
109
|
+
}
|
|
50
110
|
/** Convert a Node.js IncomingMessage into a ReadableStream for Web Request body. */
|
|
51
111
|
function readNodeStream(req) {
|
|
52
112
|
return new ReadableStream({ start(controller) {
|
|
@@ -157,12 +217,14 @@ const NO_BODY_RESPONSE_STATUSES = new Set([
|
|
|
157
217
|
205,
|
|
158
218
|
304
|
|
159
219
|
]);
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
220
|
+
const OMIT_BODY_HEADERS = new Set(["content-length", "content-type"]);
|
|
221
|
+
const OMIT_STATIC_RESPONSE_HEADERS = new Set([
|
|
222
|
+
VINEXT_STATIC_FILE_HEADER,
|
|
223
|
+
"content-encoding",
|
|
224
|
+
"content-length",
|
|
225
|
+
"content-type"
|
|
226
|
+
]);
|
|
227
|
+
function omitHeadersCaseInsensitive(headersRecord, targets) {
|
|
166
228
|
const filtered = {};
|
|
167
229
|
for (const [key, value] of Object.entries(headersRecord)) {
|
|
168
230
|
if (targets.has(key.toLowerCase())) continue;
|
|
@@ -175,9 +237,14 @@ function matchesIfNoneMatchHeader(ifNoneMatch, etag) {
|
|
|
175
237
|
if (ifNoneMatch === "*") return true;
|
|
176
238
|
return ifNoneMatch.split(",").map((value) => value.trim()).some((value) => value === etag);
|
|
177
239
|
}
|
|
178
|
-
function
|
|
179
|
-
const
|
|
180
|
-
|
|
240
|
+
function installClientBuildManifestGlobals(clientDir, assetBase, assetPrefix) {
|
|
241
|
+
const metadata = computeClientRuntimeMetadata({
|
|
242
|
+
clientDir,
|
|
243
|
+
assetBase,
|
|
244
|
+
assetPrefix
|
|
245
|
+
});
|
|
246
|
+
globalThis.__VINEXT_LAZY_CHUNKS__ = metadata.lazyChunks;
|
|
247
|
+
globalThis.__VINEXT_DYNAMIC_PRELOADS__ = metadata.dynamicPreloads;
|
|
181
248
|
}
|
|
182
249
|
function isNoBodyResponseStatus(status) {
|
|
183
250
|
return NO_BODY_RESPONSE_STATUSES.has(status);
|
|
@@ -201,36 +268,15 @@ function logProdServerStarted(host, port, purpose) {
|
|
|
201
268
|
/**
|
|
202
269
|
* Merge middleware/config headers and an optional status override into a new
|
|
203
270
|
* Web Response while preserving the original body stream when allowed.
|
|
204
|
-
*
|
|
205
|
-
*
|
|
271
|
+
*
|
|
272
|
+
* This is the canonical {@link mergeHeaders} (server/worker-utils.ts) with the
|
|
273
|
+
* arguments in (headers, response) order. The request path now calls
|
|
274
|
+
* `runPagesRequest`, which uses `mergeHeaders` directly; this wrapper is retained
|
|
275
|
+
* only for its existing tests and any external callers, so there is a single
|
|
276
|
+
* implementation to keep in sync. (deploy.ts still emits its own generated copy.)
|
|
206
277
|
*/
|
|
207
278
|
function mergeWebResponse(middlewareHeaders, response, statusOverride) {
|
|
208
|
-
|
|
209
|
-
const status = statusOverride ?? response.status;
|
|
210
|
-
const mergedHeaders = mergeResponseHeaders(filteredMiddlewareHeaders, response);
|
|
211
|
-
const shouldDropBody = isNoBodyResponseStatus(status);
|
|
212
|
-
const shouldStripStreamLength = isVinextStreamedHtmlResponse(response) && hasHeader(mergedHeaders, "content-length");
|
|
213
|
-
if (!Object.keys(filteredMiddlewareHeaders).length && statusOverride === void 0 && !shouldDropBody && !shouldStripStreamLength) return response;
|
|
214
|
-
if (shouldDropBody) {
|
|
215
|
-
cancelResponseBody(response);
|
|
216
|
-
stripHeaders(mergedHeaders, [
|
|
217
|
-
"content-encoding",
|
|
218
|
-
"content-length",
|
|
219
|
-
"content-type",
|
|
220
|
-
"transfer-encoding"
|
|
221
|
-
]);
|
|
222
|
-
return new Response(null, {
|
|
223
|
-
status,
|
|
224
|
-
statusText: status === response.status ? response.statusText : void 0,
|
|
225
|
-
headers: toWebHeaders(mergedHeaders)
|
|
226
|
-
});
|
|
227
|
-
}
|
|
228
|
-
if (shouldStripStreamLength) stripHeaders(mergedHeaders, ["content-length"]);
|
|
229
|
-
return new Response(response.body, {
|
|
230
|
-
status,
|
|
231
|
-
statusText: status === response.status ? response.statusText : void 0,
|
|
232
|
-
headers: toWebHeaders(mergedHeaders)
|
|
233
|
-
});
|
|
279
|
+
return mergeHeaders(response, middlewareHeaders, statusOverride);
|
|
234
280
|
}
|
|
235
281
|
/**
|
|
236
282
|
* Send a compressed response if the content type is compressible and the
|
|
@@ -240,7 +286,7 @@ function sendCompressed(req, res, body, contentType, statusCode, extraHeaders =
|
|
|
240
286
|
const buf = typeof body === "string" ? Buffer.from(body) : body;
|
|
241
287
|
const baseType = contentType.split(";")[0].trim();
|
|
242
288
|
const encoding = compress ? negotiateEncoding(req) : null;
|
|
243
|
-
const headersWithoutBodyHeaders = omitHeadersCaseInsensitive(extraHeaders,
|
|
289
|
+
const headersWithoutBodyHeaders = omitHeadersCaseInsensitive(extraHeaders, OMIT_BODY_HEADERS);
|
|
244
290
|
const writeHead = (headers) => {
|
|
245
291
|
if (statusText) res.writeHead(statusCode, statusText, headers);
|
|
246
292
|
else res.writeHead(statusCode, headers);
|
|
@@ -624,6 +670,40 @@ function resolveAppRouterAssetPath(pathname, assetPathPrefix, assetPrefix) {
|
|
|
624
670
|
if (pathname.startsWith(nextStaticDir)) return pathname;
|
|
625
671
|
return null;
|
|
626
672
|
}
|
|
673
|
+
function isSsrManifest(value) {
|
|
674
|
+
if (!isUnknownRecord(value)) return false;
|
|
675
|
+
return Object.values(value).every((files) => Array.isArray(files) && files.every((file) => typeof file === "string"));
|
|
676
|
+
}
|
|
677
|
+
function readSsrManifest(clientDir) {
|
|
678
|
+
const manifestPath = path.join(clientDir, ".vite", "ssr-manifest.json");
|
|
679
|
+
if (!fs.existsSync(manifestPath)) return {};
|
|
680
|
+
let parsed;
|
|
681
|
+
try {
|
|
682
|
+
parsed = JSON.parse(fs.readFileSync(manifestPath, "utf-8"));
|
|
683
|
+
} catch (error) {
|
|
684
|
+
console.warn(`[vinext] Ignoring unparseable SSR manifest at ${manifestPath}:`, error);
|
|
685
|
+
return {};
|
|
686
|
+
}
|
|
687
|
+
if (!isSsrManifest(parsed)) {
|
|
688
|
+
console.warn(`[vinext] Ignoring SSR manifest with unexpected shape at ${manifestPath}`);
|
|
689
|
+
return {};
|
|
690
|
+
}
|
|
691
|
+
return parsed;
|
|
692
|
+
}
|
|
693
|
+
function installPagesClientAssetGlobals(options) {
|
|
694
|
+
const ssrManifest = readSsrManifest(options.clientDir);
|
|
695
|
+
globalThis.__VINEXT_SSR_MANIFEST__ = Object.keys(ssrManifest).length > 0 ? ssrManifest : void 0;
|
|
696
|
+
const metadata = computeClientRuntimeMetadata({
|
|
697
|
+
clientDir: options.clientDir,
|
|
698
|
+
assetBase: options.assetBase,
|
|
699
|
+
assetPrefix: options.assetPrefix,
|
|
700
|
+
includeClientEntry: options.clientEntryLookup === "pages-client-entry" ? "pages-client-entry" : true
|
|
701
|
+
});
|
|
702
|
+
globalThis.__VINEXT_CLIENT_ENTRY__ = metadata.clientEntryFile;
|
|
703
|
+
globalThis.__VINEXT_LAZY_CHUNKS__ = metadata.lazyChunks;
|
|
704
|
+
globalThis.__VINEXT_DYNAMIC_PRELOADS__ = metadata.dynamicPreloads;
|
|
705
|
+
return ssrManifest;
|
|
706
|
+
}
|
|
627
707
|
/**
|
|
628
708
|
* Start the App Router production server.
|
|
629
709
|
*
|
|
@@ -649,13 +729,22 @@ async function startAppRouterServer(options) {
|
|
|
649
729
|
imageConfig = JSON.parse(fs.readFileSync(imageConfigPath, "utf-8"));
|
|
650
730
|
} catch {}
|
|
651
731
|
const prerenderSecret = readPrerenderSecret(path.dirname(rscEntryPath));
|
|
652
|
-
const
|
|
653
|
-
const rscModule = await import(`${pathToFileURL(rscEntryPath).href}?t=${rscMtime}`);
|
|
732
|
+
const rscModule = await importServerEntryModule(rscEntryPath);
|
|
654
733
|
const rscHandler = resolveAppRouterHandler(rscModule.default);
|
|
655
734
|
const appRouterAssetPrefix = typeof rscModule.__assetPrefix === "string" ? rscModule.__assetPrefix : "";
|
|
735
|
+
const appRouterBasePath = typeof rscModule.__basePath === "string" ? rscModule.__basePath : "";
|
|
656
736
|
const appRouterInlineCss = rscModule.__inlineCss === true;
|
|
737
|
+
const appRouterHasPagesDir = rscModule.__hasPagesDir === true;
|
|
657
738
|
globalThis.__VINEXT_INLINE_CSS__ = appRouterInlineCss ? collectInlineCssManifest(clientDir, appRouterAssetPrefix) : void 0;
|
|
658
739
|
const appAssetPathPrefix = assetPrefixPathname(appRouterAssetPrefix);
|
|
740
|
+
const appAssetBase = appRouterBasePath ? `${appRouterBasePath}/` : "/";
|
|
741
|
+
if (appRouterHasPagesDir) installPagesClientAssetGlobals({
|
|
742
|
+
clientDir,
|
|
743
|
+
assetPrefix: appRouterAssetPrefix,
|
|
744
|
+
assetBase: appAssetBase,
|
|
745
|
+
clientEntryLookup: "pages-client-entry"
|
|
746
|
+
});
|
|
747
|
+
else installClientBuildManifestGlobals(clientDir, appAssetBase, appRouterAssetPrefix);
|
|
659
748
|
const seededRoutes = await resolveAppRouterPrerenderSeeder(rscModule)(path.dirname(rscEntryPath));
|
|
660
749
|
if (seededRoutes > 0) console.log(`[vinext] Seeded ${seededRoutes} pre-rendered route${seededRoutes !== 1 ? "s" : ""} into memory cache`);
|
|
661
750
|
const staticCache = await StaticFileCache.create(clientDir);
|
|
@@ -726,12 +815,7 @@ async function startAppRouterServer(options) {
|
|
|
726
815
|
} catch {
|
|
727
816
|
staticFilePath = staticFileSignal;
|
|
728
817
|
}
|
|
729
|
-
const staticResponseHeaders = omitHeadersCaseInsensitive(mergeResponseHeaders({}, response),
|
|
730
|
-
VINEXT_STATIC_FILE_HEADER,
|
|
731
|
-
"content-encoding",
|
|
732
|
-
"content-length",
|
|
733
|
-
"content-type"
|
|
734
|
-
]);
|
|
818
|
+
const staticResponseHeaders = omitHeadersCaseInsensitive(mergeResponseHeaders({}, response), OMIT_STATIC_RESPONSE_HEADERS);
|
|
735
819
|
const served = await tryServeStatic(req, res, clientDir, staticFilePath, compress, staticCache, staticResponseHeaders, response.status);
|
|
736
820
|
cancelResponseBody(response);
|
|
737
821
|
if (served) return;
|
|
@@ -785,8 +869,7 @@ function readPagesServerEntryPageRoutes(value) {
|
|
|
785
869
|
*/
|
|
786
870
|
async function startPagesRouterServer(options) {
|
|
787
871
|
const { port, host, clientDir, serverEntryPath, compress, purpose } = options;
|
|
788
|
-
const
|
|
789
|
-
const serverEntry = await import(`${pathToFileURL(serverEntryPath).href}?t=${serverMtime}`);
|
|
872
|
+
const serverEntry = await importServerEntryModule(serverEntryPath);
|
|
790
873
|
const { renderPage, handleApiRoute: handleApi, runMiddleware, vinextConfig, buildId: pagesBuildId } = serverEntry;
|
|
791
874
|
const matchPageRoute = typeof serverEntry.matchPageRoute === "function" ? serverEntry.matchPageRoute : void 0;
|
|
792
875
|
const pageRoutes = readPagesServerEntryPageRoutes(serverEntry.pageRoutes);
|
|
@@ -811,20 +894,12 @@ async function startPagesRouterServer(options) {
|
|
|
811
894
|
contentDispositionType: vinextConfig.images.contentDispositionType,
|
|
812
895
|
contentSecurityPolicy: vinextConfig.images.contentSecurityPolicy
|
|
813
896
|
} : void 0;
|
|
814
|
-
|
|
815
|
-
const manifestPath = path.join(clientDir, ".vite", "ssr-manifest.json");
|
|
816
|
-
if (fs.existsSync(manifestPath)) ssrManifest = JSON.parse(fs.readFileSync(manifestPath, "utf-8"));
|
|
817
|
-
const buildManifest = readClientBuildManifest(path.join(clientDir, ".vite", "manifest.json"));
|
|
818
|
-
globalThis.__VINEXT_CLIENT_ENTRY__ = findClientEntryFile({
|
|
819
|
-
buildManifest,
|
|
897
|
+
const ssrManifest = installPagesClientAssetGlobals({
|
|
820
898
|
clientDir,
|
|
821
|
-
|
|
822
|
-
assetBase
|
|
899
|
+
assetPrefix,
|
|
900
|
+
assetBase,
|
|
901
|
+
clientEntryLookup: "any-client-entry"
|
|
823
902
|
});
|
|
824
|
-
if (buildManifest) {
|
|
825
|
-
const lazyChunks = computeLazyChunks(buildManifest).map((file) => manifestFileWithBase(file, assetBase));
|
|
826
|
-
globalThis.__VINEXT_LAZY_CHUNKS__ = lazyChunks.length > 0 ? lazyChunks : void 0;
|
|
827
|
-
} else globalThis.__VINEXT_LAZY_CHUNKS__ = void 0;
|
|
828
903
|
const staticCache = await StaticFileCache.create(clientDir);
|
|
829
904
|
const handleRequest = async (req, res) => {
|
|
830
905
|
const rawUrl = req.url ?? "/";
|
|
@@ -915,20 +990,6 @@ async function startPagesRouterServer(options) {
|
|
|
915
990
|
pathname = stripped;
|
|
916
991
|
}
|
|
917
992
|
}
|
|
918
|
-
const basePathState = {
|
|
919
|
-
basePath,
|
|
920
|
-
hadBasePath
|
|
921
|
-
};
|
|
922
|
-
{
|
|
923
|
-
const qs = url.includes("?") ? url.slice(url.indexOf("?")) : "";
|
|
924
|
-
const trailingSlashRedirect = normalizeTrailingSlash(pathname, basePath, trailingSlash, qs);
|
|
925
|
-
if (trailingSlashRedirect) {
|
|
926
|
-
const location = trailingSlashRedirect.headers.get("Location");
|
|
927
|
-
res.writeHead(trailingSlashRedirect.status, location ? { Location: location } : void 0);
|
|
928
|
-
res.end();
|
|
929
|
-
return;
|
|
930
|
-
}
|
|
931
|
-
}
|
|
932
993
|
let isDataReq = false;
|
|
933
994
|
if (isNextDataPathname(pathname)) {
|
|
934
995
|
const dataMatch = pagesBuildId ? parseNextDataPathname(pathname, pagesBuildId) : null;
|
|
@@ -948,167 +1009,54 @@ async function startPagesRouterServer(options) {
|
|
|
948
1009
|
const reqHeaders = filterInternalHeaders(rawReqHeaders);
|
|
949
1010
|
const method = req.method ?? "GET";
|
|
950
1011
|
const hasBody = method !== "GET" && method !== "HEAD";
|
|
951
|
-
|
|
1012
|
+
const result = await runPagesRequest(new Request(`${protocol}://${hostHeader}${url}`, {
|
|
952
1013
|
method,
|
|
953
1014
|
headers: reqHeaders,
|
|
954
1015
|
body: hasBody ? readNodeStream(req) : void 0,
|
|
955
1016
|
duplex: hasBody ? "half" : void 0
|
|
956
|
-
})
|
|
957
|
-
|
|
958
|
-
|
|
959
|
-
|
|
960
|
-
|
|
961
|
-
|
|
962
|
-
if (redirect) {
|
|
963
|
-
const dest = sanitizeDestination(basePath && hadBasePath && !isExternalUrl(redirect.destination) && !hasBasePath(redirect.destination, basePath) ? basePath + redirect.destination : redirect.destination);
|
|
964
|
-
res.writeHead(redirect.permanent ? 308 : 307, { Location: dest });
|
|
965
|
-
res.end();
|
|
966
|
-
return;
|
|
967
|
-
}
|
|
968
|
-
}
|
|
969
|
-
let resolvedUrl = url;
|
|
970
|
-
const middlewareHeaders = {};
|
|
971
|
-
let middlewareStatus;
|
|
972
|
-
if (typeof runMiddleware === "function") {
|
|
973
|
-
const result = await runMiddleware(webRequest, void 0, { isDataRequest });
|
|
974
|
-
if (result.waitUntilPromises && result.waitUntilPromises.length > 0) Promise.allSettled(result.waitUntilPromises);
|
|
975
|
-
if (!result.continue) {
|
|
976
|
-
if (result.redirectUrl) {
|
|
977
|
-
const redirectHeaders = { Location: result.redirectUrl };
|
|
978
|
-
if (result.responseHeaders) for (const [key, value] of result.responseHeaders) {
|
|
979
|
-
const existing = redirectHeaders[key];
|
|
980
|
-
if (existing === void 0) redirectHeaders[key] = value;
|
|
981
|
-
else if (Array.isArray(existing)) existing.push(value);
|
|
982
|
-
else redirectHeaders[key] = [existing, value];
|
|
983
|
-
}
|
|
984
|
-
res.writeHead(result.redirectStatus ?? 307, redirectHeaders);
|
|
985
|
-
res.end();
|
|
986
|
-
return;
|
|
987
|
-
}
|
|
988
|
-
if (result.response) {
|
|
989
|
-
const body = Buffer.from(await result.response.arrayBuffer());
|
|
990
|
-
const respHeaders = {};
|
|
991
|
-
result.response.headers.forEach((value, key) => {
|
|
992
|
-
if (key === "set-cookie") return;
|
|
993
|
-
respHeaders[key] = value;
|
|
994
|
-
});
|
|
995
|
-
const setCookies = result.response.headers.getSetCookie?.() ?? [];
|
|
996
|
-
if (setCookies.length > 0) respHeaders["set-cookie"] = setCookies;
|
|
997
|
-
if (result.response.statusText) res.writeHead(result.response.status, result.response.statusText, respHeaders);
|
|
998
|
-
else res.writeHead(result.response.status, respHeaders);
|
|
999
|
-
res.end(body);
|
|
1000
|
-
return;
|
|
1001
|
-
}
|
|
1002
|
-
}
|
|
1003
|
-
if (result.responseHeaders) for (const [key, value] of result.responseHeaders) if (key === "set-cookie") {
|
|
1004
|
-
const existing = middlewareHeaders[key];
|
|
1005
|
-
if (Array.isArray(existing)) existing.push(value);
|
|
1006
|
-
else if (existing) middlewareHeaders[key] = [existing, value];
|
|
1007
|
-
else middlewareHeaders[key] = [value];
|
|
1008
|
-
} else middlewareHeaders[key] = value;
|
|
1009
|
-
if (result.rewriteUrl) resolvedUrl = result.rewriteUrl;
|
|
1010
|
-
middlewareStatus = result.status ?? result.rewriteStatus;
|
|
1011
|
-
}
|
|
1012
|
-
const { postMwReqCtx, request: postMwReq } = applyMiddlewareRequestHeaders(middlewareHeaders, webRequest, { preserveCredentialHeaders: isExternalUrl(resolvedUrl) });
|
|
1013
|
-
webRequest = postMwReq;
|
|
1014
|
-
let resolvedPathname = resolvedUrl.split("?")[0];
|
|
1015
|
-
const matchResolvedPathname = (p) => i18nConfig ? normalizeDefaultLocalePathname(p, i18nConfig, { hostname: requestHostname }) : p;
|
|
1016
|
-
if (configHeaders.length) applyConfigHeadersToHeaderRecord(middlewareHeaders, {
|
|
1017
|
+
}), {
|
|
1018
|
+
basePath,
|
|
1019
|
+
trailingSlash,
|
|
1020
|
+
i18nConfig,
|
|
1021
|
+
configRedirects,
|
|
1022
|
+
configRewrites,
|
|
1017
1023
|
configHeaders,
|
|
1018
|
-
|
|
1019
|
-
|
|
1020
|
-
|
|
1021
|
-
|
|
1022
|
-
|
|
1023
|
-
|
|
1024
|
-
|
|
1025
|
-
|
|
1026
|
-
|
|
1027
|
-
|
|
1028
|
-
|
|
1029
|
-
|
|
1030
|
-
if (rewritten) {
|
|
1031
|
-
if (isExternalUrl(rewritten)) {
|
|
1032
|
-
await sendWebResponse(await proxyExternalRequest(webRequest, rewritten), req, res, compress);
|
|
1033
|
-
return;
|
|
1034
|
-
}
|
|
1035
|
-
resolvedUrl = mergeRewriteQuery(resolvedUrl, rewritten);
|
|
1036
|
-
resolvedPathname = resolvedUrl.split("?")[0];
|
|
1037
|
-
configRewriteFired = true;
|
|
1024
|
+
hadBasePath,
|
|
1025
|
+
isDataReq,
|
|
1026
|
+
isDataRequest,
|
|
1027
|
+
ctx: void 0,
|
|
1028
|
+
rawSearch: rawQs,
|
|
1029
|
+
matchPageRoute: matchPageRoute ?? null,
|
|
1030
|
+
runMiddleware: typeof runMiddleware === "function" ? wrapMiddlewareWithBasePath(runMiddleware, basePath, hadBasePath) : null,
|
|
1031
|
+
renderPage: typeof renderPage === "function" ? (request, resolvedUrl, options, stagedHeaders) => renderPage(request, resolvedUrl, ssrManifest, void 0, stagedHeaders, options) : null,
|
|
1032
|
+
handleApi: typeof handleApi === "function" ? (request, apiUrl) => handleApi(request, apiUrl, createNodeExecutionContext()) : null,
|
|
1033
|
+
serveStaticFile: async (requestPathname, stagedHeaders) => {
|
|
1034
|
+
if (requestPathname === "/" || requestPathname.startsWith("/api/") || requestPathname.startsWith(`/_next/static/`)) return false;
|
|
1035
|
+
return tryServeStatic(req, res, clientDir, requestPathname, compress, staticCache, stagedHeaders);
|
|
1038
1036
|
}
|
|
1039
|
-
}
|
|
1040
|
-
if (
|
|
1041
|
-
|
|
1042
|
-
|
|
1043
|
-
|
|
1044
|
-
|
|
1045
|
-
const apiLookupUrl = stripI18nLocaleForApiRoute(resolvedUrl, vinextConfig?.i18n ?? null);
|
|
1046
|
-
const apiLookupPathname = apiLookupUrl.split("?")[0];
|
|
1047
|
-
if (apiLookupPathname.startsWith("/api/") || apiLookupPathname === "/api") {
|
|
1048
|
-
let response;
|
|
1049
|
-
if (typeof handleApi === "function") response = await handleApi(webRequest, apiLookupUrl, createNodeExecutionContext());
|
|
1050
|
-
else response = new Response("404 - API route not found", { status: 404 });
|
|
1051
|
-
const mergedResponse = mergeWebResponse(middlewareHeaders, response, middlewareStatus);
|
|
1052
|
-
if (!mergedResponse.body) {
|
|
1053
|
-
await sendWebResponse(mergedResponse, req, res, compress);
|
|
1037
|
+
});
|
|
1038
|
+
if (result.type === "handled") return;
|
|
1039
|
+
if (result.type === "response") {
|
|
1040
|
+
const { response } = result;
|
|
1041
|
+
if (isVinextStreamedHtmlResponse(response) || !response.body || result.defaultContentType === void 0) {
|
|
1042
|
+
await sendWebResponse(response, req, res, compress);
|
|
1054
1043
|
return;
|
|
1055
1044
|
}
|
|
1056
|
-
const responseBody = Buffer.from(await
|
|
1057
|
-
const ct =
|
|
1058
|
-
const responseHeaders =
|
|
1059
|
-
|
|
1060
|
-
|
|
1061
|
-
|
|
1062
|
-
|
|
1063
|
-
|
|
1064
|
-
|
|
1065
|
-
const
|
|
1066
|
-
|
|
1067
|
-
if (isExternalUrl(rewritten)) {
|
|
1068
|
-
await sendWebResponse(await proxyExternalRequest(webRequest, rewritten), req, res, compress);
|
|
1069
|
-
return;
|
|
1070
|
-
}
|
|
1071
|
-
resolvedUrl = mergeRewriteQuery(resolvedUrl, rewritten);
|
|
1072
|
-
resolvedPathname = resolvedUrl.split("?")[0];
|
|
1073
|
-
}
|
|
1074
|
-
}
|
|
1075
|
-
let response;
|
|
1076
|
-
if (typeof renderPage === "function") {
|
|
1077
|
-
const middlewareResponseHeaders = toWebHeaders(middlewareHeaders);
|
|
1078
|
-
const renderPageMatch = matchPageRoute ? matchPageRoute(resolvedPathname, webRequest) : null;
|
|
1079
|
-
const shouldDeferErrorPageOnMiss = !isDataReq && !!matchPageRoute && !renderPageMatch;
|
|
1080
|
-
const dataRenderOptions = isDataReq ? { isDataReq: true } : void 0;
|
|
1081
|
-
response = await renderPage(webRequest, resolvedUrl, ssrManifest, void 0, middlewareResponseHeaders, shouldDeferErrorPageOnMiss ? { renderErrorPageOnMiss: false } : dataRenderOptions);
|
|
1082
|
-
let matchedFallbackRewrite = false;
|
|
1083
|
-
if (response && response.status === 404 && shouldDeferErrorPageOnMiss && configRewrites.fallback?.length) {
|
|
1084
|
-
const fallbackRewrite = matchRewrite(matchResolvedPathname(resolvedPathname), configRewrites.fallback, postMwReqCtx, basePathState);
|
|
1085
|
-
if (fallbackRewrite) {
|
|
1086
|
-
if (isExternalUrl(fallbackRewrite)) {
|
|
1087
|
-
await sendWebResponse(await proxyExternalRequest(webRequest, fallbackRewrite), req, res, compress);
|
|
1088
|
-
return;
|
|
1089
|
-
}
|
|
1090
|
-
matchedFallbackRewrite = true;
|
|
1091
|
-
response = await renderPage(webRequest, mergeRewriteQuery(resolvedUrl, fallbackRewrite), ssrManifest, void 0, middlewareResponseHeaders, dataRenderOptions);
|
|
1092
|
-
}
|
|
1093
|
-
}
|
|
1094
|
-
if (response && response.status === 404 && shouldDeferErrorPageOnMiss && !matchedFallbackRewrite) response = await renderPage(webRequest, resolvedUrl, ssrManifest, void 0, middlewareResponseHeaders);
|
|
1095
|
-
}
|
|
1096
|
-
if (!response) {
|
|
1097
|
-
res.writeHead(404);
|
|
1098
|
-
res.end("This page could not be found");
|
|
1099
|
-
return;
|
|
1100
|
-
}
|
|
1101
|
-
const shouldStreamPagesResponse = isVinextStreamedHtmlResponse(response);
|
|
1102
|
-
const mergedResponse = mergeWebResponse(middlewareHeaders, response, middlewareStatus);
|
|
1103
|
-
if (shouldStreamPagesResponse || !mergedResponse.body) {
|
|
1104
|
-
await sendWebResponse(mergedResponse, req, res, compress);
|
|
1045
|
+
const responseBody = Buffer.from(await response.arrayBuffer());
|
|
1046
|
+
const ct = response.headers.get("content-type") ?? result.defaultContentType;
|
|
1047
|
+
const responseHeaders = {};
|
|
1048
|
+
response.headers.forEach((v, k) => {
|
|
1049
|
+
if (k === "set-cookie") return;
|
|
1050
|
+
responseHeaders[k] = v;
|
|
1051
|
+
});
|
|
1052
|
+
const setCookies = response.headers.getSetCookie?.() ?? [];
|
|
1053
|
+
if (setCookies.length > 0) responseHeaders["set-cookie"] = setCookies;
|
|
1054
|
+
const finalStatusText = response.statusText || void 0;
|
|
1055
|
+
sendCompressed(req, res, responseBody, ct, response.status, responseHeaders, compress, finalStatusText);
|
|
1105
1056
|
return;
|
|
1106
1057
|
}
|
|
1107
|
-
|
|
1108
|
-
|
|
1109
|
-
const responseHeaders = mergeResponseHeaders({}, mergedResponse);
|
|
1110
|
-
const finalStatusText = mergedResponse.statusText || void 0;
|
|
1111
|
-
sendCompressed(req, res, responseBody, ct, mergedResponse.status, responseHeaders, compress, finalStatusText);
|
|
1058
|
+
res.writeHead(404);
|
|
1059
|
+
res.end("This page could not be found");
|
|
1112
1060
|
} catch (e) {
|
|
1113
1061
|
console.error("[vinext] Server error:", e);
|
|
1114
1062
|
if (!res.headersSent) {
|
|
@@ -1134,4 +1082,4 @@ async function startPagesRouterServer(options) {
|
|
|
1134
1082
|
};
|
|
1135
1083
|
}
|
|
1136
1084
|
//#endregion
|
|
1137
|
-
export { COMPRESSIBLE_TYPES, COMPRESS_THRESHOLD, mergeResponseHeaders, mergeWebResponse, negotiateEncoding, nodeToWebRequest, resolveAppRouterAssetPath, resolveAppRouterPrerenderSeeder, resolveRequestHost as resolveHost, sendCompressed, sendWebResponse, startProdServer, trustProxy, trustedHosts, tryServeStatic };
|
|
1085
|
+
export { COMPRESSIBLE_TYPES, COMPRESS_THRESHOLD, importServerEntryModule, mergeResponseHeaders, mergeWebResponse, negotiateEncoding, nodeToWebRequest, resolveAppRouterAssetPath, resolveAppRouterPrerenderSeeder, resolveRequestHost as resolveHost, resolveServerEntryImportUrl, sendCompressed, sendWebResponse, startProdServer, trustProxy, trustedHosts, tryServeStatic };
|
|
@@ -5,6 +5,24 @@
|
|
|
5
5
|
* Exported for unit testing in isolation (no process-state mutation).
|
|
6
6
|
*/
|
|
7
7
|
declare function peerDisconnectCode(err: unknown): string | undefined;
|
|
8
|
+
/**
|
|
9
|
+
* Pure predicate: returns `true` when `err` is a benign failure from a
|
|
10
|
+
* dynamic `import()` of a static asset URL — the "URL dependency" pattern
|
|
11
|
+
* that Next.js tolerates at build time. Two shapes are recognised:
|
|
12
|
+
*
|
|
13
|
+
* - `ERR_UNKNOWN_FILE_EXTENSION`: the asset resolved on disk but is not an
|
|
14
|
+
* ES module (e.g. a co-located `./style.css`). The error message ends in
|
|
15
|
+
* the offending extension in quotes: `... extension ".css" for /path`.
|
|
16
|
+
* - `ERR_MODULE_NOT_FOUND`: the asset URL did not resolve (the chunk lives
|
|
17
|
+
* in `dist/server/` but the source asset does not). Node attaches the
|
|
18
|
+
* unresolved specifier on `err.url`; we match only when it points at a
|
|
19
|
+
* static-asset extension.
|
|
20
|
+
*
|
|
21
|
+
* Anything outside this allow-list (including missing `.js`/`.mjs`/`.ts`
|
|
22
|
+
* modules with no extension) returns `false` so real bugs still crash.
|
|
23
|
+
* Exported for unit testing in isolation.
|
|
24
|
+
*/
|
|
25
|
+
declare function isBenignAssetImportError(err: unknown): boolean;
|
|
8
26
|
/**
|
|
9
27
|
* Test-only: returns whether the backstop has been installed in this
|
|
10
28
|
* process. Used by the unit test to assert idempotent install via the
|
|
@@ -13,4 +31,4 @@ declare function peerDisconnectCode(err: unknown): string | undefined;
|
|
|
13
31
|
declare function isSocketErrorBackstopInstalled(): boolean;
|
|
14
32
|
declare function installSocketErrorBackstop(): void;
|
|
15
33
|
//#endregion
|
|
16
|
-
export { installSocketErrorBackstop, isSocketErrorBackstopInstalled, peerDisconnectCode };
|
|
34
|
+
export { installSocketErrorBackstop, isBenignAssetImportError, isSocketErrorBackstopInstalled, peerDisconnectCode };
|