From d8e8a7fcbd0f3bffc437d8ce66816bd4cebcafde Mon Sep 17 00:00:00 2001 From: Hiroshi Ogawa Date: Wed, 27 Aug 2025 08:27:16 +0900 Subject: [PATCH 1/6] fix(rsc): inject `AsyncLocalStorage` global via transform --- packages/plugin-rsc/src/plugin.ts | 51 ++++++++++++++++++++----------- 1 file changed, 33 insertions(+), 18 deletions(-) diff --git a/packages/plugin-rsc/src/plugin.ts b/packages/plugin-rsc/src/plugin.ts index ac104eb1..69b90b46 100644 --- a/packages/plugin-rsc/src/plugin.ts +++ b/packages/plugin-rsc/src/plugin.ts @@ -948,25 +948,40 @@ import.meta.hot.on("rsc:update", () => { // make `AsyncLocalStorage` available globally for React request context on edge build (e.g. React.cache, ssr preload) // https://github.com/facebook/react/blob/f14d7f0d2597ea25da12bcf97772e8803f2a394c/packages/react-server/src/forks/ReactFlightServerConfig.dom-edge.js#L16-L19 name: 'rsc:inject-async-local-storage', - async configureServer() { - const __viteRscAyncHooks = await import('node:async_hooks') - ;(globalThis as any).AsyncLocalStorage = - __viteRscAyncHooks.AsyncLocalStorage - }, - banner(chunk) { - if ( - (this.environment.name === 'ssr' || - this.environment.name === 'rsc') && - this.environment.mode === 'build' && - chunk.isEntry - ) { - return `\ -import * as __viteRscAyncHooks from "node:async_hooks"; -globalThis.AsyncLocalStorage = __viteRscAyncHooks.AsyncLocalStorage; -` - } - return '' + // async configureServer() { + // const __viteRscAyncHooks = await import('node:async_hooks') + // ;(globalThis as any).AsyncLocalStorage = + // __viteRscAyncHooks.AsyncLocalStorage + // }, + transform: { + handler(code) { + if ( + this.environment.name !== 'client' && + code.includes('new AsyncLocalStorage()') && + !code.includes('__viteRscAyncHooks') + ) { + return ( + `import * as __viteRscAyncHooks from "node:async_hooks";` + + `globalThis.AsyncLocalStorage = __viteRscAyncHooks.AsyncLocalStorage;` + + code + ) + } + }, }, + // banner(chunk) { + // if ( + // (this.environment.name === 'ssr' || + // this.environment.name === 'rsc') && + // this.environment.mode === 'build' && + // chunk.isEntry + // ) { + // return `\ + // import * as __viteRscAyncHooks from "node:async_hooks"; + // globalThis.AsyncLocalStorage = __viteRscAyncHooks.AsyncLocalStorage; + // ` + // } + // return '' + // }, }, ...vitePluginRscMinimal(rscPluginOptions, manager), ...vitePluginFindSourceMapURL(), From 3ce936daf89ad87a625f82e40f16ed4ff577b61a Mon Sep 17 00:00:00 2001 From: Hiroshi Ogawa Date: Wed, 27 Aug 2025 08:47:27 +0900 Subject: [PATCH 2/6] fix: use require for rollup --- packages/plugin-rsc/src/plugin.ts | 15 ++++++++------- 1 file changed, 8 insertions(+), 7 deletions(-) diff --git a/packages/plugin-rsc/src/plugin.ts b/packages/plugin-rsc/src/plugin.ts index 69b90b46..108f654a 100644 --- a/packages/plugin-rsc/src/plugin.ts +++ b/packages/plugin-rsc/src/plugin.ts @@ -53,6 +53,8 @@ import { validateImportPlugin } from './plugins/validate-import' import { vitePluginFindSourceMapURL } from './plugins/find-source-map-url' import { parseCssVirtual, toCssVirtual, parseIdQuery } from './plugins/shared' +const isRolldownVite = 'rolldownVersion' in vite + const BUILD_ASSETS_MANIFEST_NAME = '__vite_rsc_assets_manifest.js' type ClientReferenceMeta = { @@ -948,20 +950,19 @@ import.meta.hot.on("rsc:update", () => { // make `AsyncLocalStorage` available globally for React request context on edge build (e.g. React.cache, ssr preload) // https://github.com/facebook/react/blob/f14d7f0d2597ea25da12bcf97772e8803f2a394c/packages/react-server/src/forks/ReactFlightServerConfig.dom-edge.js#L16-L19 name: 'rsc:inject-async-local-storage', - // async configureServer() { - // const __viteRscAyncHooks = await import('node:async_hooks') - // ;(globalThis as any).AsyncLocalStorage = - // __viteRscAyncHooks.AsyncLocalStorage - // }, transform: { handler(code) { + // for build, we cannot use `import` as it seems to confuse rollup commonjs plugin. if ( - this.environment.name !== 'client' && + (this.environment.name === 'ssr' || + this.environment.name === 'rsc') && code.includes('new AsyncLocalStorage()') && !code.includes('__viteRscAyncHooks') ) { return ( - `import * as __viteRscAyncHooks from "node:async_hooks";` + + (this.environment.mode === 'build' && !isRolldownVite + ? `const __viteRscAyncHooks = require("node:async_hooks");` + : `import * as __viteRscAyncHooks from "node:async_hooks";`) + `globalThis.AsyncLocalStorage = __viteRscAyncHooks.AsyncLocalStorage;` + code ) From c961f9a1d1164b2abf985bf7837de8d0cbaaa3cc Mon Sep 17 00:00:00 2001 From: Hiroshi Ogawa Date: Wed, 27 Aug 2025 09:07:57 +0900 Subject: [PATCH 3/6] fix: narrow condition --- packages/plugin-rsc/src/plugin.ts | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/packages/plugin-rsc/src/plugin.ts b/packages/plugin-rsc/src/plugin.ts index 108f654a..254520df 100644 --- a/packages/plugin-rsc/src/plugin.ts +++ b/packages/plugin-rsc/src/plugin.ts @@ -952,13 +952,14 @@ import.meta.hot.on("rsc:update", () => { name: 'rsc:inject-async-local-storage', transform: { handler(code) { - // for build, we cannot use `import` as it seems to confuse rollup commonjs plugin. if ( (this.environment.name === 'ssr' || this.environment.name === 'rsc') && + code.includes('typeof AsyncLocalStorage') && code.includes('new AsyncLocalStorage()') && !code.includes('__viteRscAyncHooks') ) { + // for build, we cannot use `import` as it confuses rollup commonjs plugin. return ( (this.environment.mode === 'build' && !isRolldownVite ? `const __viteRscAyncHooks = require("node:async_hooks");` From edc26497d85bd730f08be9972706fc7cea8b85f0 Mon Sep 17 00:00:00 2001 From: Hiroshi Ogawa Date: Wed, 27 Aug 2025 09:09:31 +0900 Subject: [PATCH 4/6] chore: cleanup --- packages/plugin-rsc/src/plugin.ts | 16 +--------------- 1 file changed, 1 insertion(+), 15 deletions(-) diff --git a/packages/plugin-rsc/src/plugin.ts b/packages/plugin-rsc/src/plugin.ts index 254520df..34ef480e 100644 --- a/packages/plugin-rsc/src/plugin.ts +++ b/packages/plugin-rsc/src/plugin.ts @@ -947,7 +947,7 @@ import.meta.hot.on("rsc:update", () => { }, ), { - // make `AsyncLocalStorage` available globally for React request context on edge build (e.g. React.cache, ssr preload) + // make `AsyncLocalStorage` available globally for React edge build (required for React.cache, ssr preload, etc.) // https://github.com/facebook/react/blob/f14d7f0d2597ea25da12bcf97772e8803f2a394c/packages/react-server/src/forks/ReactFlightServerConfig.dom-edge.js#L16-L19 name: 'rsc:inject-async-local-storage', transform: { @@ -970,20 +970,6 @@ import.meta.hot.on("rsc:update", () => { } }, }, - // banner(chunk) { - // if ( - // (this.environment.name === 'ssr' || - // this.environment.name === 'rsc') && - // this.environment.mode === 'build' && - // chunk.isEntry - // ) { - // return `\ - // import * as __viteRscAyncHooks from "node:async_hooks"; - // globalThis.AsyncLocalStorage = __viteRscAyncHooks.AsyncLocalStorage; - // ` - // } - // return '' - // }, }, ...vitePluginRscMinimal(rscPluginOptions, manager), ...vitePluginFindSourceMapURL(), From f66b3c9a638af6feeea475a5aa3094b190a52dd3 Mon Sep 17 00:00:00 2001 From: Hiroshi Ogawa Date: Wed, 27 Aug 2025 09:25:03 +0900 Subject: [PATCH 5/6] fix: ssg --- packages/plugin-rsc/examples/ssg/vite.config.ts | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/packages/plugin-rsc/examples/ssg/vite.config.ts b/packages/plugin-rsc/examples/ssg/vite.config.ts index 7c0fb059..646f9430 100644 --- a/packages/plugin-rsc/examples/ssg/vite.config.ts +++ b/packages/plugin-rsc/examples/ssg/vite.config.ts @@ -25,6 +25,14 @@ export default defineConfig((env) => ({ }), rscSsgPlugin(), ], + environments: { + ssr: { + optimizeDeps: { + // TODO: move to plugin + include: ['react-dom/static.edge'], + }, + }, + }, })) function rscSsgPlugin(): Plugin[] { From d3dbe781dfeab899362cdfd5c3c20028883ba6c8 Mon Sep 17 00:00:00 2001 From: Hiroshi Ogawa Date: Wed, 27 Aug 2025 09:40:13 +0900 Subject: [PATCH 6/6] chore: cleanup --- packages/plugin-rsc/examples/ssg/vite.config.ts | 8 -------- 1 file changed, 8 deletions(-) diff --git a/packages/plugin-rsc/examples/ssg/vite.config.ts b/packages/plugin-rsc/examples/ssg/vite.config.ts index 646f9430..7c0fb059 100644 --- a/packages/plugin-rsc/examples/ssg/vite.config.ts +++ b/packages/plugin-rsc/examples/ssg/vite.config.ts @@ -25,14 +25,6 @@ export default defineConfig((env) => ({ }), rscSsgPlugin(), ], - environments: { - ssr: { - optimizeDeps: { - // TODO: move to plugin - include: ['react-dom/static.edge'], - }, - }, - }, })) function rscSsgPlugin(): Plugin[] {