Vite RSC runtime field note

Follow the load ID, one prefix at a time

React starts with moduleKey#exportName. A manifest separates the export name, decorates the remaining load ID, and hands that string to a patched require path. Each layer removes only the decoration it owns.

vitejs/vite-plugin-react commit 61637cf illustrative development IDs

A manifest lookup turns one reference identity into a load ID and a separate export selector. The require globals route only the load ID.

Reference identity

moduleKey#exportName

Manifest entry

id: decoratedLoadId name: exportName
Require receives decoratedLoadId, not moduleKey#exportName. React retains name and uses it after the module promise resolves.
02 / Overview

All $$ decorations

This is the complete runtime decoration map. Each part has one routing or cache purpose and one layer responsible for removing it.

DecorationPositionPurposeRemoved by
$$server:Outer prefixRoute this load ID to server require.setInternalRequire
$$decode-client:After $$server:Synthesize client references rather than import a module.RSC server require
$$cache=...SuffixFresh development load identity with the same underlying Vite import ID.Concrete client or server require
#exportName is not a $$ decoration. The manifest removes it earlier by separating the reference identity into id and name.
Client developmentmoduleId$$cache=nonce
Server development$$server:moduleId$$cache=nonce
Decode client on RSC$$server:$$decode-client:moduleId
Productionsame routes, generally without $$cache
Concrete require functions memoize by the decorated ID. Cache-tag removal occurs inside that memoized operation, immediately before the environment loader.
03 / Trace

Client load ID

No routing prefix means client require. The development cache suffix survives routing and is removed immediately before the environment loader.

module ID export name development cache tag

Illustrative identity

Development mode
Manifest lookupcore/rsc.ts:119
/src/Button.tsx#Button
{ id: "/src/Button.tsx$$cache=abc", name: "Button" }
Shared dispatchercore/shared.ts:16
__vite_rsc_require__("/src/Button.tsx$$cache=abc")

No $$server: prefix. Forward the ID unchanged.

__vite_rsc_client_require__("/src/Button.tsx$$cache=abc")
/src/Button.tsx$$cache=abc

Remove the cache tag inside the memoized require operation.

options.load("/src/Button.tsx")
After resolution
module["Button"]

The shared dispatcher owns the outer routing prefix. Server require owns the development cache suffix.

server routing prefix module ID development cache tag export name

Illustrative identity

Development mode
Manifest lookupcore/rsc.ts:74
/src/actions.ts#save
{ id: "$$server:/src/actions.ts$$cache=abc", name: "save" }
Shared dispatchercore/shared.ts:16
__vite_rsc_require__("$$server:/src/actions.ts$$cache=abc")

Recognize and remove the server routing prefix.

__vite_rsc_server_require__("/src/actions.ts$$cache=abc")
Server requirecore/rsc.ts:17
/src/actions.ts$$cache=abc

Remove the cache tag inside the memoized require operation.

options.load("/src/actions.ts")
After resolution
module["save"]

Two prefixes produce two decisions. The first routes to server require. The second tells server require to synthesize reference exports instead of importing a browser module.

server routing prefix decode-client instruction client module identity

Manifest entry

No real client import on RSC
Decode manifestcore/rsc.ts:96
{ id: "$$server:$$decode-client:/src/Button.tsx", name: "Button" }
Shared dispatchercore/shared.ts:16
__vite_rsc_require__("$$server:$$decode-client:/src/Button.tsx")
__vite_rsc_server_require__("$$decode-client:/src/Button.tsx")
Server requirecore/rsc.ts:28
$$decode-client:/src/Button.tsx

Recognize the instruction, remove it, and return a synthetic module-shaped Proxy.

registerClientReference(throwingProxy, "/src/Button.tsx", "Button")

No __vite_rsc_require__

The action identity stays in its combined moduleKey#exportName form across the application transport. It does not receive $$server:.

createServerReference("moduleKey#exportName")
callServer("moduleKey#exportName", args)

The framework encodes and transports the ID and arguments.

loadServerAction("moduleKey#exportName")

Split at #, call requireModule(moduleKey) directly, then select the export.

core/rsc.ts:68

Registration transforms establish the identity upstream. They are context for the string journey, not part of prefix routing.

"use client" on RSC

registerClientReference(proxy, referenceKey, exportName)

plugin.ts:1523

"use server" on RSC

registerServerReference(fn, normalizedId, exportName)

plugin.ts:2010

Server export outside RSC

createServerReference("normalizedId#exportName", ...)

plugin.ts:2059

Runtime manifest lookup

React combines the registered module ID and export name as the manifest lookup key.

core/rsc.ts:74