Skip to content

feat(plugin-rsc): expose RSC compatibility manifest#1223

Open
agcty wants to merge 1 commit into
vitejs:mainfrom
agcty:codex/rsc-compatibility-version-api
Open

feat(plugin-rsc): expose RSC compatibility manifest#1223
agcty wants to merge 1 commit into
vitejs:mainfrom
agcty:codex/rsc-compatibility-version-api

Conversation

@agcty
Copy link
Copy Markdown

@agcty agcty commented May 11, 2026

Summary

Adds a compiler-owned RSC compatibility manifest for frameworks built on @vitejs/plugin-rsc.

The manifest is intended for deployment skew protection. A framework can include compatibilityManifest.compatibilityVersion in RSC responses, headers, or framework manifests, then trigger its own recovery behavior when a request comes from an incompatible client.

Usage

Framework runtime code can import the finalized manifest from RSC or SSR environments:

import compatibilityManifest from 'virtual:vite-rsc/compatibility-manifest'

export function getRscResponseMetadata() {
  return {
    compatibilityVersion: compatibilityManifest.compatibilityVersion,
  }
}

Frameworks with custom build orchestration can finalize the manifest through the plugin manager after the real RSC and client builds have completed:

const manager = getPluginApi(config)!.manager
const manifest = manager.finalizeCompatibilityManifest()

Build-time manager.getCompatibilityManifest() and manager.getCompatibilityVersion() throw until the manifest has been finalized, so scan builds or incomplete custom pipelines cannot accidentally emit a partial version.

What The Manifest Covers

The compatibility version is derived from the build and RSC state owned by @vitejs/plugin-rsc:

  • Vite base path
  • RSC runtime package versions
  • final assets manifest hash
  • final client/RSC/SSR output bundle hashes
  • client reference keys and rendered exports
  • server reference keys and exported functions
  • server-action encryption key identity when action closure encryption is emitted

Frameworks can compose this value with framework-specific deployment state such as route/data protocol versions, deployment ids, cache policy, or runtime-only configuration that plugin-rsc cannot observe directly.

@agcty agcty force-pushed the codex/rsc-compatibility-version-api branch from efc7995 to 16933c1 Compare May 11, 2026 10:35
@agcty agcty force-pushed the codex/rsc-compatibility-version-api branch from 16933c1 to f6437f0 Compare May 11, 2026 10:47
@agcty agcty changed the title feat(plugin-rsc): expose RSC compatibility version feat(plugin-rsc): expose RSC compatibility manifest May 11, 2026
@agcty
Copy link
Copy Markdown
Author

agcty commented May 11, 2026

@jacob-ebey @hi-ogawa I wanted to add some context for the motivation here.

This started from the React Router RSC skew issue and Jacob’s comment about possibly moving toward a more precise versioning system for RSC deployments:
remix-run/react-router#14849 (comment)

The initial pass first tried solving skew protection in React Router/framework space by deriving a compatibility version from the framework’s RSC graph. After working through the edge cases, it seemed like the correctness boundary actually belongs lower, in @vitejs/plugin-rsc.

The plugin already owns the authoritative build-time state frameworks would otherwise have to approximate: client reference keys, rendered client exports, server references, the final assets manifest, final client/RSC/SSR outputs, and server-action encryption identity. If each framework reconstructs that separately, skew protection becomes fragile and likely divergent.

So this PR tries to expose a first-class, opt-in primitive:

  • plugin-rsc provides the compiler/build compatibility manifest
  • frameworks compose it with framework-specific state, like deployment id, route/data protocol version, cache policy, or runtime-only config
  • frameworks still decide the recovery behavior: reload, refetch, tolerate the deployment, etc.

The intended runtime API is virtual:vite-rsc/compatibility-manifest, with compatibilityManifest.compatibilityVersion included in framework RSC responses/headers/manifests.

Would you consider this the right layer / boundary and shape for skew protection? Would love to hear your thoughts.

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.

1 participant