vinext 1.0.0 → 1.1.0
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 +72 -1
- package/THIRD_PARTY_LICENSES.md +26 -0
- package/dist/build/app-page-static-eligibility.d.ts +15 -0
- package/dist/build/app-page-static-eligibility.js +82 -0
- package/dist/build/lifecycle.js +10 -10
- package/dist/build/pages-client-assets-module.js +6 -1
- package/dist/build/precompress.js +1 -1
- package/dist/build/prerender-paths.js +6 -85
- package/dist/build/prerender.d.ts +8 -1
- package/dist/build/prerender.js +167 -46
- package/dist/build/run-prerender.js +4 -3
- package/dist/build/server-entry.d.ts +2 -0
- package/dist/build/server-entry.js +7 -1
- package/dist/build/server-manifest.d.ts +7 -0
- package/dist/build/server-manifest.js +11 -1
- package/dist/cache/cache-adapters-virtual.d.ts +7 -1
- package/dist/cache/cache-adapters-virtual.js +3 -3
- package/dist/client/browser-globals.d.ts +4 -0
- package/dist/client/browser-globals.js +5 -0
- package/dist/client/navigation-runtime.d.ts +11 -1
- package/dist/client/navigation-runtime.js +3 -3
- package/dist/config/config-matchers.js +3 -1
- package/dist/config/dotenv.js +14 -3
- package/dist/config/next-config.d.ts +7 -0
- package/dist/config/next-config.js +18 -3
- package/dist/entries/app-rsc-entry.d.ts +2 -0
- package/dist/entries/app-rsc-entry.js +67 -45
- package/dist/index.d.ts +4 -1
- package/dist/index.js +200 -100
- package/dist/init-cloudflare.d.ts +1 -1
- package/dist/init-cloudflare.js +6 -6
- package/dist/init-platform.js +1 -1
- package/dist/init.js +4 -2
- package/dist/plugins/cache-flight-codec.d.ts +19 -0
- package/dist/plugins/cache-flight-codec.js +68 -0
- package/dist/plugins/commonjs-esm-facade.d.ts +35 -0
- package/dist/plugins/commonjs-esm-facade.js +80 -0
- package/dist/plugins/commonjs-syntax.d.ts +16 -0
- package/dist/plugins/commonjs-syntax.js +22 -0
- package/dist/plugins/fonts.d.ts +8 -11
- package/dist/plugins/fonts.js +71 -34
- package/dist/plugins/ignore-dynamic-requests.d.ts +11 -0
- package/dist/plugins/ignore-dynamic-requests.js +54 -3
- package/dist/plugins/import-meta-url.js +6 -6
- package/dist/plugins/og-asset-ownership.d.ts +2 -0
- package/dist/plugins/og-asset-ownership.js +24 -13
- package/dist/plugins/og-assets.d.ts +18 -0
- package/dist/plugins/og-assets.js +50 -8
- package/dist/plugins/og-harfbuzz.js +38 -27
- package/dist/plugins/optimize-imports.js +2 -1
- package/dist/plugins/require-context.d.ts +1 -0
- package/dist/plugins/require-context.js +28 -1
- package/dist/plugins/scan-build-css.d.ts +12 -0
- package/dist/plugins/scan-build-css.js +39 -0
- package/dist/plugins/strip-server-exports.d.ts +2 -0
- package/dist/plugins/strip-server-exports.js +3 -1
- package/dist/plugins/transform-result.d.ts +18 -0
- package/dist/plugins/transform-result.js +23 -2
- package/dist/plugins/typeof-window.d.ts +10 -0
- package/dist/plugins/typeof-window.js +33 -9
- package/dist/routing/app-route-graph.d.ts +0 -1
- package/dist/routing/app-route-graph.js +2 -4
- package/dist/routing/app-route-ids.d.ts +3 -0
- package/dist/routing/app-route-ids.js +6 -0
- package/dist/routing/file-matcher.d.ts +1 -0
- package/dist/routing/file-matcher.js +1 -1
- package/dist/server/api-handler.js +17 -7
- package/dist/server/app-bfcache-id.d.ts +1 -0
- package/dist/server/app-bfcache-id.js +7 -1
- package/dist/server/app-bfcache-identity.js +1 -2
- package/dist/server/app-browser-entry.js +15 -9
- package/dist/server/app-browser-history-controller.d.ts +2 -0
- package/dist/server/app-browser-history-controller.js +8 -0
- package/dist/server/app-browser-hydration.d.ts +1 -1
- package/dist/server/app-browser-hydration.js +2 -2
- package/dist/server/app-browser-interception-context.js +26 -2
- package/dist/server/app-browser-navigation-controller.d.ts +7 -1
- package/dist/server/app-browser-navigation-controller.js +94 -11
- package/dist/server/app-browser-state.js +1 -1
- package/dist/server/app-browser-stream.d.ts +1 -1
- package/dist/server/app-fallback-renderer.d.ts +2 -0
- package/dist/server/app-fallback-renderer.js +1 -0
- package/dist/server/app-history-state.d.ts +3 -1
- package/dist/server/app-history-state.js +9 -5
- package/dist/server/app-middleware.js +2 -1
- package/dist/server/app-optimistic-routing.js +1 -1
- package/dist/server/app-page-boundary-render.d.ts +5 -0
- package/dist/server/app-page-boundary-render.js +6 -4
- package/dist/server/app-page-cache-finalizer.d.ts +11 -0
- package/dist/server/app-page-cache-finalizer.js +41 -7
- package/dist/server/app-page-cache-render.d.ts +18 -0
- package/dist/server/app-page-cache-render.js +65 -44
- package/dist/server/app-page-cache.d.ts +5 -0
- package/dist/server/app-page-cache.js +27 -7
- package/dist/server/app-page-dispatch.d.ts +9 -1
- package/dist/server/app-page-dispatch.js +47 -30
- package/dist/server/app-page-element-builder.d.ts +7 -0
- package/dist/server/app-page-element-builder.js +27 -42
- package/dist/server/app-page-execution.d.ts +15 -12
- package/dist/server/app-page-execution.js +30 -40
- package/dist/server/app-page-head.d.ts +5 -0
- package/dist/server/app-page-head.js +9 -3
- package/dist/server/app-page-probe.d.ts +0 -109
- package/dist/server/app-page-probe.js +3 -136
- package/dist/server/app-page-render-identity.d.ts +0 -1
- package/dist/server/app-page-render-identity.js +1 -1
- package/dist/server/app-page-render-observation.js +2 -2
- package/dist/server/app-page-render.d.ts +13 -5
- package/dist/server/app-page-render.js +219 -118
- package/dist/server/app-page-request.d.ts +0 -1
- package/dist/server/app-page-request.js +1 -2
- package/dist/server/app-page-response.d.ts +4 -3
- package/dist/server/app-page-response.js +4 -3
- package/dist/server/app-page-route-wiring.d.ts +17 -5
- package/dist/server/app-page-route-wiring.js +55 -33
- package/dist/server/app-page-rsc-render-status.d.ts +48 -0
- package/dist/server/app-page-rsc-render-status.js +54 -0
- package/dist/server/app-page-search-params-observation.js +1 -1
- package/dist/server/app-page-stream.d.ts +15 -8
- package/dist/server/app-page-stream.js +7 -1
- package/dist/server/app-page-tracing.js +2 -1
- package/dist/server/app-pages-bridge.js +3 -2
- package/dist/server/app-render-abort-error.d.ts +3 -0
- package/dist/server/app-render-abort-error.js +8 -0
- package/dist/server/app-request-stage-dispatch.js +1 -1
- package/dist/server/app-request-stage-independent-entry.js +8 -11
- package/dist/server/app-response-header-provenance.d.ts +2 -0
- package/dist/server/app-response-header-provenance.js +10 -4
- package/dist/server/app-route-handler-cache.d.ts +2 -1
- package/dist/server/app-route-handler-cache.js +11 -7
- package/dist/server/app-route-handler-dispatch.js +11 -4
- package/dist/server/app-route-handler-execution.d.ts +9 -1
- package/dist/server/app-route-handler-execution.js +28 -13
- package/dist/server/app-route-handler-policy.js +2 -2
- package/dist/server/app-route-handler-response.d.ts +1 -1
- package/dist/server/app-route-handler-response.js +14 -5
- package/dist/server/app-router-entry.d.ts +2 -1
- package/dist/server/app-router-entry.js +8 -12
- package/dist/server/app-rsc-errors.d.ts +0 -1
- package/dist/server/app-rsc-errors.js +2 -6
- package/dist/server/app-rsc-handler.d.ts +5 -0
- package/dist/server/app-rsc-handler.js +229 -102
- package/dist/server/app-rsc-request-normalization.d.ts +4 -2
- package/dist/server/app-rsc-request-normalization.js +7 -4
- package/dist/server/app-rsc-response-finalizer.js +4 -1
- package/dist/server/app-rsc-response-stage.d.ts +1 -1
- package/dist/server/app-rsc-response-stage.js +6 -4
- package/dist/server/app-rsc-route-matching.d.ts +9 -1
- package/dist/server/app-rsc-route-matching.js +37 -20
- package/dist/server/app-server-action-execution.d.ts +2 -1
- package/dist/server/app-server-action-execution.js +1 -1
- package/dist/server/app-ssr-entry.d.ts +3 -2
- package/dist/server/app-ssr-entry.js +9 -7
- package/dist/server/app-ssr-search-params-gate.js +1 -1
- package/dist/server/app-ssr-stream.d.ts +6 -1
- package/dist/server/app-ssr-stream.js +35 -16
- package/dist/server/app-worker-stages.d.ts +2 -2
- package/dist/server/app-worker-stages.js +3 -3
- package/dist/server/cache-control.js +3 -11
- package/dist/server/cacheability-request.js +56 -52
- package/dist/server/config-headers.js +3 -1
- package/dist/server/dev-server.js +23 -5
- package/dist/server/headers.d.ts +16 -0
- package/dist/server/headers.js +19 -1
- package/dist/server/http-error-responses.js +1 -0
- package/dist/server/image-optimization.d.ts +16 -0
- package/dist/server/image-optimization.js +26 -6
- package/dist/server/isr-cache.d.ts +2 -0
- package/dist/server/isr-cache.js +8 -3
- package/dist/server/metadata-route-response.js +94 -37
- package/dist/server/middleware-matcher-pattern.js +8 -4
- package/dist/server/middleware-response-headers.js +2 -0
- package/dist/server/multi-stage.d.ts +8 -0
- package/dist/server/navigation-planner.js +1 -1
- package/dist/server/node-response-signal.d.ts +16 -0
- package/dist/server/node-response-signal.js +26 -0
- package/dist/server/open-redirect.d.ts +47 -0
- package/dist/server/open-redirect.js +74 -1
- package/dist/server/pages-api-route.js +8 -2
- package/dist/server/pages-asset-tags.d.ts +1 -0
- package/dist/server/pages-asset-tags.js +73 -22
- package/dist/server/pages-client-assets.d.ts +2 -0
- package/dist/server/pages-page-data.d.ts +6 -1
- package/dist/server/pages-page-data.js +71 -65
- package/dist/server/pages-page-handler.js +50 -15
- package/dist/server/pages-page-response.js +3 -1
- package/dist/server/pages-request-pipeline.d.ts +2 -1
- package/dist/server/pages-request-pipeline.js +20 -5
- package/dist/server/pages-request-stage-entry.js +14 -8
- package/dist/server/prerender-manifest.d.ts +6 -0
- package/dist/server/prerender-manifest.js +1 -1
- package/dist/server/prod-server.d.ts +8 -7
- package/dist/server/prod-server.js +152 -78
- package/dist/server/request-pipeline.d.ts +20 -8
- package/dist/server/request-pipeline.js +21 -7
- package/dist/server/response-compression.d.ts +43 -0
- package/dist/server/response-compression.js +111 -0
- package/dist/server/response-stage-cacheability.js +1 -1
- package/dist/server/seed-cache.js +10 -7
- package/dist/server/socket-error-backstop.d.ts +14 -0
- package/dist/server/socket-error-backstop.js +27 -4
- package/dist/server/worker-revalidation-context.d.ts +2 -1
- package/dist/server/worker-revalidation-context.js +1 -0
- package/dist/server/workers-tracing.d.ts +17 -0
- package/dist/server/workers-tracing.js +48 -8
- package/dist/shims/cache-adapter-instantiate.d.ts +50 -0
- package/dist/shims/cache-adapter-instantiate.js +118 -0
- package/dist/shims/cache-callable-runtime.d.ts +2 -40
- package/dist/shims/cache-callable-runtime.js +50 -168
- package/dist/shims/cache-flight-arguments.d.ts +22 -0
- package/dist/shims/cache-flight-arguments.js +56 -0
- package/dist/shims/cache-request-state.d.ts +18 -14
- package/dist/shims/cache-request-state.js +33 -21
- package/dist/shims/cache-runtime.d.ts +6 -19
- package/dist/shims/cache-runtime.js +168 -226
- package/dist/shims/cache.d.ts +3 -2
- package/dist/shims/cache.js +8 -5
- package/dist/shims/cacheability-classification.d.ts +8 -1
- package/dist/shims/cacheability-classification.js +2 -2
- package/dist/shims/cdn-cache.d.ts +10 -1
- package/dist/shims/cdn-cache.js +16 -9
- package/dist/shims/error-boundary-navigation.d.ts +7 -0
- package/dist/shims/error-boundary-navigation.js +19 -1
- package/dist/shims/error-boundary.d.ts +10 -10
- package/dist/shims/error-boundary.js +26 -7
- package/dist/shims/error.d.ts +4 -18
- package/dist/shims/error.js +17 -10
- package/dist/shims/error.react-server.d.ts +4 -6
- package/dist/shims/error.react-server.js +4 -1
- package/dist/shims/fetch-cache.d.ts +6 -0
- package/dist/shims/fetch-cache.js +23 -4
- package/dist/shims/form.js +1 -1
- package/dist/shims/headers.d.ts +19 -69
- package/dist/shims/headers.js +82 -183
- package/dist/shims/internal/app-page-props-cache-key.d.ts +5 -2
- package/dist/shims/internal/app-page-props-cache-key.js +24 -15
- package/dist/shims/internal/cache-context-accessor.d.ts +16 -0
- package/dist/shims/internal/cache-context-accessor.js +15 -0
- package/dist/shims/internal/headers-state.d.ts +73 -0
- package/dist/shims/internal/headers-state.js +157 -0
- package/dist/shims/metadata.js +3 -3
- package/dist/shims/navigation-errors.d.ts +6 -0
- package/dist/shims/navigation-errors.js +11 -1
- package/dist/shims/navigation.d.ts +7 -0
- package/dist/shims/navigation.js +16 -6
- package/dist/shims/request-context.d.ts +9 -0
- package/dist/shims/request-state-types.d.ts +2 -1
- package/dist/shims/root-params.js +1 -1
- package/dist/shims/server.js +52 -2
- package/dist/shims/thenable-params.d.ts +4 -0
- package/dist/shims/thenable-params.js +25 -3
- package/dist/shims/unified-request-context.d.ts +1 -1
- package/dist/shims/unified-request-context.js +1 -0
- package/dist/utils/encode-cache-tag.d.ts +1 -0
- package/dist/utils/encode-cache-tag.js +11 -1
- package/dist/utils/mdx-scan.d.ts +5 -0
- package/dist/utils/mdx-scan.js +8 -1
- package/dist/utils/regex-safety.d.ts +10 -0
- package/dist/utils/regex-safety.js +70 -18
- package/dist/utils/vite-cli-invocation.js +8 -1
- package/package.json +8 -4
- package/dist/server/metadata-route-cache-policy.d.ts +0 -5
- package/dist/server/metadata-route-cache-policy.js +0 -6
package/README.md
CHANGED
|
@@ -158,6 +158,42 @@ Environment variables: `PORT` (default `3000`), `HOST` (default `0.0.0.0`).
|
|
|
158
158
|
|
|
159
159
|
> **Note:** Next.js standalone uses `HOSTNAME` for the bind address, but vinext uses `HOST` to avoid collision with the system-set `HOSTNAME` variable on Linux. Update your deployment config accordingly.
|
|
160
160
|
|
|
161
|
+
#### Custom standalone entries
|
|
162
|
+
|
|
163
|
+
The generated `server.js` is a small wrapper around `startProdServer` from `vinext/server/prod-server`. To control where the server loads the build output from, write your own entry and call `startProdServer` directly. All options are optional:
|
|
164
|
+
|
|
165
|
+
| Option | Default | Description |
|
|
166
|
+
| ----------------- | ---------------------------------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
|
|
167
|
+
| `port` | `PORT` env var, otherwise `3000` | Port to listen on. |
|
|
168
|
+
| `host` | `"0.0.0.0"` | Address to bind to. Unlike the generated `server.js`, `startProdServer` doesn't read `HOST`, so pass `process.env.HOST` yourself if you need it. |
|
|
169
|
+
| `outDir` | `dist`, resolved against the current directory | Build output directory containing `client/` and `server/`. Relative paths resolve against the current directory. In standalone output, this is `dist/standalone/dist`. |
|
|
170
|
+
| `serverDir` | `<outDir>/server` | Directory containing the server bundles, manifests, and prerendered output. |
|
|
171
|
+
| `rscEntryPath` | `<serverDir>/index.js` | App Router server entry. If this file exists, the server runs in App Router mode. |
|
|
172
|
+
| `serverEntryPath` | `<serverDir>/entry.js` | Pages Router server entry. Used when there's no App Router entry. |
|
|
173
|
+
| `noCompression` | `false` | Disable response compression. |
|
|
174
|
+
|
|
175
|
+
`ProdServerOptions` also has `purpose` and `silent`, which vinext uses for its own build-time servers. Leave them unset. The returned promise resolves to `{ server, port }` once the server is listening.
|
|
176
|
+
|
|
177
|
+
**Compiled single-file binaries.** A `bun build --compile` binary can't use the generated `server.js`. Bun fixes `import.meta.dirname` when it compiles the binary, so `join(import.meta.dirname, "dist")` doesn't point at the directory the binary runs from. Depending on the Bun version, it points at the build machine's path or at Bun's embedded `/$bunfs/root`. Resolve `outDir` from the executable's location instead:
|
|
178
|
+
|
|
179
|
+
```js
|
|
180
|
+
// server-bin.mjs, in your project root
|
|
181
|
+
import path from "node:path";
|
|
182
|
+
import { startProdServer } from "vinext/server/prod-server";
|
|
183
|
+
|
|
184
|
+
await startProdServer({
|
|
185
|
+
port: Number.parseInt(process.env.PORT ?? "3000", 10),
|
|
186
|
+
host: process.env.HOST ?? "0.0.0.0",
|
|
187
|
+
outDir: path.join(path.dirname(process.execPath), "dist"),
|
|
188
|
+
});
|
|
189
|
+
```
|
|
190
|
+
|
|
191
|
+
```bash
|
|
192
|
+
bun build --compile --compile-autoload-package-json server-bin.mjs --outfile dist/standalone/server
|
|
193
|
+
```
|
|
194
|
+
|
|
195
|
+
Keep the entry outside `dist/standalone`: each build deletes and recreates that directory. Compile after `vite build`, then ship the whole `dist/standalone` directory, because the `server` binary needs the `dist/` and `node_modules/` directories next to it. The server bundles in `dist/server` still import their dependencies from `node_modules` at runtime. `--compile-autoload-package-json` lets the binary read package `exports` and `main` fields when it resolves them. Under plain Node, `process.execPath` is the Node binary, so use this entry only for compiled builds.
|
|
196
|
+
|
|
161
197
|
### Starting a new vinext project
|
|
162
198
|
|
|
163
199
|
Use `create-vinext-app` for new projects. It creates a TypeScript App Router project
|
|
@@ -792,7 +828,7 @@ their `env` binding lookups) are instantiated lazily on the first request.
|
|
|
792
828
|
|
|
793
829
|
Registration is wired into **every router and runtime** — App Router and Pages Router, on Cloudflare Workers as well as the Node.js server (`vinext start`) and dev. It self-guards (instantiated once per isolate) and is resilient: if an adapter can't initialize on a given runtime (e.g. a KV binding doesn't exist on the Node server), vinext logs a warning and falls back to the default handler instead of failing requests.
|
|
794
830
|
|
|
795
|
-
To write your own adapter, point a slot at any module by path
|
|
831
|
+
To write your own adapter, point a slot at any module by path. Its default export receives one `{ env, options }` argument at runtime and produces a data-cache `CacheHandler` (or a CDN adapter):
|
|
796
832
|
|
|
797
833
|
```ts
|
|
798
834
|
vinext({
|
|
@@ -805,6 +841,41 @@ vinext({
|
|
|
805
841
|
});
|
|
806
842
|
```
|
|
807
843
|
|
|
844
|
+
The default export can be a factory or a class:
|
|
845
|
+
|
|
846
|
+
```ts
|
|
847
|
+
// my-adapter.js: a factory
|
|
848
|
+
export default ({ env, options }) => ({
|
|
849
|
+
async get(key) {
|
|
850
|
+
/* … */
|
|
851
|
+
},
|
|
852
|
+
async set(key, data) {
|
|
853
|
+
/* … */
|
|
854
|
+
},
|
|
855
|
+
async revalidateTag(tags) {
|
|
856
|
+
/* … */
|
|
857
|
+
},
|
|
858
|
+
});
|
|
859
|
+
|
|
860
|
+
// my-adapter.js: or a class
|
|
861
|
+
export default class MyAdapter {
|
|
862
|
+
constructor({ env, options }) {
|
|
863
|
+
/* … */
|
|
864
|
+
}
|
|
865
|
+
async get(key) {
|
|
866
|
+
/* … */
|
|
867
|
+
}
|
|
868
|
+
async set(key, data) {
|
|
869
|
+
/* … */
|
|
870
|
+
}
|
|
871
|
+
async revalidateTag(tags) {
|
|
872
|
+
/* … */
|
|
873
|
+
}
|
|
874
|
+
}
|
|
875
|
+
```
|
|
876
|
+
|
|
877
|
+
vinext invokes class syntax with `new` and calls any other function, so existing factories keep plain-call semantics. A constructor that isn't class syntax (an ES5-compiled, bound, or Proxy-wrapped class) can't be told apart from a factory, so export a factory that constructs it: `export default (args) => new MyAdapter(args)`. The result must be the adapter itself, not a Promise. A data adapter implements `get`, `set`, and `revalidateTag`; a CDN adapter also implements `buildResponseHeaders` and sets `ownsBackgroundRevalidation` to a boolean. If the export isn't a function or the result is missing a member, vinext logs a warning naming the slot and what's wrong, then keeps the default handler.
|
|
878
|
+
|
|
808
879
|
## What's NOT supported (and won't be)
|
|
809
880
|
|
|
810
881
|
These are intentional exclusions. For things that are missing today but on the roadmap, see [Known gaps we're working on](#known-gaps-were-working-on) above.
|
package/THIRD_PARTY_LICENSES.md
CHANGED
|
@@ -23,3 +23,29 @@ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
|
23
23
|
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
24
24
|
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
25
25
|
SOFTWARE.
|
|
26
|
+
|
|
27
|
+
## dotenv (parser adapted from version 16.3.1)
|
|
28
|
+
|
|
29
|
+
Copyright (c) 2015, Scott Motte
|
|
30
|
+
All rights reserved.
|
|
31
|
+
|
|
32
|
+
Redistribution and use in source and binary forms, with or without
|
|
33
|
+
modification, are permitted provided that the following conditions are met:
|
|
34
|
+
|
|
35
|
+
- Redistributions of source code must retain the above copyright notice, this
|
|
36
|
+
list of conditions and the following disclaimer.
|
|
37
|
+
|
|
38
|
+
- Redistributions in binary form must reproduce the above copyright notice,
|
|
39
|
+
this list of conditions and the following disclaimer in the documentation
|
|
40
|
+
and/or other materials provided with the distribution.
|
|
41
|
+
|
|
42
|
+
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
|
43
|
+
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
|
44
|
+
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
|
45
|
+
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
|
|
46
|
+
FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
|
47
|
+
DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
|
48
|
+
SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
|
|
49
|
+
CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
|
|
50
|
+
OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
|
51
|
+
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import { AppRoute } from "../routing/app-route-graph.js";
|
|
2
|
+
//#region src/build/app-page-static-eligibility.d.ts
|
|
3
|
+
/**
|
|
4
|
+
* Whether Next.js classifies an App page route as static or SSG, read from its
|
|
5
|
+
* layout, page and parallel-slot sources with the helpers dispatch applies to
|
|
6
|
+
* the loaded modules. Only such a route has listed paths.
|
|
7
|
+
*
|
|
8
|
+
* An MDX source read without the MDX parser has unknown exports, so its route
|
|
9
|
+
* is "unreadable". Its paths are still listed: the built runtime reads the real
|
|
10
|
+
* exports and never stores a route that isn't static, while an unlisted path's
|
|
11
|
+
* render failure would be dropped instead of failing. But no probe renders an
|
|
12
|
+
* unreadable route's fallback, so it never certifies one.
|
|
13
|
+
*/
|
|
14
|
+
export declare function classifyAppPageRouteStaticEligibility(route: AppRoute, readMdxEsm: ((source: string) => string) | null): "eligible" | "ineligible" | "unreadable";
|
|
15
|
+
//#endregion
|
|
@@ -0,0 +1,82 @@
|
|
|
1
|
+
import { extractExportConstNumber, extractExportConstString, hasRuntimeExportedName } from "./report.js";
|
|
2
|
+
import { collectAppPageStaticGenerationRuntimes, hasAppPageGenerateStaticParamsAtLastDynamicSegment, isAppPageStaticEligible, isEdgeRuntime, resolveAppPageSegmentConfig, resolveAppPageStaticGenerationRuntime } from "../server/app-segment-config.js";
|
|
3
|
+
import fs from "node:fs";
|
|
4
|
+
//#region src/build/app-page-static-eligibility.ts
|
|
5
|
+
/**
|
|
6
|
+
* Whether Next.js classifies an App page route as static or SSG, read from its
|
|
7
|
+
* layout, page and parallel-slot sources with the helpers dispatch applies to
|
|
8
|
+
* the loaded modules. Only such a route has listed paths.
|
|
9
|
+
*
|
|
10
|
+
* An MDX source read without the MDX parser has unknown exports, so its route
|
|
11
|
+
* is "unreadable". Its paths are still listed: the built runtime reads the real
|
|
12
|
+
* exports and never stores a route that isn't static, while an unlisted path's
|
|
13
|
+
* render failure would be dropped instead of failing. But no probe renders an
|
|
14
|
+
* unreadable route's fallback, so it never certifies one.
|
|
15
|
+
*/
|
|
16
|
+
function classifyAppPageRouteStaticEligibility(route, readMdxEsm) {
|
|
17
|
+
let unreadable = false;
|
|
18
|
+
const readSegmentConfig = (filePath) => {
|
|
19
|
+
if (!filePath) return null;
|
|
20
|
+
let code = fs.readFileSync(filePath, "utf8");
|
|
21
|
+
if (filePath.toLowerCase().endsWith(".mdx")) {
|
|
22
|
+
let esm = null;
|
|
23
|
+
try {
|
|
24
|
+
esm = readMdxEsm?.(code) ?? null;
|
|
25
|
+
} catch {}
|
|
26
|
+
unreadable ||= esm === null;
|
|
27
|
+
code = esm ?? "";
|
|
28
|
+
}
|
|
29
|
+
const dynamic = extractExportConstString(code, "dynamic");
|
|
30
|
+
const revalidate = extractExportConstNumber(code, "revalidate");
|
|
31
|
+
const runtime = extractExportConstString(code, "runtime");
|
|
32
|
+
return {
|
|
33
|
+
...dynamic === null ? {} : { dynamic },
|
|
34
|
+
...hasRuntimeExportedName(code, "generateStaticParams") ? { generateStaticParams() {} } : {},
|
|
35
|
+
...revalidate === null ? {} : { revalidate },
|
|
36
|
+
...runtime === null ? {} : { runtime }
|
|
37
|
+
};
|
|
38
|
+
};
|
|
39
|
+
const layouts = route.layouts.map(readSegmentConfig);
|
|
40
|
+
const page = readSegmentConfig(route.pagePath);
|
|
41
|
+
const parallelBranches = route.parallelSlots.map((slot) => ({
|
|
42
|
+
configLayouts: (slot.configLayoutPaths ?? []).map(readSegmentConfig),
|
|
43
|
+
configLayoutTreePositions: slot.configLayoutTreePositions ?? [],
|
|
44
|
+
isDefault: !slot.pagePath,
|
|
45
|
+
layout: readSegmentConfig(slot.layoutPath),
|
|
46
|
+
name: slot.name,
|
|
47
|
+
ownerTreePosition: slot.ownerTreePosition ?? null,
|
|
48
|
+
page: readSegmentConfig(slot.pagePath ?? slot.defaultPath),
|
|
49
|
+
routeSegments: slot.routeSegments
|
|
50
|
+
}));
|
|
51
|
+
if (unreadable) return "unreadable";
|
|
52
|
+
const segmentConfig = resolveAppPageSegmentConfig({
|
|
53
|
+
layouts,
|
|
54
|
+
layoutTreePositions: route.layoutTreePositions,
|
|
55
|
+
page,
|
|
56
|
+
parallelBranches,
|
|
57
|
+
routeSegments: route.routeSegments
|
|
58
|
+
});
|
|
59
|
+
return isAppPageStaticEligible({
|
|
60
|
+
dynamicConfig: segmentConfig.dynamicConfig,
|
|
61
|
+
hasGenerateStaticParams: hasAppPageGenerateStaticParamsAtLastDynamicSegment({
|
|
62
|
+
childrenSlot: route.childrenSlot ?? null,
|
|
63
|
+
layouts,
|
|
64
|
+
layoutTreePositions: route.layoutTreePositions,
|
|
65
|
+
page,
|
|
66
|
+
parallelBranches,
|
|
67
|
+
routeSegments: route.routeSegments
|
|
68
|
+
}),
|
|
69
|
+
isDynamicRoute: route.isDynamic,
|
|
70
|
+
isStaticGenerationEdgeRuntime: isEdgeRuntime(resolveAppPageStaticGenerationRuntime(collectAppPageStaticGenerationRuntimes({
|
|
71
|
+
childrenSlot: route.childrenSlot ?? null,
|
|
72
|
+
layouts,
|
|
73
|
+
layoutTreePositions: route.layoutTreePositions,
|
|
74
|
+
page,
|
|
75
|
+
parallelBranches,
|
|
76
|
+
routeSegments: route.routeSegments
|
|
77
|
+
}))),
|
|
78
|
+
revalidateSeconds: segmentConfig.revalidateSeconds
|
|
79
|
+
}) ? "eligible" : "ineligible";
|
|
80
|
+
}
|
|
81
|
+
//#endregion
|
|
82
|
+
export { classifyAppPageRouteStaticEligibility };
|
package/dist/build/lifecycle.js
CHANGED
|
@@ -141,16 +141,6 @@ async function finalizeBuild(builder, context) {
|
|
|
141
141
|
__VINEXT_SHARED_RSC_COMPATIBILITY_ID: context.rscCompatibilityId
|
|
142
142
|
}, () => runWithPreviewBuildCredentials(() => buildHybridPagesBundle(builder, context), context.previewBuildCredentials));
|
|
143
143
|
if (context.deferPostBuild) return;
|
|
144
|
-
if (context.nextConfig.output === "standalone") {
|
|
145
|
-
const { emitStandaloneOutput } = await import("./standalone.js");
|
|
146
|
-
const standalone = emitStandaloneOutput({
|
|
147
|
-
root: context.root,
|
|
148
|
-
outDir: path.resolve(context.root, "dist")
|
|
149
|
-
});
|
|
150
|
-
console.log(` Generated standalone output in ${path.relative(context.root, standalone.standaloneDir)}/`);
|
|
151
|
-
console.log(" Start it with: node dist/standalone/server.js\n");
|
|
152
|
-
return;
|
|
153
|
-
}
|
|
154
144
|
const prerenderDecision = resolveVinextPrerenderDecision({
|
|
155
145
|
prerenderAllFlag: context.prerenderAll,
|
|
156
146
|
vinextPrerenderConfig: context.prerenderConfig,
|
|
@@ -187,6 +177,16 @@ async function finalizeBuild(builder, context) {
|
|
|
187
177
|
routeRootConfig: buildOutput
|
|
188
178
|
});
|
|
189
179
|
}
|
|
180
|
+
if (context.nextConfig.output === "standalone") {
|
|
181
|
+
const { emitStandaloneOutput } = await import("./standalone.js");
|
|
182
|
+
const standalone = emitStandaloneOutput({
|
|
183
|
+
root: context.root,
|
|
184
|
+
outDir: path.resolve(context.root, "dist")
|
|
185
|
+
});
|
|
186
|
+
console.log(` Generated standalone output in ${path.relative(context.root, standalone.standaloneDir)}/`);
|
|
187
|
+
console.log(" Start it with: node dist/standalone/server.js\n");
|
|
188
|
+
return;
|
|
189
|
+
}
|
|
190
190
|
const { printBuildReport } = await import("./report.js");
|
|
191
191
|
await printBuildReport({
|
|
192
192
|
root: context.root,
|
|
@@ -1,9 +1,14 @@
|
|
|
1
1
|
import path from "../deps/.pnpm/pathslash@0.1.0/deps/pathslash/dist/index.js";
|
|
2
|
+
import { getSharedChunkFiles } from "../server/pages-asset-tags.js";
|
|
2
3
|
import fs from "node:fs";
|
|
3
4
|
//#region src/build/pages-client-assets-module.ts
|
|
4
5
|
const PAGES_CLIENT_ASSETS_MODULE = "vinext-client-assets.js";
|
|
5
6
|
function buildPagesClientAssetsModule(assets) {
|
|
6
|
-
|
|
7
|
+
const prepared = assets.ssrManifest ? {
|
|
8
|
+
...assets,
|
|
9
|
+
sharedChunks: getSharedChunkFiles(assets.ssrManifest)
|
|
10
|
+
} : assets;
|
|
11
|
+
return `export default ${JSON.stringify(prepared)};\n`;
|
|
7
12
|
}
|
|
8
13
|
function writePagesClientAssetsModuleIfMissing(outputDir, moduleSource) {
|
|
9
14
|
const outputPath = path.join(outputDir, PAGES_CLIENT_ASSETS_MODULE);
|
|
@@ -3,9 +3,9 @@ import { ASSET_PREFIX_URL_DIR } from "../utils/asset-prefix.js";
|
|
|
3
3
|
import { isPrecompressedVariantBeneficial } from "../utils/precompressed-variant.js";
|
|
4
4
|
import fsp from "node:fs/promises";
|
|
5
5
|
import { randomUUID } from "node:crypto";
|
|
6
|
-
import { promisify } from "node:util";
|
|
7
6
|
import os from "node:os";
|
|
8
7
|
import zlib from "node:zlib";
|
|
8
|
+
import { promisify } from "node:util";
|
|
9
9
|
//#region src/build/precompress.ts
|
|
10
10
|
/**
|
|
11
11
|
* Build-time precompression for hashed static assets.
|
|
@@ -10,18 +10,19 @@ import { apiRouter, matchRoute, pagesRouter } from "../routing/pages-router.js";
|
|
|
10
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
|
-
import { classifyAppRoute, classifyAppRouteHandler, classifyPagesRoute,
|
|
13
|
+
import { classifyAppRoute, classifyAppRouteHandler, classifyPagesRoute, extractExportConstString, extractMiddlewareMatcherConfig, getAppRouteRenderEntryPath } from "./report.js";
|
|
14
14
|
import { normalizeStaticPathname, normalizeStaticPathsEntry } from "../routing/route-pattern.js";
|
|
15
15
|
import { buildPagesDataHref } from "../shims/internal/pages-data-url.js";
|
|
16
16
|
import { normalizePathTrailingSlash } from "../shims/url-utils.js";
|
|
17
|
+
import { resolveAppPageDynamicConfig } from "../server/app-segment-config.js";
|
|
18
|
+
import { classifyAppPageRouteStaticEligibility } from "./app-page-static-eligibility.js";
|
|
17
19
|
import { pagesRouteHasPriorityOverAppRoute } from "../server/hybrid-route-priority.js";
|
|
18
20
|
import { readPrerenderSecret } from "./server-manifest.js";
|
|
19
21
|
import { loadMdxEsmReader } from "../utils/mdx-scan.js";
|
|
20
22
|
import { startProdServer } from "../server/prod-server.js";
|
|
21
23
|
import { enterPrerenderPhase } from "./prerender-phase.js";
|
|
22
|
-
import { buildUrlFromParams, layoutOnlyParamSets, resolveParentParams, routeStaticParamSets, validateDiscoveredParams } from "./prerender.js";
|
|
23
|
-
import {
|
|
24
|
-
import { resolveBuiltRscEntryPath } from "./server-entry.js";
|
|
24
|
+
import { buildUrlFromParams, layoutOnlyParamSets, localizePagesPath, resolveParentParams, routeStaticParamSets, validateDiscoveredParams } from "./prerender.js";
|
|
25
|
+
import { resolveBuiltPagesEntryPath, resolveBuiltRscEntryPath } from "./server-entry.js";
|
|
25
26
|
import fs from "node:fs";
|
|
26
27
|
//#region src/build/prerender-paths.ts
|
|
27
28
|
const PRERENDER_PATH_DISCOVERY_ENV = "__VINEXT_PRERENDER_PATH_DISCOVERY";
|
|
@@ -325,10 +326,6 @@ async function resolvePagesWarmRouteMetadata(options) {
|
|
|
325
326
|
routePatterns
|
|
326
327
|
};
|
|
327
328
|
}
|
|
328
|
-
function localizePagesPath(pathname, locale, i18n) {
|
|
329
|
-
if (!i18n || !locale || locale === i18n.defaultLocale) return pathname;
|
|
330
|
-
return pathname === "/" ? `/${locale}` : `/${locale}${pathname}`;
|
|
331
|
-
}
|
|
332
329
|
/**
|
|
333
330
|
* Next.js data URLs always carry the locale segment, including the default
|
|
334
331
|
* locale that is omitted from the corresponding public HTML pathname.
|
|
@@ -355,82 +352,6 @@ function extractPagesStaticPathLocale(url, i18n) {
|
|
|
355
352
|
url: `${rest || "/"}${query}`
|
|
356
353
|
};
|
|
357
354
|
}
|
|
358
|
-
/**
|
|
359
|
-
* Whether Next.js classifies an App page route as static or SSG, read from its
|
|
360
|
-
* layout, page and parallel-slot sources with the helpers dispatch applies to
|
|
361
|
-
* the loaded modules. Only such a route has listed paths.
|
|
362
|
-
*
|
|
363
|
-
* An MDX source read without the MDX parser has unknown exports, so its route
|
|
364
|
-
* is "unreadable". Its paths are still listed: the built runtime reads the real
|
|
365
|
-
* exports and never stores a route that isn't static, while an unlisted path's
|
|
366
|
-
* render failure would be dropped instead of failing. But no probe renders an
|
|
367
|
-
* unreadable route's fallback, so it never certifies one.
|
|
368
|
-
*/
|
|
369
|
-
function classifyAppPageRouteStaticEligibility(route, readMdxEsm) {
|
|
370
|
-
let unreadable = false;
|
|
371
|
-
const readSegmentConfig = (filePath) => {
|
|
372
|
-
if (!filePath) return null;
|
|
373
|
-
let code = fs.readFileSync(filePath, "utf8");
|
|
374
|
-
if (filePath.toLowerCase().endsWith(".mdx")) {
|
|
375
|
-
let esm = null;
|
|
376
|
-
try {
|
|
377
|
-
esm = readMdxEsm?.(code) ?? null;
|
|
378
|
-
} catch {}
|
|
379
|
-
unreadable ||= esm === null;
|
|
380
|
-
code = esm ?? "";
|
|
381
|
-
}
|
|
382
|
-
const dynamic = extractExportConstString(code, "dynamic");
|
|
383
|
-
const revalidate = extractExportConstNumber(code, "revalidate");
|
|
384
|
-
const runtime = extractExportConstString(code, "runtime");
|
|
385
|
-
return {
|
|
386
|
-
...dynamic === null ? {} : { dynamic },
|
|
387
|
-
...hasRuntimeExportedName(code, "generateStaticParams") ? { generateStaticParams() {} } : {},
|
|
388
|
-
...revalidate === null ? {} : { revalidate },
|
|
389
|
-
...runtime === null ? {} : { runtime }
|
|
390
|
-
};
|
|
391
|
-
};
|
|
392
|
-
const layouts = route.layouts.map(readSegmentConfig);
|
|
393
|
-
const page = readSegmentConfig(route.pagePath);
|
|
394
|
-
const parallelBranches = route.parallelSlots.map((slot) => ({
|
|
395
|
-
configLayouts: (slot.configLayoutPaths ?? []).map(readSegmentConfig),
|
|
396
|
-
configLayoutTreePositions: slot.configLayoutTreePositions ?? [],
|
|
397
|
-
isDefault: !slot.pagePath,
|
|
398
|
-
layout: readSegmentConfig(slot.layoutPath),
|
|
399
|
-
name: slot.name,
|
|
400
|
-
ownerTreePosition: slot.ownerTreePosition ?? null,
|
|
401
|
-
page: readSegmentConfig(slot.pagePath ?? slot.defaultPath),
|
|
402
|
-
routeSegments: slot.routeSegments
|
|
403
|
-
}));
|
|
404
|
-
if (unreadable) return "unreadable";
|
|
405
|
-
const segmentConfig = resolveAppPageSegmentConfig({
|
|
406
|
-
layouts,
|
|
407
|
-
layoutTreePositions: route.layoutTreePositions,
|
|
408
|
-
page,
|
|
409
|
-
parallelBranches,
|
|
410
|
-
routeSegments: route.routeSegments
|
|
411
|
-
});
|
|
412
|
-
return isAppPageStaticEligible({
|
|
413
|
-
dynamicConfig: segmentConfig.dynamicConfig,
|
|
414
|
-
hasGenerateStaticParams: hasAppPageGenerateStaticParamsAtLastDynamicSegment({
|
|
415
|
-
childrenSlot: route.childrenSlot ?? null,
|
|
416
|
-
layouts,
|
|
417
|
-
layoutTreePositions: route.layoutTreePositions,
|
|
418
|
-
page,
|
|
419
|
-
parallelBranches,
|
|
420
|
-
routeSegments: route.routeSegments
|
|
421
|
-
}),
|
|
422
|
-
isDynamicRoute: route.isDynamic,
|
|
423
|
-
isStaticGenerationEdgeRuntime: isEdgeRuntime(resolveAppPageStaticGenerationRuntime(collectAppPageStaticGenerationRuntimes({
|
|
424
|
-
childrenSlot: route.childrenSlot ?? null,
|
|
425
|
-
layouts,
|
|
426
|
-
layoutTreePositions: route.layoutTreePositions,
|
|
427
|
-
page,
|
|
428
|
-
parallelBranches,
|
|
429
|
-
routeSegments: route.routeSegments
|
|
430
|
-
}))),
|
|
431
|
-
revalidateSeconds: segmentConfig.revalidateSeconds
|
|
432
|
-
}) ? "eligible" : "ineligible";
|
|
433
|
-
}
|
|
434
355
|
/** Keys a path an App page route lists by the route and the pathname together. */
|
|
435
356
|
function appPageListingKey(routePattern, pathname) {
|
|
436
357
|
return `${routePattern}\0${pathname}`;
|
|
@@ -795,7 +716,7 @@ async function discoverPrerenderPathManifest(options) {
|
|
|
795
716
|
const rscBundlePath = options.rscBundlePath ?? defaultRscBundlePath;
|
|
796
717
|
const relativeRscEntryPath = path.relative(configuredRscServerDir, rscBundlePath);
|
|
797
718
|
const rscServerDir = !relativeRscEntryPath.startsWith("../") && !path.isAbsolute(relativeRscEntryPath) ? configuredRscServerDir : path.dirname(rscBundlePath);
|
|
798
|
-
const pagesBundlePath = options.pagesBundlePath ?? path.
|
|
719
|
+
const pagesBundlePath = options.pagesBundlePath ?? resolveBuiltPagesEntryPath(path.resolve(root, options.routeRootConfig?.ssrOutDir ?? path.join("dist", "server")));
|
|
799
720
|
const bundleServerDir = fs.existsSync(rscBundlePath) ? rscServerDir : path.dirname(pagesBundlePath);
|
|
800
721
|
const manifestDir = path.join(root, "dist", "server");
|
|
801
722
|
const config = options.nextConfig ? { ...options.nextConfig } : { ...await resolveNextConfig(await loadNextConfig(root, PHASE_PRODUCTION_BUILD), root) };
|
|
@@ -30,8 +30,14 @@ export type PrerenderRouteResult = {
|
|
|
30
30
|
router: "app" | "pages" | "metadata";
|
|
31
31
|
/** Response headers that must be replayed with the prerendered artifact. */
|
|
32
32
|
headers?: Record<string, string | string[]>;
|
|
33
|
-
/** Original HTTP status for prerendered
|
|
33
|
+
/** Original HTTP status for prerendered route responses. */
|
|
34
34
|
responseStatus?: number;
|
|
35
|
+
/** Pages source returned notFound, distinct from the custom 404 document. */
|
|
36
|
+
notFound?: true;
|
|
37
|
+
/** Original Pages redirect props, including client navigation semantics. */
|
|
38
|
+
redirectProps?: object;
|
|
39
|
+
/** Pages locale rendered for this public pathname. */
|
|
40
|
+
locale?: string;
|
|
35
41
|
/** Cache tags collected while rendering this route. */
|
|
36
42
|
tags?: string[];
|
|
37
43
|
/** Raw app-tree segments used to derive App Route implicit tags. */
|
|
@@ -234,6 +240,7 @@ export declare function routeStaticParamSets(route: Pick<AppRoute, "pattern">, p
|
|
|
234
240
|
* sets still go through routeStaticParamSets.
|
|
235
241
|
*/
|
|
236
242
|
export declare function layoutOnlyParamSets(route: Pick<AppRoute, "params" | "pattern">, parentParamSets: Record<string, string | string[]>[]): Record<string, string | string[]>[] | null;
|
|
243
|
+
export declare function localizePagesPath(pathname: string, locale: string | undefined, i18n: ResolvedNextConfig["i18n"]): string;
|
|
237
244
|
/**
|
|
238
245
|
* Run the prerender phase for Pages Router.
|
|
239
246
|
*
|