mirror of
https://github.com/cloudflare/vinext.git
synced 2026-09-14 19:04:59 +08:00
vinext@0.2.1
3 Commits
| Author | SHA1 | Message | Date | |
|---|---|---|---|---|
|
|
735d9dad77 |
fix(build): define process.env.NEXT_RUNTIME for server bundles (#1880)
* fix(build): define process.env.NEXT_RUNTIME for server bundles (#1365)
Next.js stamps each route bundle with a compile-time
`process.env.NEXT_RUNTIME` constant ('nodejs' or 'edge' depending on
the route's runtime setting). Vinext was not defining this constant,
so `process.env.NEXT_RUNTIME` resolved to `undefined` at runtime.
User-land code that reads `process.env.NEXT_RUNTIME` (including the
Next.js deploy test fixture `app/path-prefix.js`) would then produce
`'/undefined'` instead of `'/nodejs'`, causing `after()` callbacks
that call `revalidatePath()` to invalidate the wrong cache key. The
ISR page was never revalidated, and the timestamp-change assertion in
`next-after-app-deploy/index.test.ts` always failed.
Fix: inject `process.env.NEXT_RUNTIME = 'nodejs'` into all server
environments (rsc, ssr, custom worker envs) via the existing
`configEnvironment` hook. Client bundles are excluded by the existing
`if (name === "client") return null` guard. Vinext compiles a single
RSC bundle covering all routes, so 'nodejs' is the correct and only
applicable value — it matches both the Workers Node.js compatibility
layer and the `vinext start` Node.js HTTP server.
Fixes #1365
* Fix correct but breaks two tests
Co-authored-by: james-elicx <james-elicx@users.noreply.github.com>
* fix(build): reconcile NEXT_RUNTIME tests and add client '' parity (#1365)
Addresses ask-bonk blocking review findings on #1880:
1. Restore `process.env.NEXT_RUNTIME = 'nodejs'` for server environments
(removed by bot commit
|
||
|
|
9596b72495 |
fix(pages-router): pass revalidateReason "on-demand" to gsp/gssp (#1462) (#1856)
* fix(pages-router): pass revalidateReason "on-demand" to getStaticProps (#1462) Implements res.revalidate() for Pages Router API routes and wires the on-demand revalidation trigger through to getStaticProps/getServerSideProps context as revalidateReason: "on-demand". res.revalidate(urlPath) issues an internal HEAD request to the target path carrying the x-prerender-revalidate header (mirroring Next.js's api-resolver). The Pages render path (dev-server and prod pages-page-data) detects that header, bypasses the fresh/stale cache-hit short-circuits, and regenerates the entry synchronously with reason "on-demand". The build and stale reasons already worked; this finishes the on-demand case. Closes #1462 * fix(pages-router): authenticate on-demand revalidation with a secret (#1462) The on-demand `revalidateReason` detection treated `x-prerender-revalidate` as an unauthenticated presence check and sent the literal value "1". Any external client could send `x-prerender-revalidate: 1` to force synchronous regeneration of any ISR page, bypassing the fresh/stale cache short-circuits — a cache-stampede/DoS vector. Mirror Next.js's `checkIsOnDemandRevalidate`: a request is only treated as on-demand revalidation when the `x-prerender-revalidate` header value EQUALS a secret (the vinext analog of `previewModeId`). Introduce a per-process revalidate secret (`getRevalidateSecret`, 256-bit random hex via Web Crypto) that `res.revalidate()` attaches to its internal loopback request, and a constant-time `isOnDemandRevalidateRequest` equality check on the receiving dev-server and Pages page handler. Header presence alone is never honored. Also fix the test's HTML-reason extraction to avoid CodeQL's incomplete-sanitization / bad-HTML-regex findings, and add a negative test asserting forged `x-prerender-revalidate` values ("1", "", a guess) are rejected while the real secret is accepted. * refactor(pages-router): share res.revalidate() impl; support unstable_onlyGenerated (#1462) Address non-blocking bonk review findings: - Extract the two near-identical `res.revalidate()` implementations (`api-handler.ts`, `pages-node-compat.ts`) into a shared `performOnDemandRevalidate` helper so the secret wiring and success detection cannot drift between dev and prod. - Align success detection with Next.js's api-resolver: accept `x-nextjs-cache: REVALIDATED`, status 200, or a 404 when the caller passed `unstable_onlyGenerated`. Add `unstable_onlyGenerated` support (`x-prerender-revalidate-if-generated` header). * docs(pages-router): note x-nextjs-cache REVALIDATED branch is parity-only (#1462) * fix(pages-router): make on-demand revalidate secret build-time (shared across isolates) The on-demand ISR revalidation secret was a per-process random value. On Cloudflare Workers, res.revalidate()'s loopback fetch() can land on a different isolate than the sender, so a per-process secret mismatches across isolates and false-rejects legitimate revalidations. Mirror Next.js's previewModeId: generate one 256-bit secret at build time (in the vinext build CLI, once per build, shared across plugin instances like __VINEXT_SHARED_BUILD_ID) and bake it SERVER-ONLY into every server bundle via a Vite define (__VINEXT_REVALIDATE_SECRET). It is byte-for-byte identical in every isolate and never reaches the client bundle. getRevalidateSecret() reads the baked constant at runtime and falls back to a process-shared random secret in dev (single-process, no regression). Also persist revalidateSecret in vinext-server.json for diagnostics/tooling parity with prerenderSecret. Constant-time safeEqual validation and reject-arrays/empty/absent behavior are unchanged. Refs #1462 * test(pages-router): cover server-only revalidate secret; drop dead manifest reader Address ask-bonk review of the build-time revalidate secret: - Add tests pinning the security-critical invariant that the __VINEXT_REVALIDATE_SECRET define is baked into server environments (rsc/ssr) but NEVER into the client bundle (the client env returns null outright). A leak would ship the secret to every browser and re-open the cache-stampede vector the equality check prevents. Also harden the existing "no-ops when defineServer unset" test to explicitly clear the env var instead of relying on it happening to be unset. - Drop the unused readRevalidateSecret export and the orphaned revalidateSecret manifest field — the runtime authenticates against the baked define (both Workers isolates and the Node prod-server run the bundle), so the on-disk copy had no consumer (knip-flagged dead code). - Hoist the client early-return in vinext:compiler-define-server so the server-only guarantee is structural (removes the redundant name check), and reword the dev-fallback comments ("absent unless set during vinext build"). Refs #1462 |
||
|
|
34c8669182 |
fix(config): implement compiler.define / compiler.defineServer (#1638)
* feat(config): implement compiler.define and compiler.defineServer (#1496) Forward `compiler.define` to Vite's top-level `define` (applies to both client and server bundles) and `compiler.defineServer` to non-client environments only via a `configEnvironment` hook, matching Next.js Webpack `DefinePlugin` semantics. Values are JSON-stringified at config resolution time so they slot directly into Vite's substitution format. Refs Next.js: packages/next/src/build/define-env.ts. Fixes #1496 * fix(config): reject compiler.define keys that collide with built-ins Mirrors Next.js (`packages/next/src/build/define-env.ts`) — throw when a user-provided `compiler.define` or `compiler.defineServer` key would silently overwrite an internal define (e.g. `process.env.NODE_ENV`, `__NEXT_*`, `__VINEXT_*`) or when `define` and `defineServer` define the same key. Without this, a misconfigured project would produce subtly wrong output instead of failing fast. Addresses /bigbonk review on #1638. |