[PR #1020] [MERGED] fix(rsc): exclude client shims from dep optimization #1024

Closed
opened 2026-05-06 13:11:37 +02:00 by BreizhHardware · 0 comments

📋 Pull Request Information

Original PR: https://github.com/cloudflare/vinext/pull/1020
Author: @NathanDrake2406
Created: 5/2/2026
Status: Merged
Merged: 5/2/2026
Merged by: @james-elicx

Base: mainHead: nathan/issue-1008-rsc-shim-optdeps


📝 Commits (4)

  • 5b784f4 fix(rsc): exclude client shims from dep optimization
  • 5358c4d Update rsc-client-shim-excludes.ts
  • 49c894b Update rsc-client-shim-excludes.ts
  • f1c5e41 Update build-optimization.test.ts

📊 Changes

3 files changed (+63 additions, -6 deletions)

View changed files

📝 packages/vinext/src/index.ts (+14 -6)
packages/vinext/src/plugins/rsc-client-shim-excludes.ts (+33 -0)
📝 tests/build-optimization.test.ts (+16 -0)

📄 Description

What this changes

Adds vinext's known RSC client shim subpaths to the Vite dep optimizer exclude set for App Router projects. The exclude set is merged into the top-level, RSC, SSR, and client optimizer configs while preserving user-provided excludes and serverExternalPackages.

Closes #1008.

Why

Next.js treats public App Router APIs such as next/link, next/form, and next/script as client modules:

vinext matches that shape with client shims. In dev, @vitejs/plugin-rsc records bare package sources resolved from the RSC graph and generates client-package-proxy/<source> modules from that metadata. The relevant source path is here: https://github.com/vitejs/vite-plugin-react/blob/main/packages/plugin-rsc/src/plugin.ts

Before this change, vinext excluded the bare vinext package but not vinext/shims/*. That leaves known client shim subpaths eligible for dep optimization, which can make the package source recorded by plugin-rsc diverge from the optimized module that produced the client reference metadata. The result is the clientReferenceMetaMap miss reported in #1008.

Approach

  • Keep the fixed client shim list and exclude merge behavior in a normal plugin helper module.
  • Reuse that helper from vinext's Vite config setup instead of spreading another inline Set expression through the config hook.
  • Keep codegen out of the behavior. The generated entries continue to describe app shape, while the normal plugin module owns the optimizer policy.
  • Scope the list to current vinext shims that are actual top-level client modules and can appear as package subpath imports: error-boundary, form, layout-segment-context, link, script, and slot.

Validation

  • vp check packages/vinext/src/index.ts packages/vinext/src/plugins/rsc-client-shim-excludes.ts tests/build-optimization.test.ts
  • vp test run tests/build-optimization.test.ts -t "optimizeDeps.exclude"
  • vp test run tests/app-router.test.ts -t "renders next/link"

Risks / follow-ups

The main maintenance risk is list drift: if vinext adds another top-level "use client" shim that can be imported as vinext/shims/<name> from the RSC graph, it should be added to the helper list.


🔄 This issue represents a GitHub Pull Request. It cannot be merged through Gitea due to API limitations.

## 📋 Pull Request Information **Original PR:** https://github.com/cloudflare/vinext/pull/1020 **Author:** [@NathanDrake2406](https://github.com/NathanDrake2406) **Created:** 5/2/2026 **Status:** ✅ Merged **Merged:** 5/2/2026 **Merged by:** [@james-elicx](https://github.com/james-elicx) **Base:** `main` ← **Head:** `nathan/issue-1008-rsc-shim-optdeps` --- ### 📝 Commits (4) - [`5b784f4`](https://github.com/cloudflare/vinext/commit/5b784f4c8a689ae9b53664574e98156e1fec59c3) fix(rsc): exclude client shims from dep optimization - [`5358c4d`](https://github.com/cloudflare/vinext/commit/5358c4d799b2f94a3ac7980d43c15bb07c1a6c24) Update rsc-client-shim-excludes.ts - [`49c894b`](https://github.com/cloudflare/vinext/commit/49c894b52048877ffa3cae221f8d96adc1487e5c) Update rsc-client-shim-excludes.ts - [`f1c5e41`](https://github.com/cloudflare/vinext/commit/f1c5e4158c9dc21d9d41265b0de40afc7164752b) Update build-optimization.test.ts ### 📊 Changes **3 files changed** (+63 additions, -6 deletions) <details> <summary>View changed files</summary> 📝 `packages/vinext/src/index.ts` (+14 -6) ➕ `packages/vinext/src/plugins/rsc-client-shim-excludes.ts` (+33 -0) 📝 `tests/build-optimization.test.ts` (+16 -0) </details> ### 📄 Description ## What this changes Adds vinext's known RSC client shim subpaths to the Vite dep optimizer exclude set for App Router projects. The exclude set is merged into the top-level, RSC, SSR, and client optimizer configs while preserving user-provided excludes and `serverExternalPackages`. Closes #1008. ## Why Next.js treats public App Router APIs such as `next/link`, `next/form`, and `next/script` as client modules: - `next/link`: https://github.com/vercel/next.js/blob/ae61573e062e900050b8e6b24626e450accc4570/packages/next/src/client/app-dir/link.tsx#L1 - `next/form`: https://github.com/vercel/next.js/blob/ae61573e062e900050b8e6b24626e450accc4570/packages/next/src/client/app-dir/form.tsx#L1 - `next/script`: https://github.com/vercel/next.js/blob/ae61573e062e900050b8e6b24626e450accc4570/packages/next/src/client/script.tsx#L1 - Next's App Router E2E suite explicitly verifies `next/link` in Server Components: https://github.com/vercel/next.js/blob/ae61573e062e900050b8e6b24626e450accc4570/test/e2e/app-dir/rsc-basic/rsc-basic.test.ts#L272-L286 vinext matches that shape with client shims. In dev, `@vitejs/plugin-rsc` records bare package sources resolved from the RSC graph and generates `client-package-proxy/<source>` modules from that metadata. The relevant source path is here: https://github.com/vitejs/vite-plugin-react/blob/main/packages/plugin-rsc/src/plugin.ts Before this change, vinext excluded the bare `vinext` package but not `vinext/shims/*`. That leaves known client shim subpaths eligible for dep optimization, which can make the package source recorded by plugin-rsc diverge from the optimized module that produced the client reference metadata. The result is the `clientReferenceMetaMap` miss reported in #1008. ## Approach - Keep the fixed client shim list and exclude merge behavior in a normal plugin helper module. - Reuse that helper from vinext's Vite config setup instead of spreading another inline `Set` expression through the config hook. - Keep codegen out of the behavior. The generated entries continue to describe app shape, while the normal plugin module owns the optimizer policy. - Scope the list to current vinext shims that are actual top-level client modules and can appear as package subpath imports: `error-boundary`, `form`, `layout-segment-context`, `link`, `script`, and `slot`. ## Validation - `vp check packages/vinext/src/index.ts packages/vinext/src/plugins/rsc-client-shim-excludes.ts tests/build-optimization.test.ts` - `vp test run tests/build-optimization.test.ts -t "optimizeDeps.exclude"` - `vp test run tests/app-router.test.ts -t "renders next/link"` ## Risks / follow-ups The main maintenance risk is list drift: if vinext adds another top-level `"use client"` shim that can be imported as `vinext/shims/<name>` from the RSC graph, it should be added to the helper list. --- <sub>🔄 This issue represents a GitHub Pull Request. It cannot be merged through Gitea due to API limitations.</sub>
BreizhHardware 2026-05-06 13:11:37 +02:00
Sign in to join this conversation.
No milestone
No project
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set.

Reference
starred/vinext#1024
No description provided.