Commit Graph

1582 Commits

Author SHA1 Message Date
github-actions[bot] 4fad98a20e chore: version packages (beta) (#2499)
Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
@vinext/cloudflare@1.0.0-beta.0 create-vinext-app@1.0.0-beta.0 vinext@1.0.0-beta.0
2026-07-04 16:55:33 +00:00
James Anderson ed0e343d05 feat(init): mark CDN warmup flag experimental (#2533)
* feat(init): mark CDN warmup flag experimental

* chore(init): tweak experimental prewarm prompt

* chore(init): default experimental prewarm to no
2026-07-04 16:50:59 +00:00
James Anderson 201f423677 fix(init): use built Wrangler config for deploy script (#2532) 2026-07-04 17:40:33 +01:00
James Anderson f114c07d59 chore(release): reclassify prerender KV population as minor (#2530)
* chore(release): reclassify prerender KV population

* chore: format changeset override
2026-07-04 17:11:20 +01:00
James Anderson eba70463d4 feat(cloudflare): warm prerendered paths before deploy (#2481)
* feat(cloudflare): warm prerendered paths before deploy

* fix(cloudflare): warm production CDN for uploaded versions

* fix(cloudflare): resolve Worker names for CDN warmup

* fix(cloudflare): harden CDN warmup diagnostics

* fix(cloudflare): harden CDN warmup deploy flow

* fix(cloudflare): clarify CDN warmup trigger failures

* feat(cloudflare): warm cdn from build path manifest

* fix(cloudflare): emit warm paths for skip-build deploys

* fix(cloudflare): avoid stale skip-build path manifests

* test(cloudflare): lock skip-build prerender manifest gate

* fix(cloudflare): warm fallback deploy URL from triggers

* fix(cloudflare): clarify CDN warmup deploy logs

* feat(init): offer CDN warmup deploy script

* update wrangler configs

* fix(init): default CDN warmup to yes

* fix(cloudflare): explain first warm deploy failure

* fix(cloudflare): keep deploy errors concise

* fix(init): make generated home page cacheable
2026-07-04 16:09:55 +00:00
James Anderson 454dfbdf6b fix(cloudflare): populate kv cache from prerendered routes (#2509)
* fix(cloudflare): populate kv cache from prerendered routes

* fix(cloudflare): harden prerender kv population

* fix(cloudflare): match runtime app cache keys

* fix(cloudflare): clean prerender kv checks

* fix(cloudflare): align zero revalidate kv entries

* fix(cloudflare): tighten prerender kv deploy seeding

* fix(cloudflare): align toml env deploy parsing

* fix(cloudflare): cover toml deploy domain parsing

* fix(cloudflare): accept indented toml deploy fields

* fix(cloudflare): align json env domain precedence

* fix(cloudflare): upload prerender cache through wrangler

* fix(cloudflare): scope prerender kv upload to deploy
2026-07-04 15:52:01 +01:00
James Anderson 078073d75c fix(cloudflare): stream deploy logs (#2528) 2026-07-04 15:39:42 +01:00
James Anderson f22c962af8 refactor(cloudflare)!: remove vinext package coupling (#2527)
* refactor(cloudflare)!: remove vinext package coupling

* Review: PR #2527 breaks a test

Co-authored-by: james-elicx <james-elicx@users.noreply.github.com>

* test(cache): remove CDN auto-detection expectations

---------

Co-authored-by: ask-bonk[bot] <ask-bonk[bot]@users.noreply.github.com>
Co-authored-by: james-elicx <james-elicx@users.noreply.github.com>
2026-07-04 15:29:45 +01:00
James Anderson 282698a77f fix(app-router): stop varying RSC responses by Accept (#2526) 2026-07-04 14:14:10 +00:00
Cameron f7507ce238 perf(build): filter virtual module hooks (#2519)
* perf(build): filter virtual module hooks

Move several virtual-module resolveId/load hooks to Vite's object hook form with native id filters.

This lets Vite/Rolldown skip invoking vinext JavaScript handlers for unrelated module ids during dev and build module graph walks, reducing repeated string comparisons on the hot plugin hook path. The filtered hooks now only run for vinext virtual modules, instrumentation client injection, and the React canary shim ids they can actually handle.

* perf(build): anchor react canary load filter

Tighten the React canary virtual module load filter to match only the resolved null-byte-prefixed id.

I also checked exact string filters for other resolved virtual load ids, but Vite's native string filter skipped the instrumentation-client virtual module in the focused test path. Keep those null-byte virtual ids on regex filters for now.
2026-07-04 14:53:58 +01:00
James Anderson c47c74a919 docs: update vinext project status (#2525) 2026-07-04 13:46:10 +00:00
James Anderson bfeaaa7dc5 docs(web): highlight Workers Cache for ISR (#2522)
* docs(web): highlight Workers Cache for ISR

* docs(web): refresh homepage metrics

* docs(web): refine client bundle metric
2026-07-04 13:57:49 +01:00
James Anderson 5825c6807f fix(app-router): preserve client state during action revalidation (#2517)
* fix(app-router): preserve client state during action revalidation

* test(app-router): pin loading boundary to slot entry

* test(app-router): deploy action revalidation repro
2026-07-04 11:08:54 +01:00
Steve Faulkner 54497d42e7 fix: dev-server polish batch — HTML charset, client global polyfill, trailingSlash image endpoint (#2512)
* fix(pages): send charset=utf-8 on HTML Content-Type

Next.js serves every HTML response (SSR and prerendered) with
`Content-Type: text/html; charset=utf-8`, but vinext's Pages Router
paths sent a bare `text/html`. Without the header charset — and without
an early <meta charset> in the page — Chromium falls back to
windows-1252, so non-ASCII content renders as mojibake (e.g. nbsp as
'Â ') and the resulting DOM diverges from the hydrated tree, triggering
the full-screen hydration error overlay in dev. Reproduced against
nextjs-notion-starter-kit; baseline `next dev`/`next start` both send
the charset.

Append `; charset=utf-8` on every Pages Router HTML producer (the App
Router paths already send it):

- pages-page-response.ts — page render response headers + gSSP header
  merge
- dev-server.ts — streaming SSR, ISR HIT/STALE, and static-HTML dev
  responses
- pages-page-data.ts — ISR cache HIT/STALE responses in prod
- pages-request-pipeline.ts — the `defaultContentType` a buffering
  adapter applies when a render response carries no Content-Type
- static-file-cache.ts — `.html` static files (prerendered pages),
  matching Next.js static serving

Compression negotiation is unaffected: COMPRESSIBLE_TYPES matching
splits the media type on ";" before lookup.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>

* fix(client): polyfill `global` in browser bundles

Next.js exposes the Node-style `global` alias to client code: webpack
via its `node.global` runtime shim, Turbopack by compile-time rewriting
the free `global` identifier to its globalThis shortcut and folding
`typeof global` to "object" (turbopack-ecmascript references). vinext
provided nothing, so any client dependency that reads `global` (e.g.
use-dark-mode via nextjs-notion-starter-kit) threw
`ReferenceError: global is not defined` after hydration.

Add a `vinext:client-global-define` plugin that scopes
`define: { global: "globalThis" }` to the client environment:

- builds statically rewrite free `global` references (Turbopack-style)
- dev injects `"global": globalThis` into the client runtime defines
  (/@vite/env), assigning `globalThis.global` before user code runs
  (webpack-style)
- the same define is layered into the client dep optimizer
  (rolldownOptions.transform.define / esbuildOptions.define) because
  pre-bundled deps bypass the plugin transform pipeline

`typeof global` evaluates to "object" in the browser either way,
matching Next.js. Server environments are untouched — `global` remains
the real Node global — and a user-configured `compiler.define.global`
takes precedence, mirroring Turbopack's or_insert free-var semantics.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>

* fix(images): accept /_next/image/ with trailingSlash: true

With `trailingSlash: true`, the App Router dev handler 308-redirects
`/_next/image?url=...` to `/_next/image/?url=...` (the trailing-slash
normalizer runs before the image-endpoint check), but the image endpoint
only matched the exact `/_next/image` pathname — so the redirected
request 404'd and every dev-mode next/image request broke. Reproduced
on tailwind-nextjs-starter-blog, which ships trailingSlash: true.

Baseline Next 16.2.10 behaves the same way up to the redirect (dev with
trailingSlash: true also 308s `/_next/image` to `/_next/image/`) but
then SERVES the slashed form: its route matching strips a trailing
slash before matching internal paths (getItem in
packages/next/src/server/lib/router-utils/filesystem.ts), so image
requests never fail.

Match that: isImageOptimizationPath() now strips a single trailing
slash before comparing, which covers every caller — App Router
dev/prod (app-rsc-handler), Pages Router dev middleware, the Node prod
server, and the Cloudflare worker entry.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>

* test: align existing assertions with charset and trailing-slash fixes

Three assertions added on main after these fixes were authored still
asserted the old behavior: bare text/html Content-Type in
static-file-cache and the pages pipeline defaultContentType, and
isImageOptimizationPath rejecting the trailing-slash form.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>

---------

Co-authored-by: Claude Fable 5 <noreply@anthropic.com>
2026-07-04 00:46:29 +01:00
James Anderson 73156b36e7 fix(release): support beta prereleases (#2511) 2026-07-03 23:40:40 +01:00
James Anderson e4aa03ac5c feat(create): add create-vinext-app (#2483)
* feat(create): add create-vinext-app

* fix(ci): support create package checks

* fix(create): address creator review findings

* fix(create): document version flag

* fix(ci): keep create-next-app cloudflare coverage

* fix(create): update init option test for cdn cache

* fix(create): bundle creator helper deps

* fix(ci): allow local vinext dlx deploy test

* fix(ci): run create-vinext-app deploy test from local tarballs

* fix(create): keep creator package self-contained

* fix(ci): preview release create-vinext-app

* fix(init): install runtime deps as app dependencies

* fix(create-vinext-app): scope workers copy to cloudflare

* fix(create-vinext-app): use pnpm in template examples

* fix(init): start cloudflare apps with wrangler
2026-07-03 17:51:49 +01:00
James Anderson c84f5d476b fix(check): mark cache components partially supported (#2507)
* fix(check): mark cache components unsupported

* fix(check): classify cache components as partial
2026-07-03 15:27:02 +00:00
Steve Faulkner 160645c6d3 fix(config): tsconfig paths — longest-prefix matching and stylesheet-scoped aliases (#2504)
* fix(config): match overlapping tsconfig paths by longest prefix

TypeScript (and Next.js) match compilerOptions.paths patterns by longest
matched prefix regardless of declaration order, but vinext materialized
them into Vite resolve.alias entries in declaration order, where the
alias plugin picks the first match. With overlapping patterns like
`"@/*": ["./src/*"]` + `"@/public/*": ["./public/*"]` (the
ixartz/Next-js-Boilerplate shape), `@/public/...` imports resolved into
src/public/ and every page 500'd.

Sort materialized aliases longest-prefix-first in both the plugin's
resolve.alias materialization and the next.config.ts loader's
runnerImport aliases.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>

* fix(config): keep tsconfig path aliases out of stylesheet resolution

TypeScript compilerOptions.paths never apply to CSS in Next.js —
@import specifiers in stylesheets use standard bundler resolution,
including package.json exports maps. vinext's materialized
resolve.alias entries also ran inside Vite's internal CSS resolver
(which only consults the alias plugin plus Vite's own resolver), so a
monorepo alias like `"@scope/ui/*": ["../../packages/ui/src/*"]`
rewrote `@import "@scope/ui/globals.css"` away from its
exports-mapped target and every route failed with a postcss ENOENT in
dev, and builds failed while analyzing client references
(create-better-t-stack scaffolds).

Emit the merged alias map as alias entries and attach a customResolver
to tsconfig-derived ones that bails out for stylesheet importers
(stylesheet file paths and the synthetic <basedir>/* importer that
postcss-import/less use), letting Vite resolve the original specifier
normally. JS/TS importers keep full alias behavior — including
`import "@/styles/globals.css"` from a layout and alias-based
import.meta.glob / dynamic-import patterns, which require blind prefix
replacement. Vite 8 reports alias customResolver as deprecated during
config resolution; the replacement it suggests (a resolveId plugin)
never runs inside the CSS resolver container, so the warning is
filtered while this remains the only importer-aware hook available.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>

---------

Co-authored-by: Claude Fable 5 <noreply@anthropic.com>
2026-07-03 15:25:51 +01:00
James Anderson b5897d0595 feat(build): require Vite 8 (#2486)
* feat(build)!: require Vite 8

* fix(build): remove unused Vite version export

* test(link): harden prefetch timing assertions
2026-07-03 15:20:33 +01:00
James Anderson 17216d605b chore(release): reclassify 9eed252 as feat (#2500) 2026-07-03 10:20:53 +00:00
James Anderson 9eed252701 fix(init): default to Workers Cache on Cloudflare (#2482)
* fix(init): default to Workers Cache on Cloudflare

* fix(init): prompt for Cloudflare CDN cache

* fix(init): prompt for missing CDN cache choice

* fix(init): add Cloudflare deploy script
2026-07-03 11:15:52 +01:00
github-actions[bot] 5471b41eec chore: version packages (#2428)
Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
@vinext/cloudflare@0.2.1 vinext@0.2.1
2026-07-03 09:40:50 +00:00
Steve Faulkner b7455c3fa6 fix: fully elide inline type-only import specifiers (#2498)
Vite 8's OXC transform (and Vite 7's esbuild transform) honour
`"verbatimModuleSyntax": true` from the app's tsconfig, so
`import { type Metadata } from "next"` leaves a side-effect
`import "next"` behind when every specifier is type-only. Next.js
(SWC) — and esbuild/tsc without verbatimModuleSyntax — elide the whole
statement. create-t3-app and other scaffolds emit both the tsconfig
option and the inline-type import form stock, so on vinext the real
Next.js server runtime was pulled into the RSC graph (dev 500
"require is not defined", build failures via styled-jsx/client-only)
and server-only modules were pulled into the browser bundle when a
"use client" file imported only types from them (t3's tRPC router
shipped to clients and crashed hydration).

Force `typescript.onlyRemoveTypeImports: false` in the oxc transform
options (and `verbatimModuleSyntax: false` in the Vite 7 esbuild
tsconfigRaw) so type-import elision matches Next.js regardless of the
app's tsconfig.

Co-authored-by: Claude Fable 5 <noreply@anthropic.com>
2026-07-03 10:35:59 +01:00
James Anderson 5915c87116 fix(app-router): limit mounted slot cache variants (#2497) 2026-07-03 00:05:47 +01:00
James Anderson 336450ae47 fix(config): escape destination query params (#2494) 2026-07-03 00:00:45 +01:00
James Anderson e0db846716 fix(cloudflare): respect TPR cache opt-outs (#2493) 2026-07-02 23:38:48 +01:00
James Anderson 20e1076452 chore(release): reclassify reactStrictMode entry (#2496) 2026-07-02 22:29:17 +00:00
Nathan Nguyen a9a30a5c85 fix(app-router): omit pending RSC cache state for query renders (#2488)
Co-authored-by: James Anderson <james@eli.cx>
2026-07-02 22:46:53 +01:00
James Anderson 6c7b71eb12 fix(app-router): isolate global not-found css (#2444)
* fix(app-router): isolate global not-found css

* fix(app-router): cover global not-found css review gaps
2026-07-02 21:35:52 +01:00
James Anderson 8b122744ef fix(pages): align middleware data prefetch caching (#2451)
* fix(pages): align middleware data prefetch caching

* fix(pages): guard middleware prefetch data kind

* fix(dev): lazily classify pages data kind

* fix(pages): preserve legacy prefetch fallback

* fix(pages): reject unknown prefetch data kind
2026-07-02 21:33:32 +01:00
James Anderson 6bd1ee0153 fix(app-router): expose app rewrites to pages data clients (#2468) 2026-07-02 21:03:05 +01:00
James Anderson 5a90172a6b fix(pages): honor basePath false rewrites (#2442) 2026-07-02 21:01:24 +01:00
James Anderson e453928dda fix(app-router): publish committed no-prefetch navigations (#2469)
* fix(app-router): publish committed no-prefetch navigations

* fix(app-router): remove unreachable visited-cache fallback

* fix(app-router): replay committed no-prefetch cache payloads

* fix(app-router): remove dead committed cache guard
2026-07-02 20:58:48 +01:00
dependabot[bot] e82cc60de8 chore(deps): bump voidzero-dev/setup-vp from 1.12.0 to 1.13.0 (#2491)
Bumps [voidzero-dev/setup-vp](https://github.com/voidzero-dev/setup-vp) from 1.12.0 to 1.13.0.
- [Release notes](https://github.com/voidzero-dev/setup-vp/releases)
- [Commits](https://github.com/voidzero-dev/setup-vp/compare/2dec1e33f4ab2c6d5bce1b0c4607961bb1a3f7a1...35171c92dd08b67d5a9d3f2a4327800e58396f2a)

---
updated-dependencies:
- dependency-name: voidzero-dev/setup-vp
  dependency-version: 1.13.0
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-07-02 20:44:44 +01:00
James Anderson 5343a3ff32 fix(app-router): cache segment prefetches by rendered search params (#2477)
* fix(app-router): cache segment prefetches by rendered search params

* fix(app-router): protect rendered prefetch alias header

* fix(app-router): repair segment prefetch merge
2026-07-02 19:42:46 +00:00
James Anderson 04a7ed3a10 fix(app-router): skip readiness waits for speculative prerenders (#2457)
* fix(app-router): skip readiness waits for speculative prerenders

* test(request-pipeline): assert speculative header stripping

* fix(app-router): keep speculative prerender shell errors throwable

* fix(app-router): capture speculative prerender cache metadata
2026-07-02 20:25:31 +01:00
James Anderson 5f8048f660 fix(app-router): align app static ISR lifecycle (#2472)
* fix(app-router): align app static ISR lifecycle

* fix(fetch-cache): honor shorter revalidate on hits

* fix(cache): honor read-time revalidate in KV cache
2026-07-02 20:19:02 +01:00
James Anderson 9e1866abb9 fix(pages): normalize data routes for trailing slash middleware (#2470)
* fix(pages): normalize data routes for trailing slash middleware

* fix(pages): gate data trailing slash normalization on middleware
2026-07-02 20:04:25 +01:00
James Anderson 1500fe61d7 fix(pages): align prerender functional parity (#2471)
* fix(pages): align prerender functional parity

* fix(pages): harden preview bypass comparison
2026-07-02 19:57:40 +01:00
James Anderson 239595e69e fix(app-router): reuse metadata rewrite prefetches (#2455)
* fix(app-router): reuse metadata rewrite prefetches

* fix(app-router): normalize rsc reference validation ids

* Revert "fix(app-router): normalize rsc reference validation ids"

This reverts commit bbff1eb13a.

* chore: format link shim
2026-07-01 17:02:35 +00:00
James Anderson ebf8e59289 fix(app-router): avoid runtime route-tree prefetch sizing (#2467)
* fix(app-router): start optimistic prefetches immediately

* fix(app-router): support route tree prefetch inlining

* fix(app-router): dedupe max prefetch inlining requests

* fix(app-router): cap route-tree prefetch size reads

* fix(app-router): avoid runtime route-tree prefetch sizing

* Fixed CI type error, flagged parity gap

Co-authored-by: james-elicx <james-elicx@users.noreply.github.com>

* fix(app-router): preserve negative prefetch inlining thresholds

* fix(app-router): normalize rsc reference validation ids

* Revert "fix(app-router): normalize rsc reference validation ids"

This reverts commit 68b96b596c.

* fix(app-router): keep route-tree prefetch metadata scoped

---------

Co-authored-by: ask-bonk[bot] <ask-bonk[bot]@users.noreply.github.com>
Co-authored-by: james-elicx <james-elicx@users.noreply.github.com>
2026-07-01 17:47:08 +01:00
James Anderson 03f02177ec fix(app-router): start optimistic prefetches immediately (#2440)
* fix(app-router): start optimistic prefetches immediately

* fix(app-router): normalize rsc reference validation ids

* Revert "fix(app-router): normalize rsc reference validation ids"

This reverts commit 34a37658c2.
2026-07-01 16:45:35 +00:00
James Anderson 2256fdd53b fix(app-router): normalize rsc reference validation ids (#2480)
* fix(app-router): normalize rsc reference validation ids

* fix(app-router): scope rsc validation normalizer to dev
2026-07-01 14:30:22 +01:00
James Anderson 81e925eb66 fix(ci): harden perf publisher tree validation (#2478) 2026-07-01 13:39:20 +01:00
James Anderson 9ec793244e fix(app-router): send deployment id on RSC responses (#2452)
* fix(app-router): send deployment id on RSC responses

* test(app-router): isolate deployment id integration coverage
2026-07-01 11:27:22 +01:00
James Anderson 97cd5c3fb4 fix(app-router): separate header-only full-route rsc requests (#2445)
* fix(app-router): separate header-only full-route rsc requests

* test(app-router): assert header RSC redirect
2026-07-01 11:17:10 +01:00
James Anderson b0367f1448 fix(link): avoid reusing dynamic app route prefetches (#2450)
* fix(link): avoid reusing dynamic app route prefetches

* fix(link): preserve static dynamic app prefetches

* test(e2e): scope segment cache client params to prod
2026-07-01 11:14:11 +01:00
James Anderson fd8dd3de09 fix(app-router): preserve app rewrite filtering (#2441) 2026-07-01 11:08:31 +01:00
James Anderson de733ce4aa fix(app-router): revalidate dynamic intercepted actions (#2443) 2026-07-01 11:02:53 +01:00
James Anderson bc1dfce00f fix(app-router): evict segment prefetches under memory pressure (#2466)
* fix(app-router): evict segment prefetches under memory pressure

* fix(app-router): hold prefetch queue slots until body read
2026-07-01 10:54:47 +01:00