vinext 0.1.1 → 0.1.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +2 -5
- package/dist/build/client-build-config.d.ts +7 -1
- package/dist/build/client-build-config.js +9 -1
- package/dist/build/prerender.d.ts +9 -1
- package/dist/build/prerender.js +41 -12
- package/dist/build/run-prerender.d.ts +10 -2
- package/dist/build/run-prerender.js +15 -1
- package/dist/check.js +4 -3
- package/dist/client/app-nav-failure-handler.d.ts +8 -0
- package/dist/client/app-nav-failure-handler.js +44 -0
- package/dist/client/navigation-runtime.d.ts +3 -2
- package/dist/client/vinext-next-data.d.ts +18 -1
- package/dist/client/window-next.d.ts +8 -5
- package/dist/client/window-next.js +12 -1
- package/dist/cloudflare/src/cache/cdn-adapter.runtime.js +6 -1
- package/dist/config/config-matchers.d.ts +11 -4
- package/dist/config/config-matchers.js +88 -16
- package/dist/config/next-config.d.ts +59 -4
- package/dist/config/next-config.js +149 -48
- package/dist/deploy.d.ts +30 -11
- package/dist/deploy.js +189 -101
- package/dist/entries/app-browser-entry.d.ts +9 -3
- package/dist/entries/app-browser-entry.js +21 -3
- package/dist/entries/app-rsc-entry.d.ts +2 -0
- package/dist/entries/app-rsc-entry.js +71 -6
- package/dist/entries/app-rsc-manifest.js +2 -0
- package/dist/entries/app-ssr-entry.js +1 -1
- package/dist/entries/pages-client-entry.js +54 -9
- package/dist/entries/pages-server-entry.js +48 -11
- package/dist/index.d.ts +0 -2
- package/dist/index.js +285 -139
- package/dist/plugins/dynamic-preload-metadata.d.ts +13 -0
- package/dist/plugins/dynamic-preload-metadata.js +415 -0
- package/dist/plugins/extensionless-dynamic-import.d.ts +6 -0
- package/dist/plugins/extensionless-dynamic-import.js +152 -0
- package/dist/plugins/og-assets.js +2 -2
- package/dist/plugins/optimize-imports.d.ts +10 -5
- package/dist/plugins/optimize-imports.js +27 -21
- package/dist/plugins/postcss.js +7 -7
- package/dist/plugins/sass.d.ts +53 -24
- package/dist/plugins/sass.js +249 -1
- package/dist/plugins/typeof-window.d.ts +14 -0
- package/dist/plugins/typeof-window.js +150 -0
- 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 +25 -2
- package/dist/routing/app-route-graph.js +91 -22
- package/dist/routing/file-matcher.d.ts +10 -1
- package/dist/routing/file-matcher.js +23 -2
- package/dist/routing/pages-router.js +3 -3
- package/dist/routing/utils.d.ts +35 -6
- package/dist/routing/utils.js +59 -7
- package/dist/server/api-handler.d.ts +6 -1
- package/dist/server/api-handler.js +21 -15
- package/dist/server/app-browser-action-result.d.ts +19 -6
- package/dist/server/app-browser-action-result.js +19 -10
- package/dist/server/app-browser-entry.js +269 -297
- package/dist/server/app-browser-error.d.ts +10 -3
- package/dist/server/app-browser-error.js +47 -6
- 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-hydration.d.ts +2 -0
- package/dist/server/app-browser-hydration.js +1 -0
- package/dist/server/app-browser-navigation-controller.d.ts +7 -4
- package/dist/server/app-browser-navigation-controller.js +33 -9
- 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-server-action-navigation.d.ts +6 -0
- package/dist/server/app-browser-server-action-navigation.js +9 -0
- package/dist/server/app-browser-state.js +4 -7
- package/dist/server/app-browser-stream.js +86 -43
- package/dist/server/app-browser-visible-commit.js +1 -1
- package/dist/server/app-elements-wire.d.ts +6 -1
- package/dist/server/app-elements-wire.js +14 -4
- package/dist/server/app-elements.d.ts +2 -2
- package/dist/server/app-elements.js +2 -2
- package/dist/server/app-fallback-renderer.d.ts +3 -1
- package/dist/server/app-fallback-renderer.js +6 -2
- package/dist/server/app-middleware.js +1 -0
- package/dist/server/app-optimistic-routing.js +24 -3
- package/dist/server/app-page-boundary-render.d.ts +3 -1
- package/dist/server/app-page-boundary-render.js +31 -16
- package/dist/server/app-page-cache-render.d.ts +53 -0
- package/dist/server/app-page-cache-render.js +91 -0
- package/dist/server/app-page-cache.d.ts +16 -2
- package/dist/server/app-page-cache.js +71 -8
- package/dist/server/app-page-dispatch.d.ts +34 -0
- package/dist/server/app-page-dispatch.js +167 -97
- package/dist/server/app-page-element-builder.d.ts +23 -2
- package/dist/server/app-page-element-builder.js +42 -10
- package/dist/server/app-page-execution.d.ts +7 -2
- package/dist/server/app-page-execution.js +53 -18
- package/dist/server/app-page-probe.d.ts +1 -0
- package/dist/server/app-page-probe.js +4 -0
- package/dist/server/app-page-render-observation.d.ts +3 -1
- package/dist/server/app-page-render-observation.js +17 -1
- package/dist/server/app-page-render.d.ts +13 -2
- package/dist/server/app-page-render.js +48 -17
- package/dist/server/app-page-request.d.ts +3 -0
- package/dist/server/app-page-request.js +5 -3
- package/dist/server/app-page-response.js +1 -1
- package/dist/server/app-page-route-wiring.d.ts +5 -1
- package/dist/server/app-page-route-wiring.js +21 -11
- package/dist/server/app-page-stream.d.ts +16 -9
- package/dist/server/app-page-stream.js +12 -9
- package/dist/server/app-pages-bridge.d.ts +18 -0
- package/dist/server/app-pages-bridge.js +22 -5
- package/dist/server/app-ppr-fallback-shell-render.d.ts +17 -0
- package/dist/server/app-ppr-fallback-shell-render.js +26 -0
- package/dist/server/app-ppr-fallback-shell.d.ts +13 -1
- package/dist/server/app-ppr-fallback-shell.js +8 -1
- package/dist/server/app-route-handler-dispatch.js +9 -2
- package/dist/server/app-route-handler-policy.d.ts +1 -0
- package/dist/server/app-route-handler-response.js +11 -10
- package/dist/server/app-route-handler-runtime.js +12 -1
- package/dist/server/app-router-entry.js +5 -0
- package/dist/server/app-rsc-cache-busting.js +2 -0
- package/dist/server/app-rsc-handler.d.ts +25 -0
- package/dist/server/app-rsc-handler.js +153 -53
- package/dist/server/app-rsc-response-finalizer.js +1 -1
- package/dist/server/app-rsc-route-matching.d.ts +3 -0
- package/dist/server/app-rsc-route-matching.js +2 -0
- package/dist/server/app-segment-config.d.ts +9 -1
- package/dist/server/app-segment-config.js +12 -3
- package/dist/server/app-server-action-execution.d.ts +12 -0
- package/dist/server/app-server-action-execution.js +47 -15
- package/dist/server/app-ssr-entry.d.ts +2 -0
- package/dist/server/app-ssr-entry.js +81 -8
- package/dist/server/app-ssr-stream.js +9 -1
- package/dist/server/cache-control.js +4 -0
- package/dist/server/dev-lockfile.js +2 -1
- package/dist/server/dev-server.d.ts +2 -2
- package/dist/server/dev-server.js +287 -63
- package/dist/server/headers.d.ts +8 -1
- package/dist/server/headers.js +8 -1
- package/dist/server/hybrid-route-priority.d.ts +22 -0
- package/dist/server/hybrid-route-priority.js +33 -0
- package/dist/server/image-optimization.d.ts +18 -9
- package/dist/server/image-optimization.js +37 -23
- package/dist/server/implicit-tags.d.ts +2 -1
- package/dist/server/implicit-tags.js +4 -1
- package/dist/server/instrumentation-runtime.d.ts +6 -0
- package/dist/server/instrumentation-runtime.js +8 -0
- package/dist/server/isr-decision.d.ts +79 -0
- package/dist/server/isr-decision.js +70 -0
- package/dist/server/metadata-route-response.js +5 -3
- package/dist/server/middleware-runtime.d.ts +13 -0
- package/dist/server/middleware-runtime.js +11 -7
- package/dist/server/middleware.js +1 -0
- package/dist/server/navigation-planner.d.ts +186 -22
- package/dist/server/navigation-planner.js +302 -0
- package/dist/server/navigation-trace.d.ts +18 -1
- package/dist/server/navigation-trace.js +18 -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 +20 -3
- package/dist/server/pages-api-route.js +19 -3
- package/dist/server/pages-asset-tags.d.ts +16 -4
- package/dist/server/pages-asset-tags.js +22 -12
- package/dist/server/pages-data-route.d.ts +8 -1
- package/dist/server/pages-data-route.js +16 -3
- package/dist/server/pages-get-initial-props.d.ts +54 -4
- package/dist/server/pages-get-initial-props.js +43 -1
- package/dist/server/pages-node-compat.d.ts +3 -11
- package/dist/server/pages-node-compat.js +175 -122
- package/dist/server/pages-page-data.d.ts +39 -2
- package/dist/server/pages-page-data.js +261 -46
- package/dist/server/pages-page-handler.d.ts +5 -2
- package/dist/server/pages-page-handler.js +78 -25
- package/dist/server/pages-page-response.d.ts +47 -2
- package/dist/server/pages-page-response.js +73 -9
- package/dist/server/pages-readiness.d.ts +1 -1
- package/dist/server/pages-request-pipeline.d.ts +16 -1
- package/dist/server/pages-request-pipeline.js +96 -38
- package/dist/server/pregenerated-concrete-paths.d.ts +1 -17
- package/dist/server/pregenerated-concrete-paths.js +2 -19
- package/dist/server/prerender-manifest.d.ts +33 -0
- package/dist/server/prerender-manifest.js +54 -0
- package/dist/server/prerender-route-params.d.ts +1 -2
- package/dist/server/prod-server.d.ts +39 -1
- package/dist/server/prod-server.js +107 -37
- package/dist/server/request-pipeline.d.ts +3 -15
- package/dist/server/request-pipeline.js +58 -47
- package/dist/server/rsc-stream-hints.d.ts +5 -1
- package/dist/server/rsc-stream-hints.js +6 -1
- package/dist/server/seed-cache.js +10 -18
- package/dist/shims/app-router-scroll-state.d.ts +3 -1
- package/dist/shims/app-router-scroll-state.js +14 -2
- package/dist/shims/app-router-scroll.d.ts +3 -0
- package/dist/shims/app-router-scroll.js +28 -18
- package/dist/shims/cache-runtime.js +12 -4
- package/dist/shims/cache.d.ts +1 -0
- package/dist/shims/cache.js +1 -1
- package/dist/shims/cdn-cache.d.ts +5 -5
- package/dist/shims/dynamic-preload-chunks.d.ts +8 -0
- package/dist/shims/dynamic-preload-chunks.js +79 -0
- package/dist/shims/dynamic.d.ts +4 -0
- package/dist/shims/dynamic.js +4 -2
- package/dist/shims/error-boundary.d.ts +6 -4
- package/dist/shims/error-boundary.js +7 -0
- package/dist/shims/error.js +38 -11
- package/dist/shims/error.react-server.d.ts +9 -0
- package/dist/shims/error.react-server.js +6 -0
- package/dist/shims/fetch-cache.d.ts +11 -1
- package/dist/shims/fetch-cache.js +55 -20
- package/dist/shims/hash-scroll.js +6 -1
- package/dist/shims/head.js +6 -1
- package/dist/shims/headers.d.ts +16 -2
- package/dist/shims/headers.js +66 -5
- package/dist/shims/image-config.js +7 -1
- package/dist/shims/internal/als-registry.js +28 -1
- package/dist/shims/internal/app-route-detection.d.ts +6 -3
- package/dist/shims/internal/app-route-detection.js +18 -23
- package/dist/shims/internal/app-router-context.d.ts +5 -0
- package/dist/shims/internal/hybrid-client-route-owner.d.ts +31 -0
- package/dist/shims/internal/hybrid-client-route-owner.js +143 -0
- package/dist/shims/internal/navigation-untracked.d.ts +35 -0
- package/dist/shims/internal/navigation-untracked.js +55 -0
- package/dist/shims/internal/pages-data-target.d.ts +7 -2
- package/dist/shims/internal/pages-data-target.js +17 -8
- package/dist/shims/internal/pages-router-accessor.d.ts +19 -0
- package/dist/shims/internal/pages-router-accessor.js +13 -0
- package/dist/shims/internal/router-context.d.ts +2 -1
- package/dist/shims/internal/router-context.js +3 -1
- package/dist/shims/link.js +12 -5
- package/dist/shims/metadata.d.ts +6 -2
- package/dist/shims/metadata.js +32 -14
- package/dist/shims/navigation.d.ts +14 -17
- package/dist/shims/navigation.js +93 -46
- package/dist/shims/ppr-fallback-shell.d.ts +5 -1
- package/dist/shims/ppr-fallback-shell.js +28 -7
- package/dist/shims/router.d.ts +13 -2
- package/dist/shims/router.js +434 -116
- 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 +33 -2
- package/dist/shims/server.js +75 -18
- package/dist/shims/slot.js +1 -1
- package/dist/shims/unified-request-context.js +2 -0
- package/dist/typegen.js +1 -0
- package/dist/utils/built-asset-url.d.ts +4 -0
- package/dist/utils/built-asset-url.js +11 -0
- package/dist/utils/client-build-manifest.js +15 -5
- package/dist/utils/client-runtime-metadata.d.ts +45 -0
- package/dist/utils/client-runtime-metadata.js +63 -0
- package/dist/utils/commonjs-loader.d.ts +16 -0
- package/dist/utils/commonjs-loader.js +100 -0
- package/dist/utils/deployment-id.d.ts +8 -0
- package/dist/utils/deployment-id.js +22 -0
- package/dist/utils/hash.d.ts +17 -1
- package/dist/utils/hash.js +36 -1
- package/dist/utils/html-limited-bots.d.ts +18 -1
- package/dist/utils/html-limited-bots.js +23 -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/parse-cookie.d.ts +13 -0
- package/dist/utils/parse-cookie.js +52 -0
- package/dist/utils/path.d.ts +8 -1
- package/dist/utils/path.js +13 -1
- package/package.json +2 -2
- package/dist/shims/internal/parse-cookie-header.d.ts +0 -14
- package/dist/shims/internal/parse-cookie-header.js +0 -30
package/dist/utils/hash.js
CHANGED
|
@@ -2,6 +2,11 @@
|
|
|
2
2
|
/**
|
|
3
3
|
* FNV-1a hash producing a 64-bit result (two 32-bit rounds with different seeds).
|
|
4
4
|
* Used for deterministic key generation where collisions must be rare.
|
|
5
|
+
*
|
|
6
|
+
* This is a vinext-internal format: nothing outside vinext ever compares
|
|
7
|
+
* these values, so the algorithm only needs to be deterministic. For values
|
|
8
|
+
* that must be byte-for-byte identical to what Next.js emits (ETags), use
|
|
9
|
+
* `fnv1a52` below instead — the two are NOT interchangeable.
|
|
5
10
|
*/
|
|
6
11
|
function fnv1a64(input) {
|
|
7
12
|
let h1 = 2166136261;
|
|
@@ -16,5 +21,35 @@ function fnv1a64(input) {
|
|
|
16
21
|
}
|
|
17
22
|
return h1.toString(16).padStart(8, "0") + h2.toString(16).padStart(8, "0");
|
|
18
23
|
}
|
|
24
|
+
/**
|
|
25
|
+
* FNV-1a hash producing a 52-bit result, a byte-for-byte port of Next.js's
|
|
26
|
+
* `fnv1a52` in packages/next/src/server/lib/etag.ts (itself derived from
|
|
27
|
+
* fnv-plus). Used for ETag generation, where matching Next.js's exact output
|
|
28
|
+
* matters: clients and CDNs holding `If-None-Match` values from a Next.js
|
|
29
|
+
* deployment keep revalidating (304) against vinext for unchanged payloads.
|
|
30
|
+
*
|
|
31
|
+
* Deliberately separate from `fnv1a64` above — that one is a vinext-internal
|
|
32
|
+
* key format and produces different values. Do not swap one for the other.
|
|
33
|
+
*/
|
|
34
|
+
function fnv1a52(str) {
|
|
35
|
+
const len = str.length;
|
|
36
|
+
let i = 0, t0 = 0, v0 = 8997, t1 = 0, v1 = 33826, t2 = 0, v2 = 40164, t3 = 0, v3 = 52210;
|
|
37
|
+
while (i < len) {
|
|
38
|
+
v0 ^= str.charCodeAt(i++);
|
|
39
|
+
t0 = v0 * 435;
|
|
40
|
+
t1 = v1 * 435;
|
|
41
|
+
t2 = v2 * 435;
|
|
42
|
+
t3 = v3 * 435;
|
|
43
|
+
t2 += v0 << 8;
|
|
44
|
+
t3 += v1 << 8;
|
|
45
|
+
t1 += t0 >>> 16;
|
|
46
|
+
v0 = t0 & 65535;
|
|
47
|
+
t2 += t1 >>> 16;
|
|
48
|
+
v1 = t1 & 65535;
|
|
49
|
+
v3 = t3 + (t2 >>> 16) & 65535;
|
|
50
|
+
v2 = t2 & 65535;
|
|
51
|
+
}
|
|
52
|
+
return (v3 & 15) * 281474976710656 + v2 * 4294967296 + v1 * 65536 + (v0 ^ v3 >> 4);
|
|
53
|
+
}
|
|
19
54
|
//#endregion
|
|
20
|
-
export { fnv1a64 };
|
|
55
|
+
export { fnv1a52, fnv1a64 };
|
|
@@ -1,4 +1,21 @@
|
|
|
1
1
|
//#region src/utils/html-limited-bots.d.ts
|
|
2
2
|
declare function getHtmlLimitedBotRegex(htmlLimitedBots: string | undefined): RegExp;
|
|
3
|
+
/**
|
|
4
|
+
* Returns true when the User-Agent matches a known crawler/bot. Combines
|
|
5
|
+
* Next.js's "headless browser bot" check (Googlebot proper) with the
|
|
6
|
+
* "HTML-limited bot" list (Bingbot, DuckDuckBot, facebookexternalhit, …).
|
|
7
|
+
*
|
|
8
|
+
* Used by the Pages Router fallback path: a bot hitting an unlisted
|
|
9
|
+
* `fallback: true` route should get a synchronous render (real content) and
|
|
10
|
+
* not the loading shell, so the crawler indexes the actual page. Mirrors
|
|
11
|
+
* Next.js's `isBot()` in `.nextjs-ref/packages/next/src/shared/lib/router/utils/is-bot.ts`
|
|
12
|
+
* and the bot-aware fallback flip in
|
|
13
|
+
* `.nextjs-ref/packages/next/src/server/route-modules/pages/pages-handler.ts`.
|
|
14
|
+
*
|
|
15
|
+
* `htmlLimitedBots` allows next.config to override the HTML-limited list
|
|
16
|
+
* (same flag that drives `getHtmlLimitedBotRegex`), so a custom list applies
|
|
17
|
+
* to both streaming metadata gating and bot-aware fallback rendering.
|
|
18
|
+
*/
|
|
19
|
+
declare function isBotUserAgent(userAgent: string, htmlLimitedBots?: string): boolean;
|
|
3
20
|
//#endregion
|
|
4
|
-
export { getHtmlLimitedBotRegex };
|
|
21
|
+
export { getHtmlLimitedBotRegex, isBotUserAgent };
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
//#region src/utils/html-limited-bots.ts
|
|
2
2
|
const HTML_LIMITED_BOT_UA_RE_STRING = String.raw`[\w-]+-Google|Google-[\w-]+|Chrome-Lighthouse|Slurp|DuckDuckBot|baiduspider|yandex|sogou|bitlybot|tumblr|vkShare|quora link preview|redditbot|ia_archiver|Bingbot|BingPreview|applebot|facebookexternalhit|facebookcatalog|Twitterbot|LinkedInBot|Slackbot|Discordbot|WhatsApp|SkypeUriPreview|Yeti|googleweblight`;
|
|
3
|
+
const HEADLESS_BROWSER_BOT_UA_RE = /Googlebot(?!-)|Googlebot$/i;
|
|
3
4
|
const htmlLimitedBotRegexCache = /* @__PURE__ */ new Map();
|
|
4
5
|
function getHtmlLimitedBotRegex(htmlLimitedBots) {
|
|
5
6
|
const source = htmlLimitedBots || HTML_LIMITED_BOT_UA_RE_STRING;
|
|
@@ -9,5 +10,26 @@ function getHtmlLimitedBotRegex(htmlLimitedBots) {
|
|
|
9
10
|
htmlLimitedBotRegexCache.set(source, regex);
|
|
10
11
|
return regex;
|
|
11
12
|
}
|
|
13
|
+
/**
|
|
14
|
+
* Returns true when the User-Agent matches a known crawler/bot. Combines
|
|
15
|
+
* Next.js's "headless browser bot" check (Googlebot proper) with the
|
|
16
|
+
* "HTML-limited bot" list (Bingbot, DuckDuckBot, facebookexternalhit, …).
|
|
17
|
+
*
|
|
18
|
+
* Used by the Pages Router fallback path: a bot hitting an unlisted
|
|
19
|
+
* `fallback: true` route should get a synchronous render (real content) and
|
|
20
|
+
* not the loading shell, so the crawler indexes the actual page. Mirrors
|
|
21
|
+
* Next.js's `isBot()` in `.nextjs-ref/packages/next/src/shared/lib/router/utils/is-bot.ts`
|
|
22
|
+
* and the bot-aware fallback flip in
|
|
23
|
+
* `.nextjs-ref/packages/next/src/server/route-modules/pages/pages-handler.ts`.
|
|
24
|
+
*
|
|
25
|
+
* `htmlLimitedBots` allows next.config to override the HTML-limited list
|
|
26
|
+
* (same flag that drives `getHtmlLimitedBotRegex`), so a custom list applies
|
|
27
|
+
* to both streaming metadata gating and bot-aware fallback rendering.
|
|
28
|
+
*/
|
|
29
|
+
function isBotUserAgent(userAgent, htmlLimitedBots) {
|
|
30
|
+
if (!userAgent) return false;
|
|
31
|
+
if (HEADLESS_BROWSER_BOT_UA_RE.test(userAgent)) return true;
|
|
32
|
+
return getHtmlLimitedBotRegex(htmlLimitedBots).test(userAgent);
|
|
33
|
+
}
|
|
12
34
|
//#endregion
|
|
13
|
-
export { getHtmlLimitedBotRegex };
|
|
35
|
+
export { getHtmlLimitedBotRegex, isBotUserAgent };
|
|
@@ -29,5 +29,31 @@ type BuildManifestChunk = {
|
|
|
29
29
|
* should be excluded from modulepreload hints.
|
|
30
30
|
*/
|
|
31
31
|
declare function computeLazyChunks(buildManifest: Record<string, BuildManifestChunk>): string[];
|
|
32
|
+
/**
|
|
33
|
+
* Compute the production preload files for each module referenced by a
|
|
34
|
+
* `next/dynamic()` boundary.
|
|
35
|
+
*
|
|
36
|
+
* Next.js records module IDs during compilation, then resolves those IDs
|
|
37
|
+
* against its react-loadable manifest at render time. Vinext's equivalent
|
|
38
|
+
* source of truth is Vite's build manifest: each chunk lists the modules it
|
|
39
|
+
* reaches through `dynamicImports`, and each dynamic entry lists the JS/CSS
|
|
40
|
+
* files required to evaluate it.
|
|
41
|
+
*
|
|
42
|
+
* Note on shared chunks: a boundary's static-import tree (`collectStaticChunkFiles`)
|
|
43
|
+
* can include chunks that the page entry ALSO loads eagerly (a shared vendor
|
|
44
|
+
* chunk imported by both). Those files are intentionally NOT subtracted here, so
|
|
45
|
+
* a rendered boundary may emit a `<link rel="preload">` / `<link rel="stylesheet">`
|
|
46
|
+
* for a chunk the page already `<link rel="modulepreload">`s. This is harmless —
|
|
47
|
+
* the browser dedupes preloads by URL, `ReactDOM.preload()` dedupes script hints,
|
|
48
|
+
* and React's stylesheet resource model dedupes by href + precedence — and it
|
|
49
|
+
* mirrors Next.js listing a module's full file set in its react-loadable
|
|
50
|
+
* manifest. Subtracting the eager set would couple this to the entry's import
|
|
51
|
+
* closure for no correctness gain.
|
|
52
|
+
*
|
|
53
|
+
* @returns A map keyed by root-relative module ID, with JS/CSS files that
|
|
54
|
+
* should be preloaded when that dynamic boundary is rendered.
|
|
55
|
+
*/
|
|
56
|
+
declare function computeDynamicImportPreloads(buildManifest: Record<string, BuildManifestChunk>): Record<string, string[]>;
|
|
57
|
+
declare function dynamicImportPreloadsWithBase(preloads: Record<string, string[]>, applyBase: (file: string) => string): Record<string, string[]>;
|
|
32
58
|
//#endregion
|
|
33
|
-
export { BuildManifestChunk, computeLazyChunks };
|
|
59
|
+
export { BuildManifestChunk, computeDynamicImportPreloads, computeLazyChunks, dynamicImportPreloadsWithBase };
|
|
@@ -44,5 +44,69 @@ function computeLazyChunks(buildManifest) {
|
|
|
44
44
|
}
|
|
45
45
|
return lazyChunks;
|
|
46
46
|
}
|
|
47
|
+
function normalizeManifestKey(key) {
|
|
48
|
+
return key.split("?")[0].replace(/\\/g, "/").replace(/^\/+/, "");
|
|
49
|
+
}
|
|
50
|
+
function addFile(files, seen, file) {
|
|
51
|
+
if (!file || seen.has(file)) return;
|
|
52
|
+
seen.add(file);
|
|
53
|
+
files.push(file);
|
|
54
|
+
}
|
|
55
|
+
function collectStaticChunkFiles(buildManifest, key, files, seenFiles, visitedChunks) {
|
|
56
|
+
if (visitedChunks.has(key)) return;
|
|
57
|
+
visitedChunks.add(key);
|
|
58
|
+
const chunk = buildManifest[key];
|
|
59
|
+
if (!chunk) return;
|
|
60
|
+
if (chunk.file.endsWith(".js")) addFile(files, seenFiles, chunk.file);
|
|
61
|
+
for (const cssFile of chunk.css ?? []) addFile(files, seenFiles, cssFile);
|
|
62
|
+
for (const importedKey of chunk.imports ?? []) collectStaticChunkFiles(buildManifest, importedKey, files, seenFiles, visitedChunks);
|
|
63
|
+
}
|
|
64
|
+
/**
|
|
65
|
+
* Compute the production preload files for each module referenced by a
|
|
66
|
+
* `next/dynamic()` boundary.
|
|
67
|
+
*
|
|
68
|
+
* Next.js records module IDs during compilation, then resolves those IDs
|
|
69
|
+
* against its react-loadable manifest at render time. Vinext's equivalent
|
|
70
|
+
* source of truth is Vite's build manifest: each chunk lists the modules it
|
|
71
|
+
* reaches through `dynamicImports`, and each dynamic entry lists the JS/CSS
|
|
72
|
+
* files required to evaluate it.
|
|
73
|
+
*
|
|
74
|
+
* Note on shared chunks: a boundary's static-import tree (`collectStaticChunkFiles`)
|
|
75
|
+
* can include chunks that the page entry ALSO loads eagerly (a shared vendor
|
|
76
|
+
* chunk imported by both). Those files are intentionally NOT subtracted here, so
|
|
77
|
+
* a rendered boundary may emit a `<link rel="preload">` / `<link rel="stylesheet">`
|
|
78
|
+
* for a chunk the page already `<link rel="modulepreload">`s. This is harmless —
|
|
79
|
+
* the browser dedupes preloads by URL, `ReactDOM.preload()` dedupes script hints,
|
|
80
|
+
* and React's stylesheet resource model dedupes by href + precedence — and it
|
|
81
|
+
* mirrors Next.js listing a module's full file set in its react-loadable
|
|
82
|
+
* manifest. Subtracting the eager set would couple this to the entry's import
|
|
83
|
+
* closure for no correctness gain.
|
|
84
|
+
*
|
|
85
|
+
* @returns A map keyed by root-relative module ID, with JS/CSS files that
|
|
86
|
+
* should be preloaded when that dynamic boundary is rendered.
|
|
87
|
+
*/
|
|
88
|
+
function computeDynamicImportPreloads(buildManifest) {
|
|
89
|
+
const preloads = {};
|
|
90
|
+
for (const chunk of Object.values(buildManifest)) for (const dynamicKey of chunk.dynamicImports ?? []) {
|
|
91
|
+
const files = [];
|
|
92
|
+
collectStaticChunkFiles(buildManifest, dynamicKey, files, /* @__PURE__ */ new Set(), /* @__PURE__ */ new Set());
|
|
93
|
+
if (files.length === 0) continue;
|
|
94
|
+
const normalizedKey = normalizeManifestKey(dynamicKey);
|
|
95
|
+
const existing = preloads[normalizedKey] ?? [];
|
|
96
|
+
const merged = new Set(existing);
|
|
97
|
+
for (const file of files) {
|
|
98
|
+
if (merged.has(file)) continue;
|
|
99
|
+
merged.add(file);
|
|
100
|
+
existing.push(file);
|
|
101
|
+
}
|
|
102
|
+
preloads[normalizedKey] = existing;
|
|
103
|
+
}
|
|
104
|
+
return preloads;
|
|
105
|
+
}
|
|
106
|
+
function dynamicImportPreloadsWithBase(preloads, applyBase) {
|
|
107
|
+
const withBase = {};
|
|
108
|
+
for (const [key, files] of Object.entries(preloads)) withBase[key] = files.map(applyBase);
|
|
109
|
+
return withBase;
|
|
110
|
+
}
|
|
47
111
|
//#endregion
|
|
48
|
-
export { computeLazyChunks };
|
|
112
|
+
export { computeDynamicImportPreloads, computeLazyChunks, dynamicImportPreloadsWithBase };
|
|
@@ -1,6 +1,24 @@
|
|
|
1
1
|
//#region src/utils/manifest-paths.d.ts
|
|
2
2
|
declare function manifestFileWithBase(file: string, base: string): string;
|
|
3
|
-
declare function
|
|
3
|
+
declare function manifestFileWithAssetPrefix(file: string, base: string, assetPrefix: string): string;
|
|
4
|
+
/**
|
|
5
|
+
* Resolve the URL a client asset is actually SERVED from, starting from a
|
|
6
|
+
* base-anchored manifest / SSR-manifest value (no leading slash), e.g.
|
|
7
|
+
* `"docs/cdn/_next/static/x.js"`.
|
|
8
|
+
*
|
|
9
|
+
* Next.js semantics: `assetPrefix` REPLACES `basePath` for asset URLs (they do
|
|
10
|
+
* not stack). So when an `assetPrefix` is configured we strip the basePath
|
|
11
|
+
* segment and re-anchor under the assetPrefix — matching how `next/dynamic`
|
|
12
|
+
* preloads are computed (`manifestFileWithAssetPrefix`) and what the prod server
|
|
13
|
+
* / Cloudflare ASSETS binding actually serve. Without this, a `basePath` +
|
|
14
|
+
* path-style `assetPrefix` build emits `/<basePath>/<assetPrefix>/_next/...`
|
|
15
|
+
* which 404s. When no `assetPrefix` is set, the base-anchored value is already
|
|
16
|
+
* the served URL and is returned unchanged (just root-anchored).
|
|
17
|
+
*
|
|
18
|
+
* Returns an absolute URL for an absolute `assetPrefix`, otherwise a
|
|
19
|
+
* root-relative URL beginning with `/`.
|
|
20
|
+
*/
|
|
21
|
+
declare function assetServingUrlFromBaseAnchored(value: string, basePath: string, assetPrefix: string): string;
|
|
4
22
|
/**
|
|
5
23
|
* Strip a `base` prefix that Vite applied twice: it bakes `base` into the
|
|
6
24
|
* on-disk chunk fileName and then prepends it again in `ssr-manifest.json`,
|
|
@@ -9,4 +27,4 @@ declare function manifestFilesWithBase(files: string[], base: string): string[];
|
|
|
9
27
|
*/
|
|
10
28
|
declare function collapseDuplicateBase(file: string, base: string): string;
|
|
11
29
|
//#endregion
|
|
12
|
-
export { collapseDuplicateBase,
|
|
30
|
+
export { assetServingUrlFromBaseAnchored, collapseDuplicateBase, manifestFileWithAssetPrefix, manifestFileWithBase };
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { ASSET_PREFIX_URL_DIR, isAbsoluteAssetPrefix, resolveAssetUrlPrefix, resolveAssetsDir } from "./asset-prefix.js";
|
|
1
2
|
//#region src/utils/manifest-paths.ts
|
|
2
3
|
function normalizeManifestFile(file) {
|
|
3
4
|
return file.startsWith("/") ? file.slice(1) : file;
|
|
@@ -10,8 +11,42 @@ function manifestFileWithBase(file, base) {
|
|
|
10
11
|
if (normalizedFile.startsWith(normalizedBase + "/")) return normalizedFile;
|
|
11
12
|
return normalizedBase + "/" + normalizedFile;
|
|
12
13
|
}
|
|
13
|
-
function
|
|
14
|
-
|
|
14
|
+
function manifestFileWithAssetPrefix(file, base, assetPrefix) {
|
|
15
|
+
if (!assetPrefix) return manifestFileWithBase(file, base);
|
|
16
|
+
const normalizedFile = normalizeManifestFile(file);
|
|
17
|
+
const onDiskDirPrefix = normalizeManifestFile(resolveAssetsDir(assetPrefix)) + "/";
|
|
18
|
+
const staticDirPrefix = ASSET_PREFIX_URL_DIR + "/";
|
|
19
|
+
const stripped = normalizedFile.startsWith(onDiskDirPrefix) ? normalizedFile.slice(onDiskDirPrefix.length) : normalizedFile.startsWith(staticDirPrefix) ? normalizedFile.slice(staticDirPrefix.length) : normalizedFile;
|
|
20
|
+
const urlPrefix = resolveAssetUrlPrefix(assetPrefix);
|
|
21
|
+
return (isAbsoluteAssetPrefix(assetPrefix) ? urlPrefix : normalizeManifestFile(urlPrefix)) + stripped;
|
|
22
|
+
}
|
|
23
|
+
function stripBasePathSegment(file, basePath) {
|
|
24
|
+
const normalizedBase = normalizeManifestFile(basePath).replace(/\/+$/, "");
|
|
25
|
+
if (!normalizedBase) return file;
|
|
26
|
+
return file.startsWith(normalizedBase + "/") ? file.slice(normalizedBase.length + 1) : file;
|
|
27
|
+
}
|
|
28
|
+
/**
|
|
29
|
+
* Resolve the URL a client asset is actually SERVED from, starting from a
|
|
30
|
+
* base-anchored manifest / SSR-manifest value (no leading slash), e.g.
|
|
31
|
+
* `"docs/cdn/_next/static/x.js"`.
|
|
32
|
+
*
|
|
33
|
+
* Next.js semantics: `assetPrefix` REPLACES `basePath` for asset URLs (they do
|
|
34
|
+
* not stack). So when an `assetPrefix` is configured we strip the basePath
|
|
35
|
+
* segment and re-anchor under the assetPrefix — matching how `next/dynamic`
|
|
36
|
+
* preloads are computed (`manifestFileWithAssetPrefix`) and what the prod server
|
|
37
|
+
* / Cloudflare ASSETS binding actually serve. Without this, a `basePath` +
|
|
38
|
+
* path-style `assetPrefix` build emits `/<basePath>/<assetPrefix>/_next/...`
|
|
39
|
+
* which 404s. When no `assetPrefix` is set, the base-anchored value is already
|
|
40
|
+
* the served URL and is returned unchanged (just root-anchored).
|
|
41
|
+
*
|
|
42
|
+
* Returns an absolute URL for an absolute `assetPrefix`, otherwise a
|
|
43
|
+
* root-relative URL beginning with `/`.
|
|
44
|
+
*/
|
|
45
|
+
function assetServingUrlFromBaseAnchored(value, basePath, assetPrefix) {
|
|
46
|
+
const normalized = normalizeManifestFile(value);
|
|
47
|
+
if (!assetPrefix) return "/" + normalized;
|
|
48
|
+
const anchored = manifestFileWithAssetPrefix(stripBasePathSegment(normalized, basePath), "/", assetPrefix);
|
|
49
|
+
return isAbsoluteAssetPrefix(assetPrefix) ? anchored : "/" + anchored;
|
|
15
50
|
}
|
|
16
51
|
/**
|
|
17
52
|
* Strip a `base` prefix that Vite applied twice: it bakes `base` into the
|
|
@@ -28,4 +63,4 @@ function collapseDuplicateBase(file, base) {
|
|
|
28
63
|
return normalizedFile.startsWith(doubledPrefix) ? normalizedFile.slice(normalizedBase.length + 1) : normalizedFile;
|
|
29
64
|
}
|
|
30
65
|
//#endregion
|
|
31
|
-
export { collapseDuplicateBase,
|
|
66
|
+
export { assetServingUrlFromBaseAnchored, collapseDuplicateBase, manifestFileWithAssetPrefix, manifestFileWithBase };
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
//#region src/utils/parse-cookie.d.ts
|
|
2
|
+
type ParsedCookies = Record<string, string>;
|
|
3
|
+
/**
|
|
4
|
+
* Parse a Cookie header using the semantics of Next.js's compiled `cookie`
|
|
5
|
+
* package.
|
|
6
|
+
*/
|
|
7
|
+
declare function parseCookieHeader(cookieHeader: string | null | undefined): ParsedCookies;
|
|
8
|
+
/**
|
|
9
|
+
* Parse a Cookie header using Next.js/@edge-runtime RequestCookies semantics.
|
|
10
|
+
*/
|
|
11
|
+
declare function parseEdgeRequestCookieHeader(cookieHeader: string): Map<string, string>;
|
|
12
|
+
//#endregion
|
|
13
|
+
export { ParsedCookies, parseCookieHeader, parseEdgeRequestCookieHeader };
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
//#region src/utils/parse-cookie.ts
|
|
2
|
+
function decodeCookieValue(value) {
|
|
3
|
+
try {
|
|
4
|
+
return {
|
|
5
|
+
ok: true,
|
|
6
|
+
value: decodeURIComponent(value)
|
|
7
|
+
};
|
|
8
|
+
} catch {
|
|
9
|
+
return { ok: false };
|
|
10
|
+
}
|
|
11
|
+
}
|
|
12
|
+
function forEachCookieHeaderPart(cookieHeader, visit) {
|
|
13
|
+
for (const part of cookieHeader.split(/; */)) {
|
|
14
|
+
if (!part) continue;
|
|
15
|
+
visit(part, part.indexOf("="));
|
|
16
|
+
}
|
|
17
|
+
}
|
|
18
|
+
/**
|
|
19
|
+
* Parse a Cookie header using the semantics of Next.js's compiled `cookie`
|
|
20
|
+
* package.
|
|
21
|
+
*/
|
|
22
|
+
function parseCookieHeader(cookieHeader) {
|
|
23
|
+
const cookies = {};
|
|
24
|
+
if (!cookieHeader) return cookies;
|
|
25
|
+
forEachCookieHeaderPart(cookieHeader, (part, separator) => {
|
|
26
|
+
if (separator < 0) return;
|
|
27
|
+
const key = part.slice(0, separator).trim();
|
|
28
|
+
let value = part.slice(separator + 1).trim();
|
|
29
|
+
if (cookies[key] !== void 0) return;
|
|
30
|
+
if (value.startsWith("\"")) value = value.slice(1, -1);
|
|
31
|
+
const decoded = decodeCookieValue(value);
|
|
32
|
+
cookies[key] = decoded.ok ? decoded.value : value;
|
|
33
|
+
});
|
|
34
|
+
return cookies;
|
|
35
|
+
}
|
|
36
|
+
/**
|
|
37
|
+
* Parse a Cookie header using Next.js/@edge-runtime RequestCookies semantics.
|
|
38
|
+
*/
|
|
39
|
+
function parseEdgeRequestCookieHeader(cookieHeader) {
|
|
40
|
+
const cookies = /* @__PURE__ */ new Map();
|
|
41
|
+
forEachCookieHeaderPart(cookieHeader, (part, separator) => {
|
|
42
|
+
if (separator === -1) {
|
|
43
|
+
cookies.set(part, "true");
|
|
44
|
+
return;
|
|
45
|
+
}
|
|
46
|
+
const decoded = decodeCookieValue(part.slice(separator + 1));
|
|
47
|
+
if (decoded.ok) cookies.set(part.slice(0, separator), decoded.value);
|
|
48
|
+
});
|
|
49
|
+
return cookies;
|
|
50
|
+
}
|
|
51
|
+
//#endregion
|
|
52
|
+
export { parseCookieHeader, parseEdgeRequestCookieHeader };
|
package/dist/utils/path.d.ts
CHANGED
|
@@ -11,5 +11,12 @@
|
|
|
11
11
|
* appear in filesystem paths on Linux/macOS.
|
|
12
12
|
*/
|
|
13
13
|
declare function normalizePathSeparators(p: string): string;
|
|
14
|
+
declare function stripViteModuleQuery(id: string): string;
|
|
15
|
+
/** Strip a trailing `.js` extension from a module specifier so
|
|
16
|
+
* `resolveShimModulePath` looks for the correct base name (e.g. `headers.js`
|
|
17
|
+
* → `headers`). Public and internal shim imports may carry extensionful
|
|
18
|
+
* subpaths; normalising before resolution prevents looking for non-existent
|
|
19
|
+
* files like `headers.js.ts`. */
|
|
20
|
+
declare function stripJsExtension(name: string): string;
|
|
14
21
|
//#endregion
|
|
15
|
-
export { normalizePathSeparators };
|
|
22
|
+
export { normalizePathSeparators, stripJsExtension, stripViteModuleQuery };
|
package/dist/utils/path.js
CHANGED
|
@@ -14,5 +14,17 @@ const isWindows = process.platform === "win32";
|
|
|
14
14
|
function normalizePathSeparators(p) {
|
|
15
15
|
return isWindows ? p.replace(/\\/g, "/") : p;
|
|
16
16
|
}
|
|
17
|
+
function stripViteModuleQuery(id) {
|
|
18
|
+
const queryIndex = id.search(/[?#]/);
|
|
19
|
+
return queryIndex === -1 ? id : id.slice(0, queryIndex);
|
|
20
|
+
}
|
|
21
|
+
/** Strip a trailing `.js` extension from a module specifier so
|
|
22
|
+
* `resolveShimModulePath` looks for the correct base name (e.g. `headers.js`
|
|
23
|
+
* → `headers`). Public and internal shim imports may carry extensionful
|
|
24
|
+
* subpaths; normalising before resolution prevents looking for non-existent
|
|
25
|
+
* files like `headers.js.ts`. */
|
|
26
|
+
function stripJsExtension(name) {
|
|
27
|
+
return name.endsWith(".js") ? name.slice(0, -3) : name;
|
|
28
|
+
}
|
|
17
29
|
//#endregion
|
|
18
|
-
export { normalizePathSeparators };
|
|
30
|
+
export { normalizePathSeparators, stripJsExtension, stripViteModuleQuery };
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "vinext",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.3",
|
|
4
4
|
"description": "Run Next.js apps on Vite. Drop-in replacement for the next CLI.",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"repository": {
|
|
@@ -101,7 +101,7 @@
|
|
|
101
101
|
"react-server-dom-webpack": "^19.2.7",
|
|
102
102
|
"vite": "npm:@voidzero-dev/vite-plus-core@0.1.24",
|
|
103
103
|
"vite-plus": "0.1.24",
|
|
104
|
-
"@vinext/cloudflare": "0.1.
|
|
104
|
+
"@vinext/cloudflare": "0.1.2"
|
|
105
105
|
},
|
|
106
106
|
"peerDependencies": {
|
|
107
107
|
"@mdx-js/rollup": "^3.0.0",
|
|
@@ -1,14 +0,0 @@
|
|
|
1
|
-
//#region src/shims/internal/parse-cookie-header.d.ts
|
|
2
|
-
/**
|
|
3
|
-
* Port of the current Next.js/@edge-runtime request cookie parser semantics.
|
|
4
|
-
*
|
|
5
|
-
* Important details:
|
|
6
|
-
* - split on a semicolon-plus-optional-spaces pattern
|
|
7
|
-
* - preserve whitespace around names/values otherwise
|
|
8
|
-
* - bare tokens become "true"
|
|
9
|
-
* - malformed percent-encoded values are skipped
|
|
10
|
-
* - duplicate names collapse to the last value via Map.set()
|
|
11
|
-
*/
|
|
12
|
-
declare function parseCookieHeader(cookieHeader: string): Map<string, string>;
|
|
13
|
-
//#endregion
|
|
14
|
-
export { parseCookieHeader };
|
|
@@ -1,30 +0,0 @@
|
|
|
1
|
-
//#region src/shims/internal/parse-cookie-header.ts
|
|
2
|
-
/**
|
|
3
|
-
* Port of the current Next.js/@edge-runtime request cookie parser semantics.
|
|
4
|
-
*
|
|
5
|
-
* Important details:
|
|
6
|
-
* - split on a semicolon-plus-optional-spaces pattern
|
|
7
|
-
* - preserve whitespace around names/values otherwise
|
|
8
|
-
* - bare tokens become "true"
|
|
9
|
-
* - malformed percent-encoded values are skipped
|
|
10
|
-
* - duplicate names collapse to the last value via Map.set()
|
|
11
|
-
*/
|
|
12
|
-
function parseCookieHeader(cookieHeader) {
|
|
13
|
-
const cookies = /* @__PURE__ */ new Map();
|
|
14
|
-
for (const pair of cookieHeader.split(/; */)) {
|
|
15
|
-
if (!pair) continue;
|
|
16
|
-
const splitAt = pair.indexOf("=");
|
|
17
|
-
if (splitAt === -1) {
|
|
18
|
-
cookies.set(pair, "true");
|
|
19
|
-
continue;
|
|
20
|
-
}
|
|
21
|
-
const key = pair.slice(0, splitAt);
|
|
22
|
-
const value = pair.slice(splitAt + 1);
|
|
23
|
-
try {
|
|
24
|
-
cookies.set(key, decodeURIComponent(value));
|
|
25
|
-
} catch {}
|
|
26
|
-
}
|
|
27
|
-
return cookies;
|
|
28
|
-
}
|
|
29
|
-
//#endregion
|
|
30
|
-
export { parseCookieHeader };
|