vinext 0.0.24 → 0.0.25
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 +24 -0
- package/dist/check.d.ts.map +1 -1
- package/dist/check.js +3 -2
- package/dist/check.js.map +1 -1
- package/dist/client/entry.js +1 -1
- package/dist/client/entry.js.map +1 -1
- package/dist/config/config-matchers.d.ts +21 -0
- package/dist/config/config-matchers.d.ts.map +1 -1
- package/dist/config/config-matchers.js +46 -6
- package/dist/config/config-matchers.js.map +1 -1
- package/dist/config/next-config.d.ts +8 -2
- package/dist/config/next-config.d.ts.map +1 -1
- package/dist/config/next-config.js +90 -35
- package/dist/config/next-config.js.map +1 -1
- package/dist/deploy.d.ts +10 -0
- package/dist/deploy.d.ts.map +1 -1
- package/dist/deploy.js +70 -35
- package/dist/deploy.js.map +1 -1
- package/dist/index.d.ts +3 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +172 -18
- package/dist/index.js.map +1 -1
- package/dist/plugins/async-hooks-stub.d.ts +16 -0
- package/dist/plugins/async-hooks-stub.d.ts.map +1 -0
- package/dist/plugins/async-hooks-stub.js +45 -0
- package/dist/plugins/async-hooks-stub.js.map +1 -0
- package/dist/routing/app-router.d.ts +12 -6
- package/dist/routing/app-router.d.ts.map +1 -1
- package/dist/routing/app-router.js +19 -40
- package/dist/routing/app-router.js.map +1 -1
- package/dist/routing/pages-router.d.ts.map +1 -1
- package/dist/routing/pages-router.js +3 -9
- package/dist/routing/pages-router.js.map +1 -1
- package/dist/routing/utils.d.ts +9 -0
- package/dist/routing/utils.d.ts.map +1 -1
- package/dist/routing/utils.js +10 -0
- package/dist/routing/utils.js.map +1 -1
- package/dist/server/api-handler.d.ts.map +1 -1
- package/dist/server/api-handler.js +6 -0
- package/dist/server/api-handler.js.map +1 -1
- package/dist/server/app-dev-server.d.ts +2 -2
- package/dist/server/app-dev-server.d.ts.map +1 -1
- package/dist/server/app-dev-server.js +238 -114
- package/dist/server/app-dev-server.js.map +1 -1
- package/dist/server/dev-module-runner.d.ts +84 -0
- package/dist/server/dev-module-runner.d.ts.map +1 -0
- package/dist/server/dev-module-runner.js +105 -0
- package/dist/server/dev-module-runner.js.map +1 -0
- package/dist/server/dev-server.js.map +1 -1
- package/dist/server/instrumentation.d.ts +52 -9
- package/dist/server/instrumentation.d.ts.map +1 -1
- package/dist/server/instrumentation.js +52 -15
- package/dist/server/instrumentation.js.map +1 -1
- package/dist/server/middleware.d.ts +7 -3
- package/dist/server/middleware.d.ts.map +1 -1
- package/dist/server/middleware.js +16 -6
- package/dist/server/middleware.js.map +1 -1
- package/dist/server/prod-server.d.ts.map +1 -1
- package/dist/server/prod-server.js +15 -25
- package/dist/server/prod-server.js.map +1 -1
- package/dist/shims/cache.d.ts.map +1 -1
- package/dist/shims/cache.js +14 -2
- package/dist/shims/cache.js.map +1 -1
- package/dist/shims/fetch-cache.d.ts.map +1 -1
- package/dist/shims/fetch-cache.js +139 -29
- package/dist/shims/fetch-cache.js.map +1 -1
- package/dist/shims/form.d.ts.map +1 -1
- package/dist/shims/form.js +2 -3
- package/dist/shims/form.js.map +1 -1
- package/dist/shims/layout-segment-context.d.ts +5 -4
- package/dist/shims/layout-segment-context.d.ts.map +1 -1
- package/dist/shims/layout-segment-context.js +6 -5
- package/dist/shims/layout-segment-context.js.map +1 -1
- package/dist/shims/link.d.ts.map +1 -1
- package/dist/shims/link.js +32 -17
- package/dist/shims/link.js.map +1 -1
- package/dist/shims/navigation.d.ts +14 -11
- package/dist/shims/navigation.d.ts.map +1 -1
- package/dist/shims/navigation.js +122 -102
- package/dist/shims/navigation.js.map +1 -1
- package/dist/shims/router.d.ts.map +1 -1
- package/dist/shims/router.js +37 -21
- package/dist/shims/router.js.map +1 -1
- package/dist/shims/server.d.ts +2 -0
- package/dist/shims/server.d.ts.map +1 -1
- package/dist/shims/server.js +4 -0
- package/dist/shims/server.js.map +1 -1
- package/dist/shims/url-utils.d.ts +13 -0
- package/dist/shims/url-utils.d.ts.map +1 -0
- package/dist/shims/url-utils.js +28 -0
- package/dist/shims/url-utils.js.map +1 -0
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -4,6 +4,7 @@ import { appRouter, invalidateAppRouteCache } from "./routing/app-router.js";
|
|
|
4
4
|
import { createValidFileMatcher } from "./routing/file-matcher.js";
|
|
5
5
|
import { createSSRHandler } from "./server/dev-server.js";
|
|
6
6
|
import { handleApiRoute } from "./server/api-handler.js";
|
|
7
|
+
import { createDirectRunner } from "./server/dev-module-runner.js";
|
|
7
8
|
import { generateRscEntry, generateSsrEntry, generateBrowserEntry, } from "./server/app-dev-server.js";
|
|
8
9
|
import { loadNextConfig, resolveNextConfig, } from "./config/next-config.js";
|
|
9
10
|
import { findMiddlewareFile, isProxyFile, runMiddleware } from "./server/middleware.js";
|
|
@@ -16,6 +17,7 @@ import { validateDevRequest } from "./server/dev-origin-check.js";
|
|
|
16
17
|
import { safeRegExp, isExternalUrl, proxyExternalRequest, parseCookies, matchHeaders, matchRedirect, matchRewrite, } from "./config/config-matchers.js";
|
|
17
18
|
import { scanMetadataFiles } from "./server/metadata-routes.js";
|
|
18
19
|
import { detectPackageManager } from "./utils/project.js";
|
|
20
|
+
import { asyncHooksStubPlugin } from "./plugins/async-hooks-stub.js";
|
|
19
21
|
import tsconfigPaths from "vite-tsconfig-paths";
|
|
20
22
|
import react from "@vitejs/plugin-react";
|
|
21
23
|
import MagicString from "magic-string";
|
|
@@ -567,10 +569,35 @@ export default function vinext(options = {}) {
|
|
|
567
569
|
contentSecurityPolicy: nextConfig?.images?.contentSecurityPolicy,
|
|
568
570
|
},
|
|
569
571
|
});
|
|
572
|
+
// Generate instrumentation code if instrumentation.ts exists.
|
|
573
|
+
// For production (Cloudflare Workers), instrumentation.ts is bundled into the
|
|
574
|
+
// Worker and register() is called as a top-level await at module evaluation time —
|
|
575
|
+
// before any request is handled. This mirrors App Router behavior (generateRscEntry)
|
|
576
|
+
// and matches Next.js semantics: register() runs once on startup in the process
|
|
577
|
+
// that handles requests.
|
|
578
|
+
//
|
|
579
|
+
// The onRequestError handler is stored on globalThis so it is visible across
|
|
580
|
+
// all code within the Worker (same global scope).
|
|
581
|
+
const instrumentationImportCode = instrumentationPath
|
|
582
|
+
? `import * as _instrumentation from ${JSON.stringify(instrumentationPath.replace(/\\/g, "/"))};`
|
|
583
|
+
: "";
|
|
584
|
+
const instrumentationInitCode = instrumentationPath
|
|
585
|
+
? `// Run instrumentation register() once at module evaluation time — before any
|
|
586
|
+
// requests are handled. Matches Next.js semantics: register() is called once
|
|
587
|
+
// on startup in the process that handles requests.
|
|
588
|
+
if (typeof _instrumentation.register === "function") {
|
|
589
|
+
await _instrumentation.register();
|
|
590
|
+
}
|
|
591
|
+
// Store the onRequestError handler on globalThis so it is visible to all
|
|
592
|
+
// code within the Worker (same global scope).
|
|
593
|
+
if (typeof _instrumentation.onRequestError === "function") {
|
|
594
|
+
globalThis.__VINEXT_onRequestErrorHandler__ = _instrumentation.onRequestError;
|
|
595
|
+
}`
|
|
596
|
+
: "";
|
|
570
597
|
// Generate middleware code if middleware.ts exists
|
|
571
598
|
const middlewareImportCode = middlewarePath
|
|
572
599
|
? `import * as middlewareModule from ${JSON.stringify(middlewarePath.replace(/\\/g, "/"))};
|
|
573
|
-
import { NextRequest } from "next/server";`
|
|
600
|
+
import { NextRequest, NextFetchEvent } from "next/server";`
|
|
574
601
|
: "";
|
|
575
602
|
// The matcher config is read from the middleware module at import time.
|
|
576
603
|
// We inline the matching + execution logic so the prod server can call it.
|
|
@@ -581,7 +608,7 @@ ${generateNormalizePathCode("es5")}
|
|
|
581
608
|
${generateSafeRegExpCode("es5")}
|
|
582
609
|
${generateMiddlewareMatcherCode("es5")}
|
|
583
610
|
|
|
584
|
-
export async function runMiddleware(request) {
|
|
611
|
+
export async function runMiddleware(request, ctx) {
|
|
585
612
|
var isProxy = ${middlewarePath ? JSON.stringify(isProxyFile(middlewarePath)) : "false"};
|
|
586
613
|
var middlewareFn = isProxy
|
|
587
614
|
? (middlewareModule.proxy ?? middlewareModule.default)
|
|
@@ -615,12 +642,14 @@ export async function runMiddleware(request) {
|
|
|
615
642
|
mwRequest = new Request(mwUrl, request);
|
|
616
643
|
}
|
|
617
644
|
var nextRequest = mwRequest instanceof NextRequest ? mwRequest : new NextRequest(mwRequest);
|
|
645
|
+
var fetchEvent = new NextFetchEvent({ page: normalizedPathname });
|
|
618
646
|
var response;
|
|
619
|
-
try { response = await middlewareFn(nextRequest); }
|
|
647
|
+
try { response = await middlewareFn(nextRequest, fetchEvent); }
|
|
620
648
|
catch (e) {
|
|
621
649
|
console.error("[vinext] Middleware error:", e);
|
|
622
650
|
return { continue: false, response: new Response("Internal Server Error", { status: 500 }) };
|
|
623
651
|
}
|
|
652
|
+
if (ctx && typeof ctx.waitUntil === "function") { ctx.waitUntil(fetchEvent.drainWaitUntil()); } else { fetchEvent.drainWaitUntil(); }
|
|
624
653
|
|
|
625
654
|
if (!response) return { continue: true };
|
|
626
655
|
|
|
@@ -678,8 +707,11 @@ import { runWithHeadState } from "vinext/head-state";
|
|
|
678
707
|
import { safeJsonStringify } from "vinext/html";
|
|
679
708
|
import { getSSRFontLinks as _getSSRFontLinks, getSSRFontStyles as _getSSRFontStylesGoogle, getSSRFontPreloads as _getSSRFontPreloadsGoogle } from "next/font/google";
|
|
680
709
|
import { getSSRFontStyles as _getSSRFontStylesLocal, getSSRFontPreloads as _getSSRFontPreloadsLocal } from "next/font/local";
|
|
710
|
+
${instrumentationImportCode}
|
|
681
711
|
${middlewareImportCode}
|
|
682
712
|
|
|
713
|
+
${instrumentationInitCode}
|
|
714
|
+
|
|
683
715
|
// i18n config (embedded at build time)
|
|
684
716
|
const i18nConfig = ${i18nConfigJson};
|
|
685
717
|
|
|
@@ -1677,7 +1709,7 @@ hydrate();
|
|
|
1677
1709
|
// Load next.config.js if present (always from project root, not src/)
|
|
1678
1710
|
const phase = env?.command === "build" ? PHASE_PRODUCTION_BUILD : PHASE_DEVELOPMENT_SERVER;
|
|
1679
1711
|
const rawConfig = await loadNextConfig(root, phase);
|
|
1680
|
-
nextConfig = await resolveNextConfig(rawConfig);
|
|
1712
|
+
nextConfig = await resolveNextConfig(rawConfig, root);
|
|
1681
1713
|
fileMatcher = createValidFileMatcher(nextConfig.pageExtensions);
|
|
1682
1714
|
// Merge env from next.config.js with NEXT_PUBLIC_* env vars
|
|
1683
1715
|
const defines = getNextPublicEnvDefines();
|
|
@@ -1717,6 +1749,7 @@ hydrate();
|
|
|
1717
1749
|
// Build the shim alias map — used by both resolve.alias and resolveId
|
|
1718
1750
|
// (resolveId handles .js extension variants for libraries like nuqs)
|
|
1719
1751
|
nextShimMap = {
|
|
1752
|
+
...nextConfig.aliases,
|
|
1720
1753
|
"next/link": path.join(shimsDir, "link"),
|
|
1721
1754
|
"next/head": path.join(shimsDir, "head"),
|
|
1722
1755
|
"next/router": path.join(shimsDir, "router"),
|
|
@@ -1894,12 +1927,21 @@ hydrate();
|
|
|
1894
1927
|
origin: /^https?:\/\/(?:(?:[^:]+\.)?localhost|127\.0\.0\.1|\[::1\])(?::\d+)?$/,
|
|
1895
1928
|
},
|
|
1896
1929
|
},
|
|
1897
|
-
//
|
|
1898
|
-
//
|
|
1930
|
+
// Configure SSR transform behaviour for Node targets.
|
|
1931
|
+
// - `external`: React packages are loaded natively by Node (CJS)
|
|
1932
|
+
// rather than through Vite's ESM evaluator.
|
|
1933
|
+
// - `noExternal: true`: force everything else through Vite's
|
|
1934
|
+
// transform pipeline so non-JS imports (CSS, images) from
|
|
1935
|
+
// node_modules don't hit Node's native ESM loader.
|
|
1936
|
+
// Any user-provided `ssr.noExternal` is intentionally superseded
|
|
1937
|
+
// by this setting; only `ssr.external` entries escape Vite's transform.
|
|
1899
1938
|
// Skip when targeting bundled runtimes (Cloudflare/Nitro bundle everything).
|
|
1939
|
+
// This also resolves extensionless-import issues in packages like
|
|
1940
|
+
// `validator` (see #189) by routing them through Vite's resolver.
|
|
1900
1941
|
...(hasCloudflarePlugin || hasNitroPlugin ? {} : {
|
|
1901
1942
|
ssr: {
|
|
1902
1943
|
external: ["react", "react-dom", "react-dom/server"],
|
|
1944
|
+
noExternal: true,
|
|
1903
1945
|
},
|
|
1904
1946
|
}),
|
|
1905
1947
|
resolve: {
|
|
@@ -1934,6 +1976,17 @@ hydrate();
|
|
|
1934
1976
|
// Inject resolved PostCSS plugins if string names were found
|
|
1935
1977
|
...(postcssOverride ? { css: { postcss: postcssOverride } } : {}),
|
|
1936
1978
|
};
|
|
1979
|
+
// Collect user-provided ssr.external so we can propagate it into
|
|
1980
|
+
// both the RSC and SSR environment configs. Vite's `ssr.*` config
|
|
1981
|
+
// only applies to the default `ssr` environment, not custom ones
|
|
1982
|
+
// like `rsc`. Native addon packages (e.g. better-sqlite3) listed
|
|
1983
|
+
// in ssr.external must be externalized from ALL server environments.
|
|
1984
|
+
// Vite's SSROptions.external is `string[] | true`; handle both forms.
|
|
1985
|
+
const userSsrExternal = Array.isArray(config.ssr?.external)
|
|
1986
|
+
? config.ssr.external
|
|
1987
|
+
: config.ssr?.external === true
|
|
1988
|
+
? true
|
|
1989
|
+
: [];
|
|
1937
1990
|
// If app/ directory exists, configure RSC environments
|
|
1938
1991
|
if (hasAppDir) {
|
|
1939
1992
|
// Compute optimizeDeps.entries so Vite discovers server-side
|
|
@@ -1956,11 +2009,19 @@ hydrate();
|
|
|
1956
2009
|
// Note: Do NOT externalize react/react-dom here — they must
|
|
1957
2010
|
// be bundled with the "react-server" condition for RSC.
|
|
1958
2011
|
// Skip when targeting bundled runtimes (Cloudflare/Nitro).
|
|
1959
|
-
external: [
|
|
2012
|
+
external: userSsrExternal === true ? true : [
|
|
1960
2013
|
"satori",
|
|
1961
2014
|
"@resvg/resvg-js",
|
|
1962
2015
|
"yoga-wasm-web",
|
|
2016
|
+
...userSsrExternal,
|
|
1963
2017
|
],
|
|
2018
|
+
// Force all node_modules through Vite's transform pipeline
|
|
2019
|
+
// so non-JS imports (CSS, images) don't hit Node's native
|
|
2020
|
+
// ESM loader. Matches Next.js behavior of bundling everything.
|
|
2021
|
+
// Packages in `external` above take precedence per Vite rules.
|
|
2022
|
+
// When user sets `ssr.external: true`, skip noExternal since
|
|
2023
|
+
// everything is already externalized.
|
|
2024
|
+
...(userSsrExternal === true ? {} : { noExternal: true }),
|
|
1964
2025
|
},
|
|
1965
2026
|
}),
|
|
1966
2027
|
optimizeDeps: {
|
|
@@ -1975,6 +2036,17 @@ hydrate();
|
|
|
1975
2036
|
},
|
|
1976
2037
|
},
|
|
1977
2038
|
ssr: {
|
|
2039
|
+
...(hasCloudflarePlugin || hasNitroPlugin ? {} : {
|
|
2040
|
+
resolve: {
|
|
2041
|
+
external: userSsrExternal === true ? true : [...userSsrExternal],
|
|
2042
|
+
// Force all node_modules through Vite's transform pipeline
|
|
2043
|
+
// so non-JS imports (CSS, images) don't hit Node's native
|
|
2044
|
+
// ESM loader. Matches Next.js behavior of bundling everything.
|
|
2045
|
+
// When user sets `ssr.external: true`, skip noExternal since
|
|
2046
|
+
// everything is already externalized.
|
|
2047
|
+
...(userSsrExternal === true ? {} : { noExternal: true }),
|
|
2048
|
+
},
|
|
2049
|
+
}),
|
|
1978
2050
|
optimizeDeps: {
|
|
1979
2051
|
exclude: ["vinext"],
|
|
1980
2052
|
entries: appEntries,
|
|
@@ -2138,8 +2210,8 @@ hydrate();
|
|
|
2138
2210
|
rewrites: nextConfig?.rewrites,
|
|
2139
2211
|
headers: nextConfig?.headers,
|
|
2140
2212
|
allowedOrigins: nextConfig?.serverActionsAllowedOrigins,
|
|
2141
|
-
allowedDevOrigins: nextConfig?.
|
|
2142
|
-
});
|
|
2213
|
+
allowedDevOrigins: nextConfig?.allowedDevOrigins,
|
|
2214
|
+
}, instrumentationPath);
|
|
2143
2215
|
}
|
|
2144
2216
|
if (id === RESOLVED_APP_SSR_ENTRY && hasAppDir) {
|
|
2145
2217
|
return generateSsrEntry();
|
|
@@ -2149,6 +2221,8 @@ hydrate();
|
|
|
2149
2221
|
}
|
|
2150
2222
|
},
|
|
2151
2223
|
},
|
|
2224
|
+
// Stub node:async_hooks in client builds — see src/plugins/async-hooks-stub.ts
|
|
2225
|
+
asyncHooksStubPlugin,
|
|
2152
2226
|
// Proxy plugin for @mdx-js/rollup. The real MDX plugin is created lazily
|
|
2153
2227
|
// during vinext:config's config() (when MDX files are detected), but
|
|
2154
2228
|
// plugins returned from config() hooks run too late in the pipeline —
|
|
@@ -2242,6 +2316,32 @@ hydrate();
|
|
|
2242
2316
|
configureServer(server) {
|
|
2243
2317
|
// Watch pages directory for file additions/removals to invalidate route cache.
|
|
2244
2318
|
const pageExtensions = fileMatcher.extensionRegex;
|
|
2319
|
+
// Build a long-lived ModuleRunner for loading all Pages Router modules
|
|
2320
|
+
// (middleware, API routes, SSR page rendering) on every request.
|
|
2321
|
+
//
|
|
2322
|
+
// We must NOT use server.ssrLoadModule() here: when @cloudflare/vite-plugin
|
|
2323
|
+
// is present its environments replace the SSR transport, causing
|
|
2324
|
+
// SSRCompatModuleRunner to crash with:
|
|
2325
|
+
// TypeError: Cannot read properties of undefined (reading 'outsideEmitter')
|
|
2326
|
+
// on the very first request.
|
|
2327
|
+
//
|
|
2328
|
+
// createDirectRunner() builds a runner on environment.fetchModule() which
|
|
2329
|
+
// is a plain async method — safe with all plugin combinations, including
|
|
2330
|
+
// @cloudflare/vite-plugin.
|
|
2331
|
+
//
|
|
2332
|
+
// The runner is created lazily on first use so that all environments are
|
|
2333
|
+
// fully registered before we inspect them. We prefer "ssr", then any
|
|
2334
|
+
// non-"rsc" environment, then whatever is available.
|
|
2335
|
+
let pagesRunner = null;
|
|
2336
|
+
function getPagesRunner() {
|
|
2337
|
+
if (!pagesRunner) {
|
|
2338
|
+
const env = server.environments["ssr"] ??
|
|
2339
|
+
Object.values(server.environments).find((e) => e !== server.environments["rsc"]) ??
|
|
2340
|
+
Object.values(server.environments)[0];
|
|
2341
|
+
pagesRunner = createDirectRunner(env);
|
|
2342
|
+
}
|
|
2343
|
+
return pagesRunner;
|
|
2344
|
+
}
|
|
2245
2345
|
/**
|
|
2246
2346
|
* Invalidate the virtual RSC entry module in Vite's module graph.
|
|
2247
2347
|
*
|
|
@@ -2291,7 +2391,7 @@ hydrate();
|
|
|
2291
2391
|
"x-forwarded-host": req.headers["x-forwarded-host"],
|
|
2292
2392
|
"sec-fetch-site": req.headers["sec-fetch-site"],
|
|
2293
2393
|
"sec-fetch-mode": req.headers["sec-fetch-mode"],
|
|
2294
|
-
}, nextConfig?.
|
|
2394
|
+
}, nextConfig?.allowedDevOrigins);
|
|
2295
2395
|
if (blockReason) {
|
|
2296
2396
|
console.warn(`[vinext] Blocked dev request: ${blockReason} (${req.url})`);
|
|
2297
2397
|
res.writeHead(403, { "Content-Type": "text/plain" });
|
|
@@ -2303,11 +2403,28 @@ hydrate();
|
|
|
2303
2403
|
// Return a function to register middleware AFTER Vite's built-in middleware
|
|
2304
2404
|
return () => {
|
|
2305
2405
|
// Run instrumentation.ts register() if present (once at server startup).
|
|
2306
|
-
// Must be inside the returned function
|
|
2307
|
-
//
|
|
2308
|
-
//
|
|
2309
|
-
|
|
2310
|
-
|
|
2406
|
+
// Must be inside the returned function so that all environments are
|
|
2407
|
+
// fully registered before getPagesRunner() inspects them.
|
|
2408
|
+
//
|
|
2409
|
+
// App Router: register() is baked into the generated RSC entry as a
|
|
2410
|
+
// top-level await, so it runs inside the Worker process (or RSC Vite
|
|
2411
|
+
// environment) — the same process as request handling. Calling
|
|
2412
|
+
// runInstrumentation() here too would run it a second time in the host
|
|
2413
|
+
// process, which is wrong when @cloudflare/vite-plugin is present.
|
|
2414
|
+
//
|
|
2415
|
+
// Pages Router prod: register() is baked into generateServerEntry() as
|
|
2416
|
+
// a top-level await, so it runs inside the Worker bundle — the same
|
|
2417
|
+
// process as request handling. configureServer() is never called during
|
|
2418
|
+
// a prod build, so there is no double-invocation risk there either.
|
|
2419
|
+
//
|
|
2420
|
+
// We pass getPagesRunner() (createDirectRunner) rather than server so
|
|
2421
|
+
// that this is safe when @cloudflare/vite-plugin is present. That
|
|
2422
|
+
// plugin replaces the SSR environment's hot channel, causing
|
|
2423
|
+
// server.ssrLoadModule() to crash with outsideEmitter. The runner
|
|
2424
|
+
// calls environment.fetchModule() directly and never touches the hot
|
|
2425
|
+
// channel, making it safe with all Vite plugin combinations.
|
|
2426
|
+
if (instrumentationPath && !hasAppDir) {
|
|
2427
|
+
runInstrumentation(getPagesRunner(), instrumentationPath).catch((err) => {
|
|
2311
2428
|
console.error("[vinext] Instrumentation error:", err);
|
|
2312
2429
|
});
|
|
2313
2430
|
}
|
|
@@ -2446,7 +2563,7 @@ hydrate();
|
|
|
2446
2563
|
"x-forwarded-host": req.headers["x-forwarded-host"],
|
|
2447
2564
|
"sec-fetch-site": req.headers["sec-fetch-site"],
|
|
2448
2565
|
"sec-fetch-mode": req.headers["sec-fetch-mode"],
|
|
2449
|
-
}, nextConfig?.
|
|
2566
|
+
}, nextConfig?.allowedDevOrigins);
|
|
2450
2567
|
if (blockReason) {
|
|
2451
2568
|
console.warn(`[vinext] Blocked dev request: ${blockReason} (${url})`);
|
|
2452
2569
|
res.writeHead(403, { "Content-Type": "text/plain" });
|
|
@@ -2575,7 +2692,7 @@ hydrate();
|
|
|
2575
2692
|
.filter(([, v]) => v !== undefined)
|
|
2576
2693
|
.map(([k, v]) => [k, Array.isArray(v) ? v.join(", ") : String(v)])),
|
|
2577
2694
|
});
|
|
2578
|
-
const result = await runMiddleware(
|
|
2695
|
+
const result = await runMiddleware(getPagesRunner(), middlewarePath, middlewareRequest);
|
|
2579
2696
|
if (!result.continue) {
|
|
2580
2697
|
if (result.redirectUrl) {
|
|
2581
2698
|
const redirectHeaders = { Location: result.redirectUrl };
|
|
@@ -2626,11 +2743,41 @@ hydrate();
|
|
|
2626
2743
|
// Apply middleware rewrite (URL and optional status code)
|
|
2627
2744
|
if (result.rewriteUrl) {
|
|
2628
2745
|
url = result.rewriteUrl;
|
|
2746
|
+
// Write the rewritten URL back onto req.url so every subsequent
|
|
2747
|
+
// handler in the connect chain sees the correct path. The local
|
|
2748
|
+
// `url` variable is only visible within this handler — anything
|
|
2749
|
+
// further down the chain (Vite's built-in middleware, the
|
|
2750
|
+
// Cloudflare plugin's handler, or any other connect middleware)
|
|
2751
|
+
// reads req.url directly. Without this, a middleware rewrite
|
|
2752
|
+
// would be invisible to those handlers and the original URL
|
|
2753
|
+
// would be dispatched instead.
|
|
2754
|
+
req.url = url;
|
|
2629
2755
|
}
|
|
2630
2756
|
if (result.rewriteStatus) {
|
|
2631
2757
|
req.__vinextRewriteStatus = result.rewriteStatus;
|
|
2632
2758
|
}
|
|
2633
2759
|
}
|
|
2760
|
+
// ── Cloudflare Workers dev mode ────────────────────────────
|
|
2761
|
+
// When @cloudflare/vite-plugin is present, ALL rendering runs
|
|
2762
|
+
// inside the miniflare Worker subprocess — both App Router (via
|
|
2763
|
+
// virtual:vinext-rsc-entry) and Pages Router (via
|
|
2764
|
+
// virtual:vinext-server-entry → renderPage/handleApiRoute).
|
|
2765
|
+
//
|
|
2766
|
+
// The Worker entry already handles config redirects, rewrites,
|
|
2767
|
+
// headers, and all routing internally. Running them here too
|
|
2768
|
+
// would duplicate that logic and produce incorrect behaviour
|
|
2769
|
+
// (double redirects, headers set on the wrong object, etc.).
|
|
2770
|
+
//
|
|
2771
|
+
// Middleware.ts is the only thing that belongs in the host connect
|
|
2772
|
+
// handler — it has already run above. Any terminal middleware
|
|
2773
|
+
// result (redirect, block response) has already been sent.
|
|
2774
|
+
// Any rewrite has been written back to req.url above so the
|
|
2775
|
+
// Cloudflare plugin's handler sees the correct path.
|
|
2776
|
+
//
|
|
2777
|
+
// Call next() to hand off to the Cloudflare plugin's connect
|
|
2778
|
+
// handler, which dispatches the request to miniflare.
|
|
2779
|
+
if (hasCloudflarePlugin)
|
|
2780
|
+
return next();
|
|
2634
2781
|
// Build request context once for has/missing condition checks
|
|
2635
2782
|
// across headers, redirects, and rewrites.
|
|
2636
2783
|
const reqUrl = new URL(url, `http://${req.headers.host || "localhost"}`);
|
|
@@ -3767,6 +3914,8 @@ function applyRewrites(pathname, rewrites, ctx) {
|
|
|
3767
3914
|
}
|
|
3768
3915
|
/**
|
|
3769
3916
|
* Apply custom header rules from next.config.js.
|
|
3917
|
+
* Middleware headers take precedence: if a header key was already set on the
|
|
3918
|
+
* response (by middleware), the config value is skipped for that key.
|
|
3770
3919
|
*/
|
|
3771
3920
|
function applyHeaders(pathname, res, headers, ctx) {
|
|
3772
3921
|
const matched = matchHeaders(pathname, headers, ctx);
|
|
@@ -3799,7 +3948,11 @@ function applyHeaders(pathname, res, headers, ctx) {
|
|
|
3799
3948
|
}
|
|
3800
3949
|
}
|
|
3801
3950
|
else {
|
|
3802
|
-
|
|
3951
|
+
// Middleware headers take precedence: skip config keys already set by
|
|
3952
|
+
// middleware so middleware always wins over next.config.js headers.
|
|
3953
|
+
if (!res.getHeader(lk)) {
|
|
3954
|
+
res.setHeader(header.key, header.value);
|
|
3955
|
+
}
|
|
3803
3956
|
}
|
|
3804
3957
|
}
|
|
3805
3958
|
}
|
|
@@ -3854,4 +4007,5 @@ export { clientManualChunks, clientOutputConfig, clientTreeshakeConfig, computeL
|
|
|
3854
4007
|
export { resolvePostcssStringPlugins as _resolvePostcssStringPlugins };
|
|
3855
4008
|
export { parseStaticObjectLiteral as _parseStaticObjectLiteral };
|
|
3856
4009
|
export { stripServerExports as _stripServerExports };
|
|
4010
|
+
export { asyncHooksStubPlugin as _asyncHooksStubPlugin };
|
|
3857
4011
|
//# sourceMappingURL=index.js.map
|