Skip to content

feat(rsc): support custom server function directives#1246

Open
james-elicx wants to merge 9 commits into
vitejs:mainfrom
james-elicx:codex/server-function-directives
Open

feat(rsc): support custom server function directives#1246
james-elicx wants to merge 9 commits into
vitejs:mainfrom
james-elicx:codex/server-function-directives

Conversation

@james-elicx

@james-elicx james-elicx commented Jun 11, 2026

Copy link
Copy Markdown
Contributor

Summary

Adds an experimental serverFunctionDirectives API for framework directives such as Next.js-style "use cache".

This is additive to the existing rsc:use-server implementation:

  • the existing vitePluginUseServer transform remains in place
  • custom directives run in a separate focused plugin immediately before it
  • the only behavioral seam in vitePluginUseServer is preserving custom manifest metadata during cleanup and merging custom export names when a module also has "use server"

API

serverFunctionDirectives: [{
  directive: /^use cache(?:: .+)?$/,
  test: (code) => code.includes("use cache"),
  filter: (id) => !id.includes("/node_modules/"),
  rejectNonAsyncFunction: true,
  validate({ directive, location }) {},
  filterExport({ name, meta }) {},
  wrap({ value, name, id, directiveMatch, location, hasBoundArgs }) {
    return `frameworkWrap(${value})`
  },
}]

Reused functionality

The custom-directive plugin delegates to the same transform helpers used by "use server" for:

  • inline scope/capture analysis and closure hoisting
  • bound-argument encryption
  • module export wrapping and proxy generation
  • normalized server-reference IDs and manifest entries
  • export-star expansion and export filtering

It also supports object methods, static class methods, destructured exports, named re-exports, stable custom hoist names, stateful regular expressions, and export filtering before async validation.

@james-elicx james-elicx force-pushed the codex/server-function-directives branch 2 times, most recently from 79377ac to c44f424 Compare June 11, 2026 14:10
@james-elicx james-elicx force-pushed the codex/server-function-directives branch 2 times, most recently from 205122e to 1aabe31 Compare June 11, 2026 14:46
Comment thread packages/plugin-rsc/src/plugins/server-function-directives.ts Outdated
Comment thread packages/plugin-rsc/src/plugins/server-function-directives.ts
Comment thread packages/plugin-rsc/src/plugins/server-function-directives.ts Outdated
Comment thread packages/plugin-rsc/src/plugins/server-function-directives.ts Outdated
Comment thread packages/plugin-rsc/src/plugins/server-function-directives.ts Outdated
Comment thread packages/plugin-rsc/src/plugins/server-function-directives.ts Outdated
Comment thread packages/plugin-rsc/src/plugins/server-function-directives.ts Outdated
Comment thread packages/plugin-rsc/src/plugins/server-function-directives.ts Outdated
Comment thread packages/plugin-rsc/src/plugins/server-function-directives.ts Outdated
Comment thread packages/plugin-rsc/src/transforms/hoist.test.ts Outdated
@james-elicx james-elicx force-pushed the codex/server-function-directives branch from 1aabe31 to 142fb07 Compare June 11, 2026 15:46
@james-elicx james-elicx marked this pull request as ready for review June 11, 2026 17:11
@hi-ogawa hi-ogawa added the trigger: preview Trigger pkg.pr.new label Jun 12, 2026
@pkg-pr-new

pkg-pr-new Bot commented Jun 12, 2026

Copy link
Copy Markdown

Open in StackBlitz

npm i https://pkg.pr.new/@vitejs/plugin-react@1246
npm i https://pkg.pr.new/@vitejs/plugin-rsc@1246
npm i https://pkg.pr.new/@vitejs/plugin-react-swc@1246

commit: 8595871

@hi-ogawa hi-ogawa left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Can you explain higher level motivation (than implementation explanation)? From a quick look, I cannot tell things like:

  • whether this includes some fixes in existing transforms wrap/hoist and thus existing builtin "use server" support.
  • whether new plugin vitePluginServerFunctionDirectives needs to be inside rsc plugin. for example, if we land changes in transforms/*, then can you build vitePluginServerFunctionDirectives outside based on the exported transform utils?
  • whether vitePluginServerFunctionDirectives has some new mechanism compared to current builtin "use server" support that also benefit for builtin use server to have.

Comment thread packages/plugin-rsc/src/transforms/server-action.ts
@james-elicx

james-elicx commented Jun 12, 2026

Copy link
Copy Markdown
Contributor Author

Can you explain higher level motivation (than implementation explanation)? From a quick look, I cannot tell things like:

  • whether this includes some fixes in existing transforms wrap/hoist and thus existing builtin "use server" support.

Yeah, there's some improvements to how object & class methods and named expressions are treated, which the 'use server' directive will benefit from. The other part is how certain forms that can't be hoisted safely are handled and tracking metadata about parameters, which is mainly for custom directives to use. I can break those out into separate PRs if needed.

  • whether new plugin vitePluginServerFunctionDirectives needs to be inside rsc plugin. for example, if we land changes in transforms/*, then can you build vitePluginServerFunctionDirectives outside based on the exported transform utils?

I believe we may be able to, however, the more I was looking at some of the 'use cache' directive stuff we were having to do as I started fixing bugs, the more it felt like we were touching more and more on the internals of how the plugin processes directives.

By that, I'm referring to:

  • server reference manifests.
  • the runtime proxies.
  • the encryption/encoding behaviour for closures.
  • some scope tracking.

It felt a lot to me like we began implementing our own generic approach to register custom directives rather than there being an API for one, and in the process, attaching onto everything the RSC plugin was already doing internally.

  • whether vitePluginServerFunctionDirectives has some new mechanism compared to current builtin "use server" support that also benefit for builtin use server to have.

The 'use server' directive could actually be changed to route through this new plugin as well. I was originally going to do that and have one single way for people to register custom directives that was also used for registering the 'use server' directive by default. The way this works was based on how that directive works as its starting point.

Couldn't help but feel a tad risky without proving the new approach works well before doing that...

Comment thread packages/plugin-rsc/src/transforms/server-action.ts
@hi-ogawa hi-ogawa self-assigned this Jun 12, 2026
@james-elicx james-elicx force-pushed the codex/server-function-directives branch from 5586d70 to e539c58 Compare June 12, 2026 01:10
Comment thread packages/plugin-rsc/src/transforms/server-action.ts
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

trigger: preview Trigger pkg.pr.new

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants