Skip to content

perf(app): use @vitejs/plugin-rsc/rsc/* entries#2677

Draft
hi-ogawa wants to merge 2 commits into
cloudflare:mainfrom
hi-ogawa:plugin-rsc-public-entries
Draft

perf(app): use @vitejs/plugin-rsc/rsc/* entries#2677
hi-ogawa wants to merge 2 commits into
cloudflare:mainfrom
hi-ogawa:plugin-rsc-public-entries

Conversation

@hi-ogawa

@hi-ogawa hi-ogawa commented Jul 23, 2026

Copy link
Copy Markdown

This PR updates the @vitejs/plugin-rsc runtime entries consumed by vinext.

Vinext previously imported internal-ish /core/*, /react/*, and /vendor/* entries. These are now replaced and consolidated to public /rsc/* runtime API family.

Specifically:

  • Use /rsc/static, released in @vitejs/plugin-rsc@0.5.29, instead of deep import of /vendor/ static API.
  • Use the slimmer /rsc/server entry for the main RSC runtime because it only consumes server-side APIs.
  • Lazily load /rsc/server and /rsc/client separately for the "use cache" runtime.

The server/client split entries are a part of perf works by @TheAlexLichter (Thank you!). The background context is found in #2080 and vitejs/vite-plugin-react#1252.

The public static API was added in vitejs/vite-plugin-react#1285 with minimal example to exercise the PPR concept.

This is not by no means against Vinext using non-public API forever, but I think, from time to time, it's good to catch up with what API Vinext uses and make @vitejs/plugin-rsc align the runtime API to prove some features are framework agnostic concept. If there's a future occasion to reach for core/vendor API, please feel free to do so 😃


For perf number, the agent ran benchmarks/perf/run-scenarios.mjs script locally and claimed a following (I don't yet understand what the script does):

Ran six alternating base/head rounds against main using the generated 33-route benchmark app with framework caches cleared before each round.

Metric main PR Change
Dev cold start, mean 1280.7 ms 1190.5 ms -90.2 ms (-7.0%)
Dev cold start, median 1283.7 ms 1181.4 ms -102.3 ms (-8.0%)
Server bundle, gzip 181,712 B 181,444 B -268 B

The PR was faster in all six cold-start rounds. Production build time was noisy and showed no meaningful change. These are local macOS results; the PR performance workflow will provide the authoritative Linux CI comparison.

Co-authored-by: OpenCode <noreply@opencode.ai>
Comment on lines +292 to +293
} from "@vitejs/plugin-rsc/rsc/server";
import { prerender as _prerender } from "@vitejs/plugin-rsc/rsc/static";

@hi-ogawa hi-ogawa Jul 23, 2026

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

hasServerActions ? "@vitejs/plugin-rsc/rsc" : "@vitejs/plugin-rsc/react/rsc"

This hasServerActions branch is introduced by #2206, but this shouldn't matter since tree shaking server action API is mostly done by the import branch above:

import {
renderToReadableStream as _renderToReadableStream,
${
hasServerActions
? `decodeAction,
decodeFormState,
decodeReply,
loadServerAction,
createTemporaryReferenceSet,`
: ""
}

So this has been consolidated to just /rsc/server import unconditionally.

@hi-ogawa
hi-ogawa marked this pull request as ready for review July 23, 2026 04:34
"@mdx-js/rollup": "^3.0.0",
"@vitejs/plugin-react": "^5.1.4 || ^6.0.0",
"@vitejs/plugin-rsc": "^0.5.26",
"@vitejs/plugin-rsc": "^0.5.29",

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm not sure if peer dep bump should be breaking change. From the past commit history, there doesn't seem to be strict policy.

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The other times i've switched to new Vite related functionality, i've left the old behaviour behind a version check to avoid breaking changes. Will probably have to see if the same thing can be done for this too. I can have a look at that no worries

@hi-ogawa hi-ogawa changed the title refactor(app): use public @vitejs/plugin-rsc runtime entries perf(app): use @vitejs/plugin-rsc/rsc/* entries Jul 23, 2026
@NathanDrake2406

Copy link
Copy Markdown
Contributor

@james-elicx BOOOOOM! PPR time baby

@pkg-pr-new

pkg-pr-new Bot commented Jul 23, 2026

Copy link
Copy Markdown

Open in StackBlitz

npm i https://pkg.pr.new/@vinext/cloudflare@2677
npm i https://pkg.pr.new/create-vinext-app@2677
npm i https://pkg.pr.new/@vinext/types@2677
npm i https://pkg.pr.new/vinext@2677

commit: 95d9862

@github-actions

github-actions Bot commented Jul 23, 2026

Copy link
Copy Markdown
Contributor

Performance benchmarks

Compared 95d9862 against base 22f106e using alternating same-runner rounds. Next.js was unchanged and skipped.

1 improved · 0 regressed · 5 within ±1.5%

Scenario Framework Baseline Current Change
Client bundle size (gzip) vinext 131.9 KB 131.9 KB ⚫ -0.0%
Client entry size (gzip) vinext 119.3 KB 119.3 KB ⚫ -0.0%
Dev server cold start vinext 2.29 s 2.21 s 🟢 -3.5%
Production build time vinext 2.36 s 2.38 s ⚫ +0.9%
RSC entry closure size (gzip) vinext 103.2 KB 103.4 KB ⚫ +0.1%
Server bundle size (gzip) vinext 177.5 KB 177.2 KB ⚫ -0.2%

View detailed results and traces

🟢 improvement · 🔴 regression · ⚫ change below 1.5% · paired base/head

Comment on lines +235 to +238
const [server, client] = await Promise.all([
import("@vitejs/plugin-rsc/rsc/server"),
import("@vitejs/plugin-rsc/rsc/client"),
]);

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It looks like using /rsc/* here breaks for pages router setup because no rsc plugin means no virtual module used by /rsc/* entry.

I think ideally page router only mode can entirely nullifying packages/vinext/src/shims/cache-runtime.ts (and other related app router only modules). Let me check a bit.

@hi-ogawa hi-ogawa Jul 23, 2026

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Attempting to remove "cache-runtime" import from pages router ssr entry 95d9862. The existing test appears to be asserting internal request context, which has no user facing pages router feature, so it's adjusted accordingly.

Co-authored-by: OpenCode <noreply@opencode.ai>
@hi-ogawa
hi-ogawa marked this pull request as draft July 23, 2026 07:55
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants