vinext 1.1.0 → 1.2.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +22 -10
- package/dist/build/client-build-config.d.ts +10 -0
- package/dist/build/client-build-config.js +18 -2
- package/dist/build/output-root-externals.d.ts +21 -0
- package/dist/build/output-root-externals.js +40 -0
- package/dist/build/pages-client-assets-module.d.ts +8 -0
- package/dist/build/pages-client-assets-module.js +21 -1
- package/dist/build/prerender-paths.js +6 -4
- package/dist/build/prerender.js +1 -1
- package/dist/build/run-prerender.js +1 -1
- package/dist/build/ssr-manifest.d.ts +2 -0
- package/dist/build/ssr-manifest.js +6 -2
- package/dist/check.js +12 -12
- package/dist/cli-dev-config.js +3 -3
- package/dist/cli.js +3 -2
- package/dist/client/client-redirect-matcher.d.ts +14 -0
- package/dist/client/client-redirect-matcher.js +37 -0
- package/dist/client/client-redirects.d.ts +27 -0
- package/dist/client/client-redirects.js +28 -0
- package/dist/client/client-rewrites.d.ts +2 -1
- package/dist/client/client-rewrites.js +1 -1
- package/dist/config/config-matchers.d.ts +26 -11
- package/dist/config/config-matchers.js +90 -88
- package/dist/config/destination-params.d.ts +47 -0
- package/dist/config/destination-params.js +116 -0
- package/dist/config/next-config.d.ts +7 -0
- package/dist/config/next-config.js +3 -0
- package/dist/entries/app-rsc-entry.d.ts +4 -0
- package/dist/entries/app-rsc-entry.js +20 -6
- package/dist/entries/pages-client-entry.js +3 -1
- package/dist/entries/pages-server-entry.js +13 -37
- package/dist/index.d.ts +3 -1
- package/dist/index.js +246 -136
- package/dist/init-cloudflare.d.ts +9 -0
- package/dist/init-cloudflare.js +107 -31
- package/dist/init-platform.d.ts +4 -0
- package/dist/init-platform.js +27 -2
- package/dist/init.d.ts +2 -1
- package/dist/init.js +153 -9
- package/dist/plugins/ast-scope.d.ts +7 -0
- package/dist/plugins/ast-scope.js +59 -3
- package/dist/plugins/ast-utils.d.ts +53 -2
- package/dist/plugins/ast-utils.js +90 -2
- package/dist/plugins/cloudflare-dev-module-urls.d.ts +41 -0
- package/dist/plugins/cloudflare-dev-module-urls.js +271 -0
- package/dist/plugins/commonjs-esm-facade.js +2 -2
- package/dist/plugins/css-module-imports.js +13 -20
- package/dist/plugins/dynamic-preload-metadata.d.ts +1 -1
- package/dist/plugins/dynamic-preload-metadata.js +11 -11
- package/dist/plugins/extensionless-dynamic-import.js +2 -3
- package/dist/plugins/fonts.d.ts +1 -1
- package/dist/plugins/fonts.js +3 -3
- package/dist/plugins/ignore-dynamic-requests.d.ts +1 -1
- package/dist/plugins/ignore-dynamic-requests.js +5 -7
- package/dist/plugins/import-meta-url.js +3 -4
- package/dist/plugins/instrumentation-client.js +3 -2
- package/dist/plugins/middleware-export-validation.js +2 -3
- package/dist/plugins/middleware-server-only.d.ts +5 -4
- package/dist/plugins/middleware-server-only.js +8 -5
- package/dist/plugins/og-harfbuzz.js +2 -3
- package/dist/plugins/optimize-imports.js +3 -4
- package/dist/plugins/pages-node-externals.js +3 -4
- package/dist/plugins/remove-console.js +2 -18
- package/dist/plugins/require-condition-resolution.js +3 -3
- package/dist/plugins/require-context.js +2 -3
- package/dist/plugins/rsc-scan-glob-imports.d.ts +19 -0
- package/dist/plugins/rsc-scan-glob-imports.js +50 -0
- package/dist/plugins/strip-server-exports.js +265 -102
- package/dist/plugins/styled-jsx.js +2 -3
- package/dist/plugins/transform-result.d.ts +9 -5
- package/dist/plugins/transitive-externals.js +1 -1
- package/dist/plugins/typeof-window.d.ts +2 -2
- package/dist/plugins/use-cache-callable.d.ts +21 -2
- package/dist/plugins/use-cache-callable.js +84 -35
- package/dist/plugins/worker-image-imports.js +30 -33
- package/dist/plugins/worker-server-only-imports.d.ts +20 -0
- package/dist/plugins/worker-server-only-imports.js +31 -0
- package/dist/plugins/worker-use-server.d.ts +25 -0
- package/dist/plugins/worker-use-server.js +153 -0
- package/dist/server/api-handler.d.ts +1 -0
- package/dist/server/api-handler.js +3 -2
- package/dist/server/app-action-forwarding.js +2 -2
- package/dist/server/app-browser-action-result.d.ts +1 -1
- package/dist/server/app-browser-action-result.js +9 -2
- package/dist/server/app-browser-entry.js +3 -3
- package/dist/server/app-browser-interception-context.js +1 -1
- package/dist/server/app-browser-navigation-controller.js +1 -1
- package/dist/server/app-browser-prefetch-response.js +2 -2
- package/dist/server/app-browser-server-action-client.js +1 -1
- package/dist/server/app-browser-state.js +1 -1
- package/dist/server/app-browser-supplemental-refresh.js +1 -1
- package/dist/server/app-middleware.d.ts +11 -0
- package/dist/server/app-middleware.js +17 -2
- package/dist/server/app-optimistic-routing.js +1 -1
- package/dist/server/app-page-cache.d.ts +1 -1
- package/dist/server/app-page-cache.js +1 -1
- package/dist/server/app-page-dispatch.d.ts +3 -1
- package/dist/server/app-page-dispatch.js +5 -4
- package/dist/server/app-page-ppr-runtime.js +1 -1
- package/dist/server/app-page-render-observation.js +1 -1
- package/dist/server/app-page-render.js +1 -1
- package/dist/server/app-page-request.js +53 -15
- package/dist/server/app-page-route-wiring.js +2 -2
- package/dist/server/app-pages-bridge.d.ts +1 -1
- package/dist/server/app-pages-bridge.js +3 -4
- package/dist/server/app-prerender-endpoints.js +9 -6
- package/dist/server/app-render-abort-error.d.ts +19 -0
- package/dist/server/app-render-abort-error.js +31 -1
- package/dist/server/app-request-stage-dispatch.js +6 -2
- package/dist/server/app-request-stage-independent-entry.js +29 -9
- package/dist/server/app-response-stage-entry.js +11 -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 +5 -2
- package/dist/server/app-route-handler-execution.d.ts +1 -0
- package/dist/server/app-route-handler-execution.js +1 -0
- package/dist/server/app-route-handler-runtime.d.ts +4 -1
- package/dist/server/app-route-handler-runtime.js +46 -25
- package/dist/server/app-router-entry.js +29 -10
- package/dist/server/app-rsc-cache-busting.d.ts +16 -0
- package/dist/server/app-rsc-cache-busting.js +30 -13
- package/dist/server/app-rsc-errors.js +20 -16
- package/dist/server/app-rsc-handler.d.ts +7 -0
- package/dist/server/app-rsc-handler.js +89 -39
- package/dist/server/app-rsc-request-normalization.js +3 -3
- package/dist/server/app-rsc-response-stage.js +5 -3
- package/dist/server/app-segment-config.d.ts +2 -1
- package/dist/server/app-server-action-execution.d.ts +2 -1
- package/dist/server/app-server-action-execution.js +62 -23
- package/dist/server/app-ssr-entry.js +7 -5
- package/dist/server/app-visited-response-cache.js +2 -2
- package/dist/server/app-worker-stages.d.ts +5 -0
- package/dist/server/app-worker-stages.js +1 -1
- package/dist/server/cacheability-request.js +2 -2
- package/dist/server/client-build-files.d.ts +16 -0
- package/dist/server/client-build-files.js +36 -0
- package/dist/server/client-reuse-manifest.js +1 -1
- package/dist/server/config-headers.js +1 -1
- package/dist/server/defer-until-stream-consumed.d.ts +2 -1
- package/dist/server/defer-until-stream-consumed.js +3 -1
- package/dist/server/dev-server.js +39 -28
- package/dist/server/dev-stack-sourcemap.js +18 -23
- package/dist/server/document-initial-head.d.ts +0 -11
- package/dist/server/document-initial-head.js +1 -1
- package/dist/server/forwarded-middleware-context.d.ts +5 -0
- package/dist/server/forwarded-middleware-context.js +22 -0
- package/dist/server/headers.d.ts +4 -1
- package/dist/server/headers.js +4 -1
- package/dist/server/http-conditional.d.ts +11 -0
- package/dist/server/http-conditional.js +10 -1
- package/dist/server/http-error-responses.d.ts +1 -1
- package/dist/server/image-optimization.d.ts +38 -0
- package/dist/server/image-optimization.js +94 -4
- package/dist/server/isr-cache.d.ts +10 -0
- package/dist/server/isr-cache.js +41 -6
- package/dist/server/metadata-route-response.js +11 -10
- package/dist/server/middleware-matcher.d.ts +2 -0
- package/dist/server/middleware-matcher.js +23 -2
- package/dist/server/middleware-path-to-regexp.js +1 -1
- package/dist/server/middleware-runtime.d.ts +13 -0
- package/dist/server/middleware-runtime.js +38 -25
- package/dist/server/middleware.d.ts +1 -1
- package/dist/server/middleware.js +3 -1
- package/dist/server/multi-stage.d.ts +11 -0
- package/dist/server/navigation-planner.js +1 -1
- package/dist/server/normalize-path.d.ts +0 -13
- package/dist/server/normalize-path.js +1 -34
- package/dist/server/open-redirect.d.ts +11 -4
- package/dist/server/open-redirect.js +11 -4
- package/dist/server/pages-api-route.d.ts +3 -2
- package/dist/server/pages-api-route.js +6 -5
- package/dist/server/pages-cache-tag.d.ts +12 -0
- package/dist/server/pages-cache-tag.js +19 -0
- package/dist/server/pages-client-assets.d.ts +2 -0
- package/dist/server/pages-data-route.d.ts +10 -0
- package/dist/server/pages-data-route.js +21 -3
- package/dist/server/pages-document-asset-props.d.ts +5 -1
- package/dist/server/pages-document-asset-props.js +13 -5
- package/dist/server/pages-document-splice.d.ts +19 -0
- package/dist/server/pages-document-splice.js +55 -0
- package/dist/server/pages-i18n.d.ts +12 -1
- package/dist/server/pages-i18n.js +18 -4
- package/dist/server/pages-node-compat.d.ts +16 -5
- package/dist/server/pages-node-compat.js +20 -12
- package/dist/server/pages-page-data.d.ts +32 -24
- package/dist/server/pages-page-data.js +51 -121
- package/dist/server/pages-page-handler.d.ts +0 -6
- package/dist/server/pages-page-handler.js +189 -127
- package/dist/server/pages-page-response.d.ts +12 -6
- package/dist/server/pages-page-response.js +42 -35
- package/dist/server/pages-request-pipeline.d.ts +10 -2
- package/dist/server/pages-request-pipeline.js +41 -22
- package/dist/server/pages-request-stage-entry.d.ts +6 -0
- package/dist/server/pages-request-stage-entry.js +75 -16
- package/dist/server/pages-response-stage-entry.js +4 -0
- package/dist/server/pages-revalidate.js +3 -3
- package/dist/server/pages-router-entry.js +5 -4
- package/dist/server/prerender-manifest.d.ts +3 -3
- package/dist/server/prerender-manifest.js +4 -3
- package/dist/server/prerender-work-unit-setup.js +4 -0
- package/dist/server/prod-server.d.ts +12 -0
- package/dist/server/prod-server.js +204 -74
- package/dist/server/proper-error.d.ts +4 -0
- package/dist/server/proper-error.js +31 -0
- package/dist/server/request-pipeline.d.ts +4 -1
- package/dist/server/request-pipeline.js +3 -2
- package/dist/server/revalidation-request.d.ts +1 -0
- package/dist/server/revalidation-request.js +1 -1
- package/dist/server/rsc-stream-hints.d.ts +1 -1
- package/dist/server/rsc-stream-hints.js +52 -5
- package/dist/server/seed-cache.d.ts +1 -0
- package/dist/server/seed-cache.js +5 -4
- package/dist/server/server-reference-loader.d.ts +4 -0
- package/dist/server/server-reference-loader.js +29 -0
- package/dist/server/socket-error-backstop.d.ts +9 -1
- package/dist/server/socket-error-backstop.js +46 -17
- package/dist/server/static-file-signal.d.ts +15 -4
- package/dist/server/static-file-signal.js +46 -12
- package/dist/server/worker-image-optimization.d.ts +34 -0
- package/dist/server/worker-image-optimization.js +99 -0
- package/dist/server/worker-stages.d.ts +1 -1
- package/dist/server/worker-stages.js +2 -2
- package/dist/server/worker-utils.d.ts +8 -3
- package/dist/server/worker-utils.js +12 -7
- package/dist/shims/app-router-scroll.js +4 -1
- package/dist/shims/app-router-tree-context.d.ts +5 -0
- package/dist/shims/app-router-tree-context.js +27 -0
- package/dist/shims/cache-callable-runtime.d.ts +4 -2
- package/dist/shims/cache-callable-runtime.js +21 -12
- package/dist/shims/cache-handler.js +1 -9
- package/dist/shims/cache-runtime.d.ts +6 -1
- package/dist/shims/cache-runtime.js +2 -1
- package/dist/shims/cache.d.ts +2 -2
- package/dist/shims/cache.js +40 -13
- package/dist/shims/cdn-cache.d.ts +8 -0
- package/dist/shims/cdn-cache.js +17 -1
- package/dist/shims/disable-smooth-scroll.d.ts +3 -0
- package/dist/shims/disable-smooth-scroll.js +36 -0
- package/dist/shims/document-placeholders.d.ts +19 -0
- package/dist/shims/document-placeholders.js +45 -0
- package/dist/shims/document.js +21 -5
- package/dist/shims/dynamic-preload-chunks.d.ts +1 -0
- package/dist/shims/dynamic-preload-chunks.js +13 -9
- package/dist/shims/dynamic.d.ts +1 -1
- package/dist/shims/dynamic.js +60 -8
- package/dist/shims/fetch-cache-state.d.ts +66 -0
- package/dist/shims/fetch-cache-state.js +92 -0
- package/dist/shims/fetch-cache.d.ts +3 -67
- package/dist/shims/fetch-cache.js +160 -125
- package/dist/shims/head.d.ts +10 -6
- package/dist/shims/head.js +16 -14
- package/dist/shims/headers.js +2 -2
- package/dist/shims/image.js +2 -1
- package/dist/shims/internal/hybrid-client-route-owner-direct.js +1 -1
- package/dist/shims/internal/hybrid-client-route-owner.js +1 -0
- package/dist/shims/internal/work-store-scope.d.ts +5 -0
- package/dist/shims/internal/work-store-scope.js +24 -0
- package/dist/shims/link-prefetch.js +5 -4
- package/dist/shims/link.js +2 -2
- package/dist/shims/navigation.js +34 -9
- package/dist/shims/request-context.d.ts +2 -0
- package/dist/shims/request-state-types.d.ts +2 -1
- package/dist/shims/router.js +21 -32
- package/dist/shims/server.d.ts +27 -4
- package/dist/shims/server.js +65 -9
- package/dist/shims/unified-request-context.d.ts +1 -1
- package/dist/shims/url-utils.d.ts +9 -0
- package/dist/shims/url-utils.js +15 -4
- package/dist/utils/client-runtime-metadata.js +1 -1
- package/dist/utils/domain-locale.js +1 -1
- package/dist/utils/hash.d.ts +7 -0
- package/dist/utils/hash.js +11 -1
- package/dist/utils/package-name.d.ts +6 -0
- package/dist/utils/package-name.js +12 -1
- package/dist/utils/plugin-rsc-version.d.ts +6 -0
- package/dist/utils/plugin-rsc-version.js +41 -0
- package/dist/utils/prerender-output-paths.js +15 -4
- package/dist/utils/public-file-path.d.ts +10 -2
- package/dist/utils/public-file-path.js +13 -9
- package/dist/utils/public-routes.js +2 -2
- package/dist/utils/react-version.d.ts +10 -0
- package/dist/utils/react-version.js +39 -16
- package/package.json +11 -7
- package/dist/build/nitro-route-rules.d.ts +0 -47
- package/dist/build/nitro-route-rules.js +0 -79
- package/dist/plugins/cache-flight-codec.d.ts +0 -19
- package/dist/plugins/cache-flight-codec.js +0 -68
package/README.md
CHANGED
|
@@ -147,6 +147,9 @@ Other options: `--port <port>` (default: 3001), `--skip-check`, `--force`.
|
|
|
147
147
|
Cloudflare init uses `cf` and `cloudflare.config.ts` by default. Both `vinext init`
|
|
148
148
|
and `create-vinext-app` accept `--legacy-wrangler-cloudflare-init` to retain the
|
|
149
149
|
legacy Wrangler setup. Existing Wrangler configs are not automatically migrated.
|
|
150
|
+
`vinext init --name <name>` sets the Worker name in the generated config instead of
|
|
151
|
+
deriving it from `package.json`. An existing config keeps its own Worker name, and init
|
|
152
|
+
prints a warning.
|
|
150
153
|
|
|
151
154
|
If your `next.config.*` sets `output: "standalone"`, `vite build` emits a self-hosting bundle at `dist/standalone/`. Start it with:
|
|
152
155
|
|
|
@@ -282,7 +285,7 @@ You can, with caution. vinext has known compatibility gaps and has not yet been
|
|
|
282
285
|
Yes. Next.js supports [self-hosting](https://nextjs.org/docs/app/building-your-application/deploying#self-hosting) on Node.js servers, Docker containers, and static exports. If you're happy with the Next.js toolchain and just want to run it somewhere other than Vercel, self-hosting is the simplest path.
|
|
283
286
|
|
|
284
287
|
**How are you verifying this works?**
|
|
285
|
-
The test suite has over 1,700 Vitest tests and 380 Playwright E2E tests. This includes tests ported directly from the [Next.js test suite](https://github.com/vercel/next.js/tree/canary/test) and [OpenNext's Cloudflare conformance suite](https://github.com/opennextjs/opennextjs-cloudflare), covering routing, SSR, RSC, server actions, caching, metadata, middleware, streaming, and more. Vercel's [App Router Playground](https://github.com/vercel/next-app-router-playground) also runs on vinext as an integration test. See the [Tests](#tests) section
|
|
288
|
+
The test suite has over 1,700 Vitest tests and 380 Playwright E2E tests. This includes tests ported directly from the [Next.js test suite](https://github.com/vercel/next.js/tree/canary/test) and [OpenNext's Cloudflare conformance suite](https://github.com/opennextjs/opennextjs-cloudflare), covering routing, SSR, RSC, server actions, caching, metadata, middleware, streaming, and more. Vercel's [App Router Playground](https://github.com/vercel/next-app-router-playground) also runs on vinext as an integration test. See the [Tests](#tests) section for details.
|
|
286
289
|
|
|
287
290
|
**Who is reviewing this code?**
|
|
288
291
|
A mix of humans and AI agents. Humans review PRs before they merge, focused on behavior, structure, and long-term direction. We lean heavily on agent-driven code review to catch issues at PR time and across the codebase. The test suite is the primary quality gate. Outside contributions and deeper human code review are very welcome.
|
|
@@ -437,10 +440,14 @@ export default defineConfig({
|
|
|
437
440
|
|
|
438
441
|
#### Module Federation (client-side)
|
|
439
442
|
|
|
440
|
-
|
|
443
|
+
Use [`@module-federation/vinext`](https://github.com/module-federation/vinext), a thin wrapper around `@module-federation/vite` with vinext defaults. Register `federation()` before `vinext()`:
|
|
444
|
+
|
|
445
|
+
```bash
|
|
446
|
+
npm install @module-federation/vinext
|
|
447
|
+
```
|
|
441
448
|
|
|
442
449
|
```ts
|
|
443
|
-
import { federation } from "@module-federation/
|
|
450
|
+
import { federation } from "@module-federation/vinext";
|
|
444
451
|
import { defineConfig } from "vite";
|
|
445
452
|
import vinext from "vinext";
|
|
446
453
|
|
|
@@ -448,11 +455,14 @@ export default defineConfig({
|
|
|
448
455
|
plugins: [
|
|
449
456
|
federation({
|
|
450
457
|
name: "host",
|
|
451
|
-
|
|
452
|
-
|
|
453
|
-
|
|
454
|
-
|
|
455
|
-
|
|
458
|
+
remotes: {
|
|
459
|
+
catalog: {
|
|
460
|
+
type: "module",
|
|
461
|
+
name: "catalog",
|
|
462
|
+
entry: "https://catalog.example.com/remoteEntry.js",
|
|
463
|
+
entryGlobalName: "catalog",
|
|
464
|
+
shareScope: "default",
|
|
465
|
+
},
|
|
456
466
|
},
|
|
457
467
|
}),
|
|
458
468
|
vinext(),
|
|
@@ -460,6 +470,8 @@ export default defineConfig({
|
|
|
460
470
|
});
|
|
461
471
|
```
|
|
462
472
|
|
|
473
|
+
The wrapper shares `react` and `react-dom` as singletons, defaults `filename` to `remoteEntry.js`, and injects the host's federation startup into the entry, because vinext has no conventional HTML entry. Explicit options override these defaults, and every `@module-federation/vite` option remains available. Passing your own `shared` replaces the default map, so keep `react`, `react/`, `react-dom`, and `react-dom/` as singletons in it, in both the host and remotes.
|
|
474
|
+
|
|
463
475
|
In a remote client component, use `getVinextReact()` before reading React hooks. vinext registers the host's browser React instance before application modules execute, and the first registration remains stable across remote evaluation and HMR:
|
|
464
476
|
|
|
465
477
|
```tsx
|
|
@@ -478,7 +490,7 @@ export function RemoteCounter() {
|
|
|
478
490
|
|
|
479
491
|
This bridge is browser-only. It does not provide App Router Module Federation SSR or transparently replace React imports inside third-party packages; compatible React versions remain the responsibility of the Module Federation `shared` configuration.
|
|
480
492
|
|
|
481
|
-
See the [
|
|
493
|
+
See the [Module Federation guide](https://vinext.dev/docs/guides/module-federation) for loading remote components in the host.
|
|
482
494
|
|
|
483
495
|
### Other platforms (via Nitro)
|
|
484
496
|
|
|
@@ -1036,7 +1048,7 @@ Or add it to your `package.json` as a file dependency:
|
|
|
1036
1048
|
}
|
|
1037
1049
|
```
|
|
1038
1050
|
|
|
1039
|
-
vinext has peer dependencies on `react ^19.
|
|
1051
|
+
vinext has peer dependencies on `react ^19.3.1`, `react-dom ^19.3.1`, `react-server-dom-webpack ^19.3.1`, and `vite ^8.0.0`. Then replace `next` with `vinext` in your scripts and run as normal.
|
|
1040
1052
|
|
|
1041
1053
|
## Contributing
|
|
1042
1054
|
|
|
@@ -116,4 +116,14 @@ export declare function createMultiStageCodeSplittingConfig(existing: VinextBuil
|
|
|
116
116
|
* the host's existing output pattern (or vinext's server-assets default).
|
|
117
117
|
*/
|
|
118
118
|
export declare function createMultiStageChunkFileNames(assetsDir: string, existing: VinextBuildOutput["chunkFileNames"]): ChunkFileNameFunction;
|
|
119
|
+
/**
|
|
120
|
+
* The client environment builds after RSC and SSR, and Vite empties its
|
|
121
|
+
* output directory first. A client output directory that is, or contains, a
|
|
122
|
+
* server output directory would therefore delete the server build.
|
|
123
|
+
*/
|
|
124
|
+
export declare function assertClientOutDirIsSeparate(root: string, dirs: {
|
|
125
|
+
clientOutDir?: string;
|
|
126
|
+
rscOutDir?: string;
|
|
127
|
+
ssrOutDir?: string;
|
|
128
|
+
}): void;
|
|
119
129
|
//#endregion
|
|
@@ -1,6 +1,7 @@
|
|
|
1
|
-
import { toSlash } from "../deps/.pnpm/pathslash@0.1.0/deps/pathslash/dist/index.js";
|
|
1
|
+
import path, { toSlash } from "../deps/.pnpm/pathslash@0.1.0/deps/pathslash/dist/index.js";
|
|
2
2
|
//#region src/build/client-build-config.ts
|
|
3
3
|
const ROUTE_OWNED_CLIENT_SHIMS = /* @__PURE__ */ new Set([
|
|
4
|
+
"app-router-tree-context",
|
|
4
5
|
"compat-router",
|
|
5
6
|
"dynamic",
|
|
6
7
|
"dynamic-preload-chunks",
|
|
@@ -266,5 +267,20 @@ function createMultiStageChunkFileNames(assetsDir, existing) {
|
|
|
266
267
|
return (existing ?? joinAssetFileNamePattern(assetsDir, "[name]-[hash].js")).replaceAll("[name]", name);
|
|
267
268
|
};
|
|
268
269
|
}
|
|
270
|
+
/**
|
|
271
|
+
* The client environment builds after RSC and SSR, and Vite empties its
|
|
272
|
+
* output directory first. A client output directory that is, or contains, a
|
|
273
|
+
* server output directory would therefore delete the server build.
|
|
274
|
+
*/
|
|
275
|
+
function assertClientOutDirIsSeparate(root, dirs) {
|
|
276
|
+
if (!dirs.clientOutDir) return;
|
|
277
|
+
const clientOutDir = path.resolve(root, dirs.clientOutDir);
|
|
278
|
+
const serverOutDirs = [["rscOutDir", dirs.rscOutDir ?? "dist/server"], ["ssrOutDir", dirs.ssrOutDir ?? "dist/server/ssr"]];
|
|
279
|
+
for (const [name, dir] of serverOutDirs) {
|
|
280
|
+
const relative = path.relative(clientOutDir, path.resolve(root, dir));
|
|
281
|
+
if (relative === ".." || relative.startsWith("../") || path.isAbsolute(relative)) continue;
|
|
282
|
+
throw new Error(`[vinext] clientOutDir "${dirs.clientOutDir}" contains ${name} "${dir}". The client build runs last and empties its output directory, which would delete the server build. Use separate output directories.`);
|
|
283
|
+
}
|
|
284
|
+
}
|
|
269
285
|
//#endregion
|
|
270
|
-
export { RSC_FRAMEWORK_CHUNK_TEST, createClientAssetFileNames, createClientCodeSplittingConfig, createClientFileNameConfig, createClientManualChunks, createMultiStageChunkFileNames, createMultiStageCodeSplittingConfig, createRscFrameworkChunkOutputConfig, getBuildBundlerOptions, getClientTreeshakeConfig, isRscFrameworkModule, sanitizeRscChunkFileName, withBuildBundlerOptions };
|
|
286
|
+
export { RSC_FRAMEWORK_CHUNK_TEST, assertClientOutDirIsSeparate, createClientAssetFileNames, createClientCodeSplittingConfig, createClientFileNameConfig, createClientManualChunks, createMultiStageChunkFileNames, createMultiStageCodeSplittingConfig, createRscFrameworkChunkOutputConfig, getBuildBundlerOptions, getClientTreeshakeConfig, isRscFrameworkModule, sanitizeRscChunkFileName, withBuildBundlerOptions };
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
import MagicString from "magic-string";
|
|
2
|
+
//#region src/build/output-root-externals.d.ts
|
|
3
|
+
/**
|
|
4
|
+
* Rewrite external virtual ids into imports of files that live at a fixed
|
|
5
|
+
* place relative to the output root.
|
|
6
|
+
*
|
|
7
|
+
* Some server modules (the cacheability manifest, the pregenerated concrete
|
|
8
|
+
* paths, the Pages client assets) are written beside the server entry, and
|
|
9
|
+
* deploy steps can rewrite them after the build. Rolldown leaves a relative
|
|
10
|
+
* external specifier exactly as written, but it can move the importing module
|
|
11
|
+
* into any chunk, for example a shared chunk under `_next/static/` when the
|
|
12
|
+
* entry becomes a facade. Keeping the virtual id external and resolving it
|
|
13
|
+
* against each chunk's own location keeps the import pointing at the file.
|
|
14
|
+
*
|
|
15
|
+
* `targets` maps each external id to its file path relative to the output root.
|
|
16
|
+
*/
|
|
17
|
+
export declare function rewriteOutputRootExternals(code: string, chunkFileName: string, targets: ReadonlyMap<string, string>): {
|
|
18
|
+
code: string;
|
|
19
|
+
map: ReturnType<MagicString["generateMap"]>;
|
|
20
|
+
} | null;
|
|
21
|
+
//#endregion
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
import path from "../deps/.pnpm/pathslash@0.1.0/deps/pathslash/dist/index.js";
|
|
2
|
+
import { escapeRegExp } from "../utils/regex.js";
|
|
3
|
+
import MagicString from "magic-string";
|
|
4
|
+
//#region src/build/output-root-externals.ts
|
|
5
|
+
/**
|
|
6
|
+
* Rewrite external virtual ids into imports of files that live at a fixed
|
|
7
|
+
* place relative to the output root.
|
|
8
|
+
*
|
|
9
|
+
* Some server modules (the cacheability manifest, the pregenerated concrete
|
|
10
|
+
* paths, the Pages client assets) are written beside the server entry, and
|
|
11
|
+
* deploy steps can rewrite them after the build. Rolldown leaves a relative
|
|
12
|
+
* external specifier exactly as written, but it can move the importing module
|
|
13
|
+
* into any chunk, for example a shared chunk under `_next/static/` when the
|
|
14
|
+
* entry becomes a facade. Keeping the virtual id external and resolving it
|
|
15
|
+
* against each chunk's own location keeps the import pointing at the file.
|
|
16
|
+
*
|
|
17
|
+
* `targets` maps each external id to its file path relative to the output root.
|
|
18
|
+
*/
|
|
19
|
+
function rewriteOutputRootExternals(code, chunkFileName, targets) {
|
|
20
|
+
let output = null;
|
|
21
|
+
const chunkDir = path.posix.dirname(chunkFileName);
|
|
22
|
+
for (const [id, target] of targets) {
|
|
23
|
+
if (!code.includes(id)) continue;
|
|
24
|
+
let specifier = path.posix.relative(chunkDir, target);
|
|
25
|
+
if (!specifier.startsWith(".")) specifier = `./${specifier}`;
|
|
26
|
+
const quotedId = new RegExp(`(["'])${escapeRegExp(id)}\\1`, "g");
|
|
27
|
+
for (const match of code.matchAll(quotedId)) {
|
|
28
|
+
output ??= new MagicString(code);
|
|
29
|
+
const quote = match[1];
|
|
30
|
+
output.overwrite(match.index, match.index + match[0].length, quote + specifier + quote);
|
|
31
|
+
}
|
|
32
|
+
}
|
|
33
|
+
if (output === null) return null;
|
|
34
|
+
return {
|
|
35
|
+
code: output.toString(),
|
|
36
|
+
map: output.generateMap({ hires: "boundary" })
|
|
37
|
+
};
|
|
38
|
+
}
|
|
39
|
+
//#endregion
|
|
40
|
+
export { rewriteOutputRootExternals };
|
|
@@ -2,5 +2,13 @@ import { PagesClientAssets } from "../server/pages-client-assets.js";
|
|
|
2
2
|
//#region src/build/pages-client-assets-module.d.ts
|
|
3
3
|
export declare const PAGES_CLIENT_ASSETS_MODULE = "vinext-client-assets.js";
|
|
4
4
|
export declare function buildPagesClientAssetsModule(assets: PagesClientAssets): string;
|
|
5
|
+
/**
|
|
6
|
+
* Select the client bundle files that live outside `_next/static`, as URL
|
|
7
|
+
* pathnames. Plugins emit these at the output root, for example a Module
|
|
8
|
+
* Federation host's `remoteEntry.js`. Public directory files are copied
|
|
9
|
+
* outside the bundle, and build metadata (vinext's and Cloudflare's
|
|
10
|
+
* `.assetsignore`) is excluded.
|
|
11
|
+
*/
|
|
12
|
+
export declare function collectClientBuildFiles(fileNames: Iterable<string>): string[];
|
|
5
13
|
export declare function writePagesClientAssetsModuleIfMissing(outputDir: string, moduleSource: string): void;
|
|
6
14
|
//#endregion
|
|
@@ -1,5 +1,7 @@
|
|
|
1
1
|
import path from "../deps/.pnpm/pathslash@0.1.0/deps/pathslash/dist/index.js";
|
|
2
|
+
import "../utils/asset-prefix.js";
|
|
2
3
|
import { getSharedChunkFiles } from "../server/pages-asset-tags.js";
|
|
4
|
+
import "../utils/client-entry-manifest.js";
|
|
3
5
|
import fs from "node:fs";
|
|
4
6
|
//#region src/build/pages-client-assets-module.ts
|
|
5
7
|
const PAGES_CLIENT_ASSETS_MODULE = "vinext-client-assets.js";
|
|
@@ -10,6 +12,24 @@ function buildPagesClientAssetsModule(assets) {
|
|
|
10
12
|
} : assets;
|
|
11
13
|
return `export default ${JSON.stringify(prepared)};\n`;
|
|
12
14
|
}
|
|
15
|
+
/**
|
|
16
|
+
* Select the client bundle files that live outside `_next/static`, as URL
|
|
17
|
+
* pathnames. Plugins emit these at the output root, for example a Module
|
|
18
|
+
* Federation host's `remoteEntry.js`. Public directory files are copied
|
|
19
|
+
* outside the bundle, and build metadata (vinext's and Cloudflare's
|
|
20
|
+
* `.assetsignore`) is excluded.
|
|
21
|
+
*/
|
|
22
|
+
function collectClientBuildFiles(fileNames) {
|
|
23
|
+
const files = [];
|
|
24
|
+
for (const fileName of fileNames) {
|
|
25
|
+
const pathname = `/${fileName}`;
|
|
26
|
+
if (pathname.includes(`/_next/static/`)) continue;
|
|
27
|
+
if (pathname.startsWith("/.vite/") || fileName === "vinext-client-entry-manifest.json") continue;
|
|
28
|
+
if (fileName === ".assetsignore") continue;
|
|
29
|
+
files.push(pathname);
|
|
30
|
+
}
|
|
31
|
+
return files.sort();
|
|
32
|
+
}
|
|
13
33
|
function writePagesClientAssetsModuleIfMissing(outputDir, moduleSource) {
|
|
14
34
|
const outputPath = path.join(outputDir, PAGES_CLIENT_ASSETS_MODULE);
|
|
15
35
|
if (fs.existsSync(outputPath)) return;
|
|
@@ -17,4 +37,4 @@ function writePagesClientAssetsModuleIfMissing(outputDir, moduleSource) {
|
|
|
17
37
|
fs.writeFileSync(outputPath, moduleSource);
|
|
18
38
|
}
|
|
19
39
|
//#endregion
|
|
20
|
-
export { PAGES_CLIENT_ASSETS_MODULE, buildPagesClientAssetsModule, writePagesClientAssetsModuleIfMissing };
|
|
40
|
+
export { PAGES_CLIENT_ASSETS_MODULE, buildPagesClientAssetsModule, collectClientBuildFiles, writePagesClientAssetsModuleIfMissing };
|
|
@@ -3,11 +3,11 @@ import { findDir } from "../utils/project.js";
|
|
|
3
3
|
import { BLOCKED_PAGES, PHASE_PRODUCTION_BUILD } from "../shims/constants.js";
|
|
4
4
|
import { VINEXT_PRERENDER_SECRET_HEADER } from "../utils/protocol-headers.js";
|
|
5
5
|
import { isExternalUrl } from "../utils/external-url.js";
|
|
6
|
+
import "../server/headers.js";
|
|
6
7
|
import { matchHeaders, matchesRewriteSource } from "../config/config-matchers.js";
|
|
7
8
|
import { loadNextConfig, resolveNextConfig } from "../config/next-config.js";
|
|
8
9
|
import { appRouteHasMainTreeLoadingBoundary, appRouter, matchAppRoute } from "../routing/app-router.js";
|
|
9
10
|
import { apiRouter, matchRoute, pagesRouter } from "../routing/pages-router.js";
|
|
10
|
-
import "../server/headers.js";
|
|
11
11
|
import { matchesMiddlewarePathname } from "../server/middleware-matcher.js";
|
|
12
12
|
import { extractLocaleFromUrl, normalizeDefaultLocalePathname } from "../server/pages-i18n.js";
|
|
13
13
|
import { classifyAppRoute, classifyAppRouteHandler, classifyPagesRoute, extractExportConstString, extractMiddlewareMatcherConfig, getAppRouteRenderEntryPath } from "./report.js";
|
|
@@ -134,6 +134,7 @@ async function fetchDiscoveryEndpoint(url, headers, retryOptions = {}) {
|
|
|
134
134
|
const request = (async () => {
|
|
135
135
|
const res = await fetch(url, {
|
|
136
136
|
headers,
|
|
137
|
+
redirect: "manual",
|
|
137
138
|
signal: controller.signal
|
|
138
139
|
});
|
|
139
140
|
return {
|
|
@@ -152,10 +153,11 @@ async function fetchDiscoveryEndpoint(url, headers, retryOptions = {}) {
|
|
|
152
153
|
if (res.status === 204) return null;
|
|
153
154
|
return text;
|
|
154
155
|
}
|
|
155
|
-
const
|
|
156
|
+
const redirected = res.status >= 300 && res.status < 400;
|
|
157
|
+
const userFailure = redirected ? null : readDiscoveryUserFailure(res, text);
|
|
156
158
|
const detail = userFailure ?? (/cloudflare:|ERR_UNSUPPORTED_ESM_URL_SCHEME/i.test(text) ? text.trim() : "");
|
|
157
|
-
lastError = /* @__PURE__ */ new Error(`path discovery returned HTTP ${res.status}${detail ? `: ${detail}` : ""}`);
|
|
158
|
-
if (!(res.status === 404 || res.status >= 500 && res.status <= 599 && userFailure === null)) {
|
|
159
|
+
lastError = redirected ? /* @__PURE__ */ new Error(`path discovery returned a redirect (HTTP ${res.status}); refusing to follow it with the prerender secret`) : /* @__PURE__ */ new Error(`path discovery returned HTTP ${res.status}${detail ? `: ${detail}` : ""}`);
|
|
160
|
+
if (!(redirected || res.status === 404 || res.status >= 500 && res.status <= 599 && userFailure === null)) {
|
|
159
161
|
shouldRetry = false;
|
|
160
162
|
throw lastError;
|
|
161
163
|
}
|
package/dist/build/prerender.js
CHANGED
|
@@ -3,8 +3,8 @@ import { createValidFileMatcher, findFileWithExtensions } from "../routing/file-
|
|
|
3
3
|
import { isUnknownRecord } from "../utils/record.js";
|
|
4
4
|
import { BLOCKED_PAGES } from "../shims/constants.js";
|
|
5
5
|
import { VINEXT_PRERENDER_ROUTE_PARAMS_HEADER, VINEXT_PRERENDER_SECRET_HEADER, VINEXT_PRERENDER_SPECULATIVE_HEADER } from "../utils/protocol-headers.js";
|
|
6
|
-
import { appRouteLayoutStaticParamsGroups } from "../routing/app-router.js";
|
|
7
6
|
import { NEXT_CACHE_TAGS_HEADER, VINEXT_METADATA_ROUTE_CACHE_HEADER, VINEXT_PRERENDER_CACHE_LIFE_HEADER, VINEXT_PRERENDER_METADATA_ROUTES_PATH, VINEXT_PRERENDER_RENDER_ERROR_HEADER, VINEXT_PRERENDER_SPECIAL_ERROR_HEADER } from "../server/headers.js";
|
|
7
|
+
import { appRouteLayoutStaticParamsGroups } from "../routing/app-router.js";
|
|
8
8
|
import { extractLocaleFromUrl } from "../server/pages-i18n.js";
|
|
9
9
|
import { classifyAppRoute, classifyPagesRoute, getAppRouteRenderEntryPath } from "./report.js";
|
|
10
10
|
import { resolveClientStaleTimeSeconds } from "../utils/cache-control-metadata.js";
|
|
@@ -124,7 +124,7 @@ async function runPrerender(options) {
|
|
|
124
124
|
let totalUrls = 0;
|
|
125
125
|
let completedUrls = 0;
|
|
126
126
|
const progress = new PrerenderProgress();
|
|
127
|
-
const outDir = mode === "export" ? path.
|
|
127
|
+
const outDir = mode === "export" ? path.resolve(root, options.routeRootConfig?.clientOutDir ?? path.join("dist", "client")) : path.join(manifestDir, "prerendered-routes");
|
|
128
128
|
let sharedProdServer = null;
|
|
129
129
|
let sharedPrerenderSecret;
|
|
130
130
|
const restorePrerenderPhase = enterPrerenderPhase();
|
|
@@ -14,6 +14,8 @@ export type BundleBackfillChunk = {
|
|
|
14
14
|
* `toSlash` where the result becomes a module id / manifest key.
|
|
15
15
|
*/
|
|
16
16
|
export declare function tryRealpathSync(candidate: string): string | null;
|
|
17
|
+
/** Forward-slash `path.relative(root, moduleId)`, which may escape with `../`. */
|
|
18
|
+
export declare function relativeToRoot(root: string, moduleId: string): string;
|
|
17
19
|
export declare function relativeWithinRoot(root: string, moduleId: string): string | null;
|
|
18
20
|
export declare function augmentSsrManifestFromBundle(ssrManifest: Record<string, string[]>, bundle: Record<string, BundleBackfillChunk | {
|
|
19
21
|
type: string;
|
|
@@ -16,8 +16,12 @@ function tryRealpathSync(candidate) {
|
|
|
16
16
|
function isWindowsAbsolutePath(candidate) {
|
|
17
17
|
return /^[a-zA-Z]:[\\/]/.test(candidate) || candidate.startsWith("\\\\");
|
|
18
18
|
}
|
|
19
|
+
/** Forward-slash `path.relative(root, moduleId)`, which may escape with `../`. */
|
|
20
|
+
function relativeToRoot(root, moduleId) {
|
|
21
|
+
return isWindowsAbsolutePath(root) || isWindowsAbsolutePath(moduleId) ? path.win32.relative(root, moduleId) : path.relative(root, moduleId);
|
|
22
|
+
}
|
|
19
23
|
function relativeWithinRoot(root, moduleId) {
|
|
20
|
-
const relativeId =
|
|
24
|
+
const relativeId = relativeToRoot(root, moduleId);
|
|
21
25
|
if (!relativeId || relativeId === ".." || relativeId.startsWith("../")) return null;
|
|
22
26
|
return relativeId;
|
|
23
27
|
}
|
|
@@ -70,4 +74,4 @@ function augmentSsrManifestFromBundle(ssrManifest, bundle, root, base = "/") {
|
|
|
70
74
|
return Object.fromEntries(Object.entries(nextManifest).map(([key, files]) => [key, [...files]]));
|
|
71
75
|
}
|
|
72
76
|
//#endregion
|
|
73
|
-
export { augmentSsrManifestFromBundle, relativeWithinRoot, tryRealpathSync };
|
|
77
|
+
export { augmentSsrManifestFromBundle, relativeToRoot, relativeWithinRoot, tryRealpathSync };
|
package/dist/check.js
CHANGED
|
@@ -3,10 +3,9 @@ import path from "./deps/.pnpm/pathslash@0.1.0/deps/pathslash/dist/index.js";
|
|
|
3
3
|
import { detectPackageManager, findDir, findViteConfigPath } from "./utils/project.js";
|
|
4
4
|
import { normalizePageExtensions } from "./routing/file-matcher.js";
|
|
5
5
|
import { POSTCSS_CONFIG_FILES } from "./plugins/postcss.js";
|
|
6
|
-
import { unwrapExpression } from "./plugins/ast-utils.js";
|
|
6
|
+
import { parseProgram, unwrapExpression } from "./plugins/ast-utils.js";
|
|
7
7
|
import { require_ignore } from "./deps/.pnpm/ignore@5.3.2/deps/ignore/index.js";
|
|
8
8
|
import fs from "node:fs";
|
|
9
|
-
import { parseAst } from "vite";
|
|
10
9
|
//#region src/check.ts
|
|
11
10
|
/**
|
|
12
11
|
* vinext check — compatibility scanner for Next.js apps
|
|
@@ -210,7 +209,7 @@ const CONFIG_SUPPORT = {
|
|
|
210
209
|
},
|
|
211
210
|
transpilePackages: {
|
|
212
211
|
status: "supported",
|
|
213
|
-
detail: "listed packages are bundled instead of externalized on the server"
|
|
212
|
+
detail: "listed packages are bundled instead of externalized on the server, and their next/dynamic() calls get SSR preload links"
|
|
214
213
|
},
|
|
215
214
|
serverExternalPackages: {
|
|
216
215
|
status: "supported",
|
|
@@ -252,9 +251,10 @@ const CONFIG_SUPPORT = {
|
|
|
252
251
|
status: "unsupported",
|
|
253
252
|
detail: "custom cacheLife profiles are ignored; only the built-in profiles are available"
|
|
254
253
|
},
|
|
255
|
-
skipTrailingSlashRedirect: {
|
|
256
|
-
|
|
257
|
-
|
|
254
|
+
skipTrailingSlashRedirect: { status: "supported" },
|
|
255
|
+
"experimental.skipTrailingSlashRedirect": {
|
|
256
|
+
status: "supported",
|
|
257
|
+
detail: "legacy alias of skipTrailingSlashRedirect"
|
|
258
258
|
},
|
|
259
259
|
reactCompiler: {
|
|
260
260
|
status: "partial",
|
|
@@ -433,8 +433,8 @@ const LIBRARY_SUPPORT = {
|
|
|
433
433
|
detail: "renders client-side; by default events are only collected when deployed on Vercel"
|
|
434
434
|
},
|
|
435
435
|
"next-intl": {
|
|
436
|
-
status: "
|
|
437
|
-
detail: "
|
|
436
|
+
status: "supported",
|
|
437
|
+
detail: "createNextIntlPlugin is only optional with the request config at (src/)i18n/request.*; its experimental messages, precompile and extract options don't work (they need webpack/Turbopack loaders)"
|
|
438
438
|
},
|
|
439
439
|
"@clerk/nextjs": {
|
|
440
440
|
status: "supported",
|
|
@@ -812,7 +812,7 @@ function propertyKeyName(prop) {
|
|
|
812
812
|
* object — top-level keys plus, for each object-valued property, its child keys
|
|
813
813
|
* (used for dot-notation options like `experimental.ppr`).
|
|
814
814
|
*
|
|
815
|
-
* Uses Vite's
|
|
815
|
+
* Uses Vite's bundled oxc parser instead of scanning text, so
|
|
816
816
|
* comments, string values, and other non-key mentions of an option name are
|
|
817
817
|
* never mistaken for a real config option. Returns empty sets if the file cannot
|
|
818
818
|
* be parsed — the check is advisory, so a parse failure simply reports nothing.
|
|
@@ -823,7 +823,7 @@ function collectConfigKeys(source) {
|
|
|
823
823
|
let pageExtensions;
|
|
824
824
|
let program;
|
|
825
825
|
try {
|
|
826
|
-
program =
|
|
826
|
+
program = parseProgram(source, { lang: "ts" });
|
|
827
827
|
} catch {
|
|
828
828
|
return {
|
|
829
829
|
top,
|
|
@@ -970,7 +970,7 @@ function isNextConfigWithCjsGlobals(rel, content) {
|
|
|
970
970
|
if (/^next\.config\.(?:ts|mts|cjs)$/.test(rel)) return true;
|
|
971
971
|
if (rel !== "next.config.js") return false;
|
|
972
972
|
try {
|
|
973
|
-
return !
|
|
973
|
+
return !parseProgram(content).body.some((node) => node.type === "ImportDeclaration" || node.type.startsWith("Export"));
|
|
974
974
|
} catch {
|
|
975
975
|
return false;
|
|
976
976
|
}
|
|
@@ -983,7 +983,7 @@ function isNextConfigWithCjsGlobals(rel, content) {
|
|
|
983
983
|
function exportsPostcssPluginsOnlyObject(content) {
|
|
984
984
|
let program;
|
|
985
985
|
try {
|
|
986
|
-
program =
|
|
986
|
+
program = parseProgram(content, { lang: "ts" });
|
|
987
987
|
} catch {
|
|
988
988
|
return false;
|
|
989
989
|
}
|
package/dist/cli-dev-config.js
CHANGED
|
@@ -28,7 +28,7 @@ function claimViteCliDevInvocation(root, isRestart = false, isReserved = false)
|
|
|
28
28
|
return true;
|
|
29
29
|
}
|
|
30
30
|
function applyDevServerDefaults(server, options) {
|
|
31
|
-
|
|
31
|
+
if (options.port !== void 0) server.port = options.port;
|
|
32
32
|
server.host = options.hostname ?? server.host ?? "localhost";
|
|
33
33
|
}
|
|
34
34
|
function createDevServerLifecyclePlugin(options, isEnabled) {
|
|
@@ -114,7 +114,7 @@ function configureDevServerLifecycle(server) {
|
|
|
114
114
|
const listenServer = server.listen.bind(server);
|
|
115
115
|
server.listen = async (port, isRestart) => {
|
|
116
116
|
if (server.config.server.middlewareMode || process.env.VINEXT_NO_DEV_LOCK === "1") return listenServer(port, isRestart);
|
|
117
|
-
const configuredPort = port ?? server.config.server.port
|
|
117
|
+
const configuredPort = port ?? server.config.server.port;
|
|
118
118
|
const hostname = normalizeDevServerHostname(server.config.server.host);
|
|
119
119
|
const displayHostname = hostname === "0.0.0.0" ? "localhost" : hostname;
|
|
120
120
|
const restartingLock = activeDevServerLocks.get(root);
|
|
@@ -155,7 +155,7 @@ function configureDevServerLifecycle(server) {
|
|
|
155
155
|
};
|
|
156
156
|
server.httpServer?.on("listening", () => {
|
|
157
157
|
if (!activeLock) return;
|
|
158
|
-
const port = server.config.server.port
|
|
158
|
+
const port = server.config.server.port;
|
|
159
159
|
const hostname = normalizeDevServerHostname(server.config.server.host);
|
|
160
160
|
const displayHostname = hostname === "0.0.0.0" ? "localhost" : hostname;
|
|
161
161
|
const lock = activeLock;
|
package/dist/cli.js
CHANGED
|
@@ -4,8 +4,8 @@ import { detectPackageManager, ensureViteConfigCompatibility, findViteConfigPath
|
|
|
4
4
|
import { formatReport, runCheck } from "./check.js";
|
|
5
5
|
import { parseArgs } from "./cli-args.js";
|
|
6
6
|
import { findViteRoot, getViteCliInvocation, valueOptionName } from "./utils/vite-cli-invocation.js";
|
|
7
|
-
import { init } from "./init.js";
|
|
8
7
|
import { resolveInitOptions } from "./init-platform.js";
|
|
8
|
+
import { init } from "./init.js";
|
|
9
9
|
import { loadDotenv } from "./config/dotenv.js";
|
|
10
10
|
import { PHASE_PRODUCTION_BUILD } from "./shims/constants.js";
|
|
11
11
|
import { loadNextConfig, resolveNextConfig } from "./config/next-config.js";
|
|
@@ -275,6 +275,7 @@ function printHelp(cmd) {
|
|
|
275
275
|
--no-install Update dependency entries without installing them
|
|
276
276
|
--force Overwrite existing vite.config.ts
|
|
277
277
|
--platform <target> Deployment target: cloudflare or node
|
|
278
|
+
--name <name> Cloudflare Worker name (default: derived from package.json)
|
|
278
279
|
--prerender Configure Vite builds to pre-render static routes
|
|
279
280
|
(Cloudflare deploy won't serve them unless using Static Assets)
|
|
280
281
|
--warm-cache Add cache warming to the Cloudflare deploy script
|
|
@@ -363,7 +364,7 @@ function printHelp(cmd) {
|
|
|
363
364
|
--version Show version
|
|
364
365
|
|
|
365
366
|
Examples:
|
|
366
|
-
vinext dev Start dev server
|
|
367
|
+
vinext dev Start dev server
|
|
367
368
|
vinext dev --port 4000 Start dev server on port 4000
|
|
368
369
|
vinext build Build for production
|
|
369
370
|
vinext typegen Generate route helper types
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import { RequestContext } from "../config/request-context.js";
|
|
2
|
+
import { BasePathMatchState, RedirectMatch } from "../config/config-matchers.js";
|
|
3
|
+
import { ClientRedirect } from "./client-redirects.js";
|
|
4
|
+
//#region src/client/client-redirect-matcher.d.ts
|
|
5
|
+
/**
|
|
6
|
+
* Resolve the first matching client-safe redirect. A matching server-owned
|
|
7
|
+
* rule stops client evaluation and returns null so a later client-safe rule
|
|
8
|
+
* cannot take its place. The navigation then continues as it does in Next.js,
|
|
9
|
+
* which never resolves config redirects in the browser: a document request (or
|
|
10
|
+
* a data request that falls back to one) reaches the server rule, while a page
|
|
11
|
+
* without data fetching renders without it.
|
|
12
|
+
*/
|
|
13
|
+
export declare function matchClientRedirect(pathname: string, redirects: ClientRedirect[], context: RequestContext, basePathState: BasePathMatchState): RedirectMatch | null;
|
|
14
|
+
//#endregion
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
import { matchRedirect } from "../config/config-matchers.js";
|
|
2
|
+
//#region src/client/client-redirect-matcher.ts
|
|
3
|
+
const matcherRules = /* @__PURE__ */ new WeakMap();
|
|
4
|
+
function getMatcherRule(redirect) {
|
|
5
|
+
let rule = matcherRules.get(redirect);
|
|
6
|
+
if (!rule) {
|
|
7
|
+
rule = [{
|
|
8
|
+
source: redirect.source,
|
|
9
|
+
destination: redirect.destination ?? "/",
|
|
10
|
+
permanent: redirect.permanent ?? false,
|
|
11
|
+
has: redirect.has,
|
|
12
|
+
missing: redirect.missing,
|
|
13
|
+
locale: redirect.locale,
|
|
14
|
+
basePath: redirect.basePath
|
|
15
|
+
}];
|
|
16
|
+
matcherRules.set(redirect, rule);
|
|
17
|
+
}
|
|
18
|
+
return rule;
|
|
19
|
+
}
|
|
20
|
+
/**
|
|
21
|
+
* Resolve the first matching client-safe redirect. A matching server-owned
|
|
22
|
+
* rule stops client evaluation and returns null so a later client-safe rule
|
|
23
|
+
* cannot take its place. The navigation then continues as it does in Next.js,
|
|
24
|
+
* which never resolves config redirects in the browser: a document request (or
|
|
25
|
+
* a data request that falls back to one) reaches the server rule, while a page
|
|
26
|
+
* without data fetching renders without it.
|
|
27
|
+
*/
|
|
28
|
+
function matchClientRedirect(pathname, redirects, context, basePathState) {
|
|
29
|
+
for (const redirect of redirects) {
|
|
30
|
+
const match = matchRedirect(pathname, getMatcherRule(redirect), context, basePathState);
|
|
31
|
+
if (match === null) continue;
|
|
32
|
+
return redirect.requiresServerEvaluation ? null : match;
|
|
33
|
+
}
|
|
34
|
+
return null;
|
|
35
|
+
}
|
|
36
|
+
//#endregion
|
|
37
|
+
export { matchClientRedirect };
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
import { NextRedirect, ResolvedNextConfig } from "../config/next-config.js";
|
|
2
|
+
import { ClientHasCondition } from "./client-rewrites.js";
|
|
3
|
+
//#region src/client/client-redirects.d.ts
|
|
4
|
+
type ClientRedirectFields = Pick<NextRedirect, "basePath" | "locale" | "source"> & {
|
|
5
|
+
has?: ClientHasCondition[];
|
|
6
|
+
missing?: ClientHasCondition[];
|
|
7
|
+
};
|
|
8
|
+
/**
|
|
9
|
+
* Redirect data that is safe to publish in a browser bundle.
|
|
10
|
+
*
|
|
11
|
+
* Next.js keeps redirects in the server routes manifest only. Vinext resolves
|
|
12
|
+
* browser-authoritative redirects during Pages Router navigation, but rules
|
|
13
|
+
* with header or cookie conditions are server-owned: their condition values
|
|
14
|
+
* can be private, so the rule keeps only its source and client-safe
|
|
15
|
+
* conditions to preserve first-match ordering, and drops its destination.
|
|
16
|
+
*/
|
|
17
|
+
export type ClientRedirect = (ClientRedirectFields & {
|
|
18
|
+
destination: string;
|
|
19
|
+
permanent: boolean;
|
|
20
|
+
requiresServerEvaluation?: never;
|
|
21
|
+
}) | (ClientRedirectFields & {
|
|
22
|
+
destination?: never;
|
|
23
|
+
permanent?: never;
|
|
24
|
+
requiresServerEvaluation: true;
|
|
25
|
+
});
|
|
26
|
+
export declare function toClientRedirects(redirects: ResolvedNextConfig["redirects"]): ClientRedirect[];
|
|
27
|
+
//#endregion
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
import { isClientHasCondition } from "./client-rewrites.js";
|
|
2
|
+
//#region src/client/client-redirects.ts
|
|
3
|
+
function toClientRedirect(redirect) {
|
|
4
|
+
const hasServerOnlyCondition = (redirect.has?.some((condition) => !isClientHasCondition(condition)) ?? false) || (redirect.missing?.some((condition) => !isClientHasCondition(condition)) ?? false);
|
|
5
|
+
const clientHas = redirect.has?.filter(isClientHasCondition);
|
|
6
|
+
const clientMissing = redirect.missing?.filter(isClientHasCondition);
|
|
7
|
+
const common = {
|
|
8
|
+
source: redirect.source,
|
|
9
|
+
has: clientHas?.length ? clientHas : void 0,
|
|
10
|
+
missing: clientMissing?.length ? clientMissing : void 0,
|
|
11
|
+
locale: redirect.locale,
|
|
12
|
+
basePath: redirect.basePath
|
|
13
|
+
};
|
|
14
|
+
if (hasServerOnlyCondition) return {
|
|
15
|
+
...common,
|
|
16
|
+
requiresServerEvaluation: true
|
|
17
|
+
};
|
|
18
|
+
return {
|
|
19
|
+
...common,
|
|
20
|
+
destination: redirect.destination,
|
|
21
|
+
permanent: redirect.permanent
|
|
22
|
+
};
|
|
23
|
+
}
|
|
24
|
+
function toClientRedirects(redirects) {
|
|
25
|
+
return redirects.map(toClientRedirect);
|
|
26
|
+
}
|
|
27
|
+
//#endregion
|
|
28
|
+
export { toClientRedirects };
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { HasCondition, NextRewrite, ResolvedNextConfig } from "../config/next-config.js";
|
|
2
2
|
//#region src/client/client-rewrites.d.ts
|
|
3
|
-
type ClientHasCondition = Omit<HasCondition, "type"> & {
|
|
3
|
+
export type ClientHasCondition = Omit<HasCondition, "type"> & {
|
|
4
4
|
type: "host" | "query";
|
|
5
5
|
};
|
|
6
6
|
type ClientRewriteFields = Pick<NextRewrite, "basePath" | "locale" | "source"> & {
|
|
@@ -26,5 +26,6 @@ export type ClientRewrites = {
|
|
|
26
26
|
beforeFiles: ClientRewrite[];
|
|
27
27
|
fallback: ClientRewrite[];
|
|
28
28
|
};
|
|
29
|
+
export declare function isClientHasCondition(condition: HasCondition): condition is ClientHasCondition;
|
|
29
30
|
export declare function toClientRewrites(rewrites: ResolvedNextConfig["rewrites"]): ClientRewrites;
|
|
30
31
|
//#endregion
|