@vitejs/plugin-rsc 0.4.11 → 0.4.13

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -11,7 +11,7 @@ This package provides [React Server Components](https://react.dev/reference/rsc/
11
11
 
12
12
  ## Getting Started
13
13
 
14
- You can start a project by copying an example locally by:
14
+ You can create a starter project by:
15
15
 
16
16
  ```sh
17
17
  npx degit vitejs/vite-plugin-react/packages/plugin-rsc/examples/starter my-app
@@ -22,11 +22,9 @@ npx degit vitejs/vite-plugin-react/packages/plugin-rsc/examples/starter my-app
22
22
  - [`./examples/starter`](./examples/starter)
23
23
  - This example provides an in-depth overview of API with inline comments to explain how they function within RSC-powered React application.
24
24
  - [`./examples/react-router`](./examples/react-router)
25
- - This demonstrates how to integrate [experimental React Router RSC API](https://remix.run/blog/rsc-preview) with this plugin.
26
- It also includes `@cloudflare/vite-plugin` integration.
25
+ - This demonstrates how to integrate [experimental React Router RSC API](https://remix.run/blog/rsc-preview). React Router now provides [official RSC support](https://reactrouter.com/how-to/react-server-components), so it's recommended to follow React Router's official documentation for the latest integration.
27
26
  - [`./examples/basic`](./examples/basic)
28
27
  - This is mainly used for e2e testing and include various advanced RSC usages (e.g. `"use cache"` example).
29
- It also uses a high level `@vitejs/plugin-rsc/extra/{rsc,ssr,browser}` API for quick setup.
30
28
  - [`./examples/ssg`](./examples/ssg)
31
29
  - Static site generation (SSG) example with MDX and client components for interactivity.
32
30
 
@@ -130,7 +128,7 @@ export default defineConfig({
130
128
  - [`entry.rsc.tsx`](./examples/starter/src/framework/entry.rsc.tsx)
131
129
 
132
130
  ```tsx
133
- import * as ReactServer from '@vitejs/plugin-rsc/rsc' // re-export of react-server-dom/server.edge
131
+ import * as ReactServer from '@vitejs/plugin-rsc/rsc' // re-export of react-server-dom/server.edge and client.edge
134
132
 
135
133
  // the plugin assumes `rsc` entry having default export of request handler
136
134
  export default async function handler(request: Request): Promise<Response> {
@@ -214,11 +212,12 @@ main();
214
212
 
215
213
  ### `@vitejs/plugin-rsc/rsc`
216
214
 
217
- This module re-exports RSC runtime API provided by `react-server-dom/server.edge`
215
+ This module re-exports RSC runtime API provided by `react-server-dom/server.edge` and `react-server-dom/client.edge` such as:
218
216
 
219
217
  - `renderToReadableStream`: RSC serialization (React VDOM -> RSC stream)
220
218
  - `createFromReadableStream`: RSC deserialization (RSC stream -> React VDOM). This is also available on rsc environment itself. For example, it allows saving serailized RSC and deserializing it for later use.
221
- - `decodeAction/decodeReply/loadServerAction`: server function related...
219
+ - `decodeAction/decodeReply/decodeFormState/loadServerAction/createTemporaryReferenceSet`
220
+ - `encodeReply/createClientTemporaryReferenceSet`
222
221
 
223
222
  ### `@vitejs/plugin-rsc/ssr`
224
223
 
@@ -418,7 +417,10 @@ export default defineConfig({
418
417
  })
419
418
  ```
420
419
 
421
- ## Higher level API
420
+ ## High level API
421
+
422
+ > [!NOTE]
423
+ > High level API is deprecated. Please write on your own `@vitejs/plugin-rsc/{rsc,ssr,browser}` integration.
422
424
 
423
425
  This is a wrapper of `react-server-dom` API and helper API to setup a minimal RSC app without writing own framework code like [`./examples/starter/src/framework`](./examples/starter/src/framework/). See [`./examples/basic`](./examples/basic/) for how this API is used.
424
426
 
@@ -5,7 +5,7 @@ import * as clientReferences from "virtual:vite-rsc/client-references";
5
5
  initialize();
6
6
  function initialize() {
7
7
  setRequireModule({ load: async (id) => {
8
- if (!import.meta.env.__vite_rsc_build__) return __vite_rsc_raw_import__(import.meta.env.BASE_URL + id.slice(1));
8
+ if (!import.meta.env.__vite_rsc_build__) return __vite_rsc_raw_import__(withTrailingSlash(import.meta.env.BASE_URL) + id.slice(1));
9
9
  else {
10
10
  const import_ = clientReferences.default[id];
11
11
  if (!import_) throw new Error(`client reference not found '${id}'`);
@@ -13,5 +13,9 @@ function initialize() {
13
13
  }
14
14
  } });
15
15
  }
16
+ function withTrailingSlash(path) {
17
+ if (path[path.length - 1] !== "/") return `${path}/`;
18
+ return path;
19
+ }
16
20
 
17
21
  //#endregion
@@ -5,8 +5,6 @@ declare function createFromReadableStream<T>(stream: ReadableStream<Uint8Array>,
5
5
  declare function createFromFetch<T>(promiseForResponse: Promise<Response>, options?: object): Promise<T>;
6
6
  declare const encodeReply: (v: unknown[], options?: unknown) => Promise<string | FormData>;
7
7
  declare const createServerReference: (...args: any[]) => unknown;
8
- // use global instead of local variable to tolerate duplicate modules
9
- // e.g. when `setServerCallback` is pre-bundled but `createServerReference` is not
10
8
  declare function callServer(...args: any[]): any;
11
9
  declare function setServerCallback(fn: CallServerCallback): void;
12
10
  declare const createTemporaryReferenceSet: () => unknown;
package/dist/browser.d.ts CHANGED
@@ -1,4 +1,4 @@
1
1
  import { CallServerCallback } from "./index-BHqtj9tT.js";
2
2
  import { setRequireModule } from "./browser-Dw18EFgE.js";
3
- import { callServer, createFromFetch, createFromReadableStream, createServerReference, createTemporaryReferenceSet, encodeReply, findSourceMapURL, setServerCallback } from "./browser-DjnGtEmB.js";
3
+ import { callServer, createFromFetch, createFromReadableStream, createServerReference, createTemporaryReferenceSet, encodeReply, findSourceMapURL, setServerCallback } from "./browser-CeSkQWD5.js";
4
4
  export { CallServerCallback, callServer, createFromFetch, createFromReadableStream, createServerReference, createTemporaryReferenceSet, encodeReply, findSourceMapURL, setRequireModule, setServerCallback };
package/dist/browser.js CHANGED
@@ -2,6 +2,6 @@ import "./dist-DEF94lDJ.js";
2
2
  import "./shared-CEyKoKAb.js";
3
3
  import { setRequireModule } from "./browser-QWbIPyhO.js";
4
4
  import { callServer, createFromFetch, createFromReadableStream, createServerReference, createTemporaryReferenceSet, encodeReply, findSourceMapURL, setServerCallback } from "./browser-D8OPzpF5.js";
5
- import "./browser-LizIyxet.js";
5
+ import "./browser-C1Q4O7AS.js";
6
6
 
7
7
  export { callServer, createFromFetch, createFromReadableStream, createServerReference, createTemporaryReferenceSet, encodeReply, findSourceMapURL, setRequireModule, setServerCallback };
@@ -1,4 +1,4 @@
1
- //#region ../../node_modules/.pnpm/rsc-html-stream@0.0.6/node_modules/rsc-html-stream/client.js
1
+ //#region ../../node_modules/.pnpm/rsc-html-stream@0.0.7/node_modules/rsc-html-stream/client.js
2
2
  let encoder = new TextEncoder();
3
3
  let streamController;
4
4
  let rscStream = new ReadableStream({ start(controller) {
@@ -1,7 +1,14 @@
1
- import { RscPayload } from "../rsc-Cmvt9txp.js";
1
+ import { RscPayload } from "../rsc-DryRyKqc.js";
2
2
 
3
3
  //#region src/extra/browser.d.ts
4
+
5
+ /**
6
+ * @deprecated Use `@vitejs/plugin-rsc/browser` API instead.
7
+ */
4
8
  declare function hydrate(): Promise<void>;
9
+ /**
10
+ * @deprecated Use `@vitejs/plugin-rsc/browser` API instead.
11
+ */
5
12
  declare function fetchRSC(request: string | URL | Request): Promise<RscPayload["root"]>;
6
13
  //#endregion
7
14
  export { fetchRSC, hydrate };
@@ -2,13 +2,16 @@ import "../dist-DEF94lDJ.js";
2
2
  import "../shared-CEyKoKAb.js";
3
3
  import "../browser-QWbIPyhO.js";
4
4
  import { createFromFetch, createFromReadableStream, createTemporaryReferenceSet, encodeReply, setServerCallback } from "../browser-D8OPzpF5.js";
5
- import "../browser-LizIyxet.js";
6
- import { rscStream } from "../client-edAdk2GF.js";
5
+ import "../browser-C1Q4O7AS.js";
6
+ import { rscStream } from "../client-CPc-spDn.js";
7
7
  import React from "react";
8
8
  import ReactDomClient from "react-dom/client";
9
9
  import { jsx } from "react/jsx-runtime";
10
10
 
11
11
  //#region src/extra/browser.tsx
12
+ /**
13
+ * @deprecated Use `@vitejs/plugin-rsc/browser` API instead.
14
+ */
12
15
  async function hydrate() {
13
16
  const callServer = async (id, args) => {
14
17
  const url = new URL(window.location.href);
@@ -45,6 +48,9 @@ async function hydrate() {
45
48
  window.history.replaceState({}, "", window.location.href);
46
49
  });
47
50
  }
51
+ /**
52
+ * @deprecated Use `@vitejs/plugin-rsc/browser` API instead.
53
+ */
48
54
  async function fetchRSC(request) {
49
55
  const payload = await createFromFetch(fetch(request));
50
56
  return payload.root;
@@ -1,2 +1,2 @@
1
- import { RscPayload, renderRequest } from "../rsc-Cmvt9txp.js";
1
+ import { RscPayload, renderRequest } from "../rsc-DryRyKqc.js";
2
2
  export { RscPayload, renderRequest };
package/dist/extra/rsc.js CHANGED
@@ -3,10 +3,13 @@ import "../shared-CEyKoKAb.js";
3
3
  import "../encryption-utils-BDwwcMVT.js";
4
4
  import { loadServerAction } from "../rsc-DKA6wwTB.js";
5
5
  import { createTemporaryReferenceSet, decodeAction, decodeFormState, decodeReply, renderToReadableStream } from "../rsc-DHfL29FT.js";
6
- import "../rsc-DmPsJrxF.js";
6
+ import "../rsc-BIUd01vh.js";
7
7
  import { Fragment, jsx, jsxs } from "react/jsx-runtime";
8
8
 
9
9
  //#region src/extra/rsc.tsx
10
+ /**
11
+ * @deprecated Use `@vitejs/plugin-rsc/rsc` API instead.
12
+ */
10
13
  async function renderRequest(request, root, options) {
11
14
  function RscRoot() {
12
15
  const nonceMeta = options?.nonce && /* @__PURE__ */ jsx("meta", {
@@ -1,6 +1,10 @@
1
1
  import { ReactFormState } from "react-dom/client";
2
2
 
3
3
  //#region src/extra/ssr.d.ts
4
+
5
+ /**
6
+ * @deprecated Use `@vitejs/plugin-rsc/ssr` API instead.
7
+ */
4
8
  declare function renderHtml(rscStream: ReadableStream<Uint8Array>, options?: {
5
9
  formState?: ReactFormState;
6
10
  nonce?: string;
package/dist/extra/ssr.js CHANGED
@@ -2,13 +2,16 @@ import "../dist-DEF94lDJ.js";
2
2
  import "../shared-CEyKoKAb.js";
3
3
  import "../ssr-BOIYlvSn.js";
4
4
  import { createFromReadableStream } from "../ssr-D5pxP29F.js";
5
- import "../ssr-Do_Ok_bB.js";
6
- import { injectRSCPayload } from "../server-DS3S6m0g.js";
5
+ import "../ssr-DNwSdZ9T.js";
6
+ import { injectRSCPayload } from "../server-C50j-DRF.js";
7
7
  import React from "react";
8
8
  import { jsx } from "react/jsx-runtime";
9
9
  import ReactDomServer from "react-dom/server.edge";
10
10
 
11
11
  //#region src/extra/ssr.tsx
12
+ /**
13
+ * @deprecated Use `@vitejs/plugin-rsc/ssr` API instead.
14
+ */
12
15
  async function renderHtml(rscStream, options) {
13
16
  const [rscStream1, rscStream2] = rscStream.tee();
14
17
  let payload;
package/dist/index.d.ts CHANGED
@@ -1,16 +1,17 @@
1
- import { RscPluginOptions, vitePluginRsc } from "./plugin-Dg2agPFN.js";
1
+ import { RscPluginOptions, vitePluginRsc } from "./plugin-CCrsoChj.js";
2
2
  import MagicString from "magic-string";
3
3
  import { Program } from "estree";
4
4
 
5
5
  //#region src/transforms/hoist.d.ts
6
6
  declare function transformHoistInlineDirective(input: string, ast: Program, {
7
7
  runtime,
8
- directive,
9
8
  rejectNonAsyncFunction,
10
9
  ...options
11
10
  }: {
12
- runtime: (value: string, name: string) => string;
13
- directive: string;
11
+ runtime: (value: string, name: string, meta: {
12
+ directiveMatch: RegExpMatchArray;
13
+ }) => string;
14
+ directive: string | RegExp;
14
15
  rejectNonAsyncFunction?: boolean;
15
16
  encode?: (value: string) => string;
16
17
  decode?: (value: string) => string;
@@ -20,4 +21,4 @@ declare function transformHoistInlineDirective(input: string, ast: Program, {
20
21
  names: string[];
21
22
  };
22
23
  //#endregion
23
- export { RscPluginOptions, vitePluginRsc as default, transformHoistInlineDirective };
24
+ export { type RscPluginOptions, vitePluginRsc as default, transformHoistInlineDirective };
package/dist/index.js CHANGED
@@ -1,6 +1,6 @@
1
1
  import "./dist-DEF94lDJ.js";
2
2
  import "./plugin-CZbI4rhS.js";
3
- import { transformHoistInlineDirective, vitePluginRsc } from "./plugin-BZEsXXjV.js";
3
+ import { transformHoistInlineDirective, vitePluginRsc } from "./plugin-DgH7V82E.js";
4
4
  import "./encryption-utils-BDwwcMVT.js";
5
5
  import "./rpc-tGuLT8PD.js";
6
6
  import "./vite-utils-CcqBE-C4.js";
@@ -45,30 +45,30 @@ type RscPluginOptions = {
45
45
  keepUseCientProxy?: boolean;
46
46
  };
47
47
  declare function vitePluginRsc(rscPluginOptions?: RscPluginOptions): Plugin[];
48
- //
49
- // collect client reference dependency chunk for modulepreload
50
- //
48
+ declare class RuntimeAsset {
49
+ runtime: string;
50
+ constructor(value: string);
51
+ }
51
52
  type AssetsManifest = {
52
- bootstrapScriptContent: string;
53
+ bootstrapScriptContent: string | RuntimeAsset;
53
54
  clientReferenceDeps: Record<string, AssetDeps>;
54
- serverResources?: Record<string, {
55
- css: string[];
56
- }>;
55
+ serverResources?: Record<string, Pick<AssetDeps, "css">>;
57
56
  };
58
57
  type AssetDeps = {
58
+ js: (string | RuntimeAsset)[];
59
+ css: (string | RuntimeAsset)[];
60
+ };
61
+ type ResolvedAssetsManifest = {
62
+ bootstrapScriptContent: string;
63
+ clientReferenceDeps: Record<string, ResolvedAssetDeps>;
64
+ serverResources?: Record<string, Pick<ResolvedAssetDeps, "css">>;
65
+ };
66
+ type ResolvedAssetDeps = {
59
67
  js: string[];
60
68
  css: string[];
61
69
  };
62
- //
63
- // support findSourceMapURL
64
- // https://github.com/facebook/react/pull/29708
65
- // https://github.com/facebook/react/pull/30741
66
- //
67
70
  declare function vitePluginFindSourceMapURL(): Plugin[];
68
71
  declare function findSourceMapURL(server: ViteDevServer, filename: string, environmentName: string): Promise<object | undefined>;
69
- //
70
- // css support
71
- //
72
72
  declare function vitePluginRscCss(rscCssOptions?: Pick<RscPluginOptions, "rscCssTransform">): Plugin[];
73
73
  declare function transformRscCssExport(options: {
74
74
  ast: Awaited<ReturnType<typeof parseAstAsync>>;
@@ -85,4 +85,4 @@ declare function transformRscCssExport(options: {
85
85
  */
86
86
  declare function __fix_cloudflare(): Plugin;
87
87
  //#endregion
88
- export { AssetDeps, AssetsManifest, RscPluginOptions, __fix_cloudflare, findSourceMapURL, transformRscCssExport, vitePluginFindSourceMapURL, vitePluginRsc, vitePluginRscCss };
88
+ export { AssetDeps, AssetsManifest, ResolvedAssetDeps, ResolvedAssetsManifest, RscPluginOptions, __fix_cloudflare, findSourceMapURL, transformRscCssExport, vitePluginFindSourceMapURL, vitePluginRsc, vitePluginRscCss };
@@ -17,15 +17,10 @@ import { crawlFrameworkPkgs } from "vitefu";
17
17
  import { walk } from "estree-walker";
18
18
  import { analyze, extract_names } from "periscopic";
19
19
 
20
- //#region src/transforms/utils.ts
21
- function hasDirective(body, directive) {
22
- return !!body.find((stmt) => stmt.type === "ExpressionStatement" && stmt.expression.type === "Literal" && typeof stmt.expression.value === "string" && stmt.expression.value === directive);
23
- }
24
-
25
- //#endregion
26
20
  //#region src/transforms/hoist.ts
27
- function transformHoistInlineDirective(input, ast, { runtime, directive, rejectNonAsyncFunction,...options }) {
21
+ function transformHoistInlineDirective(input, ast, { runtime, rejectNonAsyncFunction,...options }) {
28
22
  const output = new MagicString(input);
23
+ const directive = typeof options.directive === "string" ? exactRegex(options.directive) : options.directive;
29
24
  walk(ast, { enter(node) {
30
25
  if (node.type === "ExportAllDeclaration") this.remove();
31
26
  if (node.type === "ExportNamedDeclaration" && !node.declaration) this.remove();
@@ -33,7 +28,9 @@ function transformHoistInlineDirective(input, ast, { runtime, directive, rejectN
33
28
  const analyzed = analyze(ast);
34
29
  const names = [];
35
30
  walk(ast, { enter(node, parent) {
36
- if ((node.type === "FunctionExpression" || node.type === "FunctionDeclaration" || node.type === "ArrowFunctionExpression") && node.body.type === "BlockStatement" && hasDirective(node.body.body, directive)) {
31
+ if ((node.type === "FunctionExpression" || node.type === "FunctionDeclaration" || node.type === "ArrowFunctionExpression") && node.body.type === "BlockStatement") {
32
+ const match = matchDirective(node.body.body, directive);
33
+ if (!match) return;
37
34
  if (!node.async && rejectNonAsyncFunction) throw Object.assign(/* @__PURE__ */ new Error(`"${directive}" doesn't allow non async function`), { pos: node.start });
38
35
  const scope = analyzed.map.get(node);
39
36
  tinyassert(scope);
@@ -54,7 +51,7 @@ function transformHoistInlineDirective(input, ast, { runtime, directive, rejectN
54
51
  output.update(node.start, node.body.start, `\n;${options.noExport ? "" : "export "}${node.async ? "async " : ""}function ${newName}(${newParams}) `);
55
52
  output.appendLeft(node.end, `;\n/* #__PURE__ */ Object.defineProperty(${newName}, "name", { value: ${JSON.stringify(originalName)} });\n`);
56
53
  output.move(node.start, node.end, input.length);
57
- let newCode = `/* #__PURE__ */ ${runtime(newName, newName)}`;
54
+ let newCode = `/* #__PURE__ */ ${runtime(newName, newName, { directiveMatch: match })}`;
58
55
  if (bindVars.length > 0) {
59
56
  const bindArgs = options.encode ? options.encode("[" + bindVars.join(", ") + "]") : bindVars.join(", ");
60
57
  newCode = `${newCode}.bind(null, ${bindArgs})`;
@@ -74,6 +71,13 @@ function transformHoistInlineDirective(input, ast, { runtime, directive, rejectN
74
71
  names
75
72
  };
76
73
  }
74
+ const exactRegex = (s) => /* @__PURE__ */ new RegExp("^" + s.replace(/[-[\]{}()*+?.,\\^$|#\s]/g, "\\$&") + "$");
75
+ function matchDirective(body, directive) {
76
+ for (const stable of body) if (stable.type === "ExpressionStatement" && stable.expression.type === "Literal" && typeof stable.expression.value === "string") {
77
+ const match = stable.expression.value.match(directive);
78
+ if (match) return match;
79
+ }
80
+ }
77
81
 
78
82
  //#endregion
79
83
  //#region src/transforms/wrap-export.ts
@@ -197,6 +201,12 @@ function transformWrapExport(input, ast, options) {
197
201
  };
198
202
  }
199
203
 
204
+ //#endregion
205
+ //#region src/transforms/utils.ts
206
+ function hasDirective(body, directive) {
207
+ return !!body.find((stmt) => stmt.type === "ExpressionStatement" && stmt.expression.type === "Literal" && typeof stmt.expression.value === "string" && stmt.expression.value === directive);
208
+ }
209
+
200
210
  //#endregion
201
211
  //#region src/transforms/proxy-export.ts
202
212
  function transformDirectiveProxyExport(ast, options) {
@@ -391,6 +401,24 @@ function vitePluginRsc(rscPluginOptions = {}) {
391
401
  sharedPlugins: true,
392
402
  sharedConfigBuild: true,
393
403
  async buildApp(builder) {
404
+ if (!builder.environments.ssr?.config.build.rollupOptions.input) {
405
+ isScanBuild = true;
406
+ builder.environments.rsc.config.build.write = false;
407
+ builder.environments.client.config.build.write = false;
408
+ await builder.build(builder.environments.rsc);
409
+ await builder.build(builder.environments.client);
410
+ isScanBuild = false;
411
+ builder.environments.rsc.config.build.write = true;
412
+ builder.environments.client.config.build.write = true;
413
+ await builder.build(builder.environments.rsc);
414
+ clientReferenceMetaMap = sortObject(clientReferenceMetaMap);
415
+ serverResourcesMetaMap = sortObject(serverResourcesMetaMap);
416
+ await builder.build(builder.environments.client);
417
+ const assetsManifestCode = `export default ${serializeValueWithRuntime(buildAssetsManifest)}`;
418
+ const manifestPath = path.join(builder.environments.rsc.config.build.outDir, BUILD_ASSETS_MANIFEST_NAME);
419
+ fs.writeFileSync(manifestPath, assetsManifestCode);
420
+ return;
421
+ }
394
422
  isScanBuild = true;
395
423
  builder.environments.rsc.config.build.write = false;
396
424
  builder.environments.ssr.config.build.write = false;
@@ -428,7 +456,7 @@ function vitePluginRsc(rscPluginOptions = {}) {
428
456
  const resolved = await environment.pluginContainer.resolveId(source);
429
457
  assert(resolved, `[vite-rsc] failed to resolve server handler '${source}'`);
430
458
  const mod = await environment.runner.import(resolved.id);
431
- createRequestListener(mod.default)(req, res);
459
+ await createRequestListener(mod.default)(req, res);
432
460
  } catch (e) {
433
461
  next(e);
434
462
  }
@@ -445,8 +473,9 @@ function vitePluginRsc(rscPluginOptions = {}) {
445
473
  const entryFile = path.join(config.environments[options.environmentName].build.outDir, `${options.entryName}.js`);
446
474
  const entry = pathToFileURL(entryFile).href;
447
475
  const mod = await import(
448
- /* @vite-ignore */
449
- entry);
476
+ /* @vite-ignore */
477
+ entry
478
+ );
450
479
  const handler = createRequestListener(mod.default);
451
480
  server$1.middlewares.use((req, _res, next) => {
452
481
  delete req.headers["accept-encoding"];
@@ -455,7 +484,7 @@ function vitePluginRsc(rscPluginOptions = {}) {
455
484
  return () => {
456
485
  server$1.middlewares.use(async (req, res, next) => {
457
486
  try {
458
- handler(req, res);
487
+ await handler(req, res);
459
488
  } catch (e) {
460
489
  next(e);
461
490
  }
@@ -614,7 +643,7 @@ function vitePluginRsc(rscPluginOptions = {}) {
614
643
  assert(this.environment.mode === "dev");
615
644
  const entryUrl = assetsURL("@id/__x00__" + VIRTUAL_ENTRIES.browser);
616
645
  const manifest = {
617
- bootstrapScriptContent: `import(${JSON.stringify(entryUrl)})`,
646
+ bootstrapScriptContent: `import(${serializeValueWithRuntime(entryUrl)})`,
618
647
  clientReferenceDeps: {}
619
648
  };
620
649
  return `export default ${JSON.stringify(manifest, null, 2)}`;
@@ -652,8 +681,11 @@ function vitePluginRsc(rscPluginOptions = {}) {
652
681
  };
653
682
  clientReferenceDeps[meta.referenceKey] = assetsURLOfDeps(mergeAssetDeps(deps, entry.deps));
654
683
  }
684
+ let bootstrapScriptContent;
685
+ if (typeof entryUrl === "string") bootstrapScriptContent = `import(${JSON.stringify(entryUrl)})`;
686
+ else bootstrapScriptContent = new RuntimeAsset(`"import(" + JSON.stringify(${entryUrl.runtime}) + ")"`);
655
687
  buildAssetsManifest = {
656
- bootstrapScriptContent: `import(${JSON.stringify(entryUrl)})`,
688
+ bootstrapScriptContent,
657
689
  clientReferenceDeps,
658
690
  serverResources
659
691
  };
@@ -670,7 +702,7 @@ function vitePluginRsc(rscPluginOptions = {}) {
670
702
  },
671
703
  writeBundle() {
672
704
  if (this.environment.name === "ssr") {
673
- const assetsManifestCode = `export default ${JSON.stringify(buildAssetsManifest, null, 2)}`;
705
+ const assetsManifestCode = `export default ${serializeValueWithRuntime(buildAssetsManifest)}`;
674
706
  for (const name of ["ssr", "rsc"]) {
675
707
  const manifestPath = path.join(config.environments[name].build.outDir, BUILD_ASSETS_MANIFEST_NAME);
676
708
  fs.writeFileSync(manifestPath, assetsManifestCode);
@@ -1056,13 +1088,50 @@ function generateDynamicImportCode(map) {
1056
1088
  let code = Object.entries(map).map(([key, id]) => `${JSON.stringify(key)}: () => import(${JSON.stringify(id)}),`).join("\n");
1057
1089
  return `export default {${code}};\n`;
1058
1090
  }
1091
+ var RuntimeAsset = class {
1092
+ runtime;
1093
+ constructor(value) {
1094
+ this.runtime = value;
1095
+ }
1096
+ };
1097
+ function serializeValueWithRuntime(value) {
1098
+ const replacements = [];
1099
+ let result = JSON.stringify(value, (_key, value$1) => {
1100
+ if (value$1 instanceof RuntimeAsset) {
1101
+ const placeholder = `__runtime_placeholder_${replacements.length}__`;
1102
+ replacements.push([placeholder, value$1.runtime]);
1103
+ return placeholder;
1104
+ }
1105
+ return value$1;
1106
+ }, 2);
1107
+ for (const [placeholder, runtime] of replacements) result = result.replace(`"${placeholder}"`, runtime);
1108
+ return result;
1109
+ }
1059
1110
  function assetsURL(url) {
1111
+ if (config.command === "build" && typeof config.experimental?.renderBuiltUrl === "function") {
1112
+ const result = config.experimental.renderBuiltUrl(url, {
1113
+ type: "asset",
1114
+ hostType: "js",
1115
+ ssr: true,
1116
+ hostId: ""
1117
+ });
1118
+ if (typeof result === "object") {
1119
+ if (result.runtime) return new RuntimeAsset(result.runtime);
1120
+ assert(!result.relative, "\"result.relative\" not supported on renderBuiltUrl() for RSC");
1121
+ } else if (result) return result;
1122
+ }
1060
1123
  return config.base + url;
1061
1124
  }
1062
1125
  function assetsURLOfDeps(deps) {
1063
1126
  return {
1064
- js: deps.js.map((href) => assetsURL(href)),
1065
- css: deps.css.map((href) => assetsURL(href))
1127
+ js: deps.js.map((href) => {
1128
+ assert(typeof href === "string");
1129
+ return assetsURL(href);
1130
+ }),
1131
+ css: deps.css.map((href) => {
1132
+ assert(typeof href === "string");
1133
+ return assetsURL(href);
1134
+ })
1066
1135
  };
1067
1136
  }
1068
1137
  function mergeAssetDeps(a, b) {
@@ -1234,7 +1303,7 @@ function vitePluginRscCss(rscCssOptions) {
1234
1303
  const result = collectCss(server.environments.ssr, mod.id);
1235
1304
  for (const file of [mod.file, ...result.visitedFiles]) this.addWatchFile(file);
1236
1305
  const hrefs = result.hrefs.map((href) => assetsURL(href.slice(1)));
1237
- return `export default ${JSON.stringify(hrefs)}`;
1306
+ return `export default ${serializeValueWithRuntime(hrefs)}`;
1238
1307
  }
1239
1308
  }
1240
1309
  },
@@ -1296,7 +1365,7 @@ function vitePluginRscCss(rscCssOptions) {
1296
1365
  css: cssHrefs,
1297
1366
  js: jsHrefs
1298
1367
  });
1299
- return generateResourcesCode(JSON.stringify(deps, null, 2));
1368
+ return generateResourcesCode(serializeValueWithRuntime(deps));
1300
1369
  } else {
1301
1370
  const key = normalizePath(path.relative(config.root, importer));
1302
1371
  serverResourcesMetaMap[importer] = { key };
package/dist/plugin.d.ts CHANGED
@@ -1,2 +1,2 @@
1
- import { AssetDeps, AssetsManifest, RscPluginOptions, __fix_cloudflare, findSourceMapURL, transformRscCssExport, vitePluginFindSourceMapURL, vitePluginRsc, vitePluginRscCss } from "./plugin-Dg2agPFN.js";
2
- export { AssetDeps, AssetsManifest, RscPluginOptions, __fix_cloudflare, vitePluginRsc as default, findSourceMapURL, transformRscCssExport, vitePluginFindSourceMapURL, vitePluginRscCss };
1
+ import { AssetDeps, AssetsManifest, ResolvedAssetDeps, ResolvedAssetsManifest, RscPluginOptions, __fix_cloudflare, findSourceMapURL, transformRscCssExport, vitePluginFindSourceMapURL, vitePluginRsc, vitePluginRscCss } from "./plugin-CCrsoChj.js";
2
+ export { AssetDeps, AssetsManifest, ResolvedAssetDeps, ResolvedAssetsManifest, RscPluginOptions, __fix_cloudflare, vitePluginRsc as default, findSourceMapURL, transformRscCssExport, vitePluginFindSourceMapURL, vitePluginRscCss };
package/dist/plugin.js CHANGED
@@ -1,6 +1,6 @@
1
1
  import "./dist-DEF94lDJ.js";
2
2
  import "./plugin-CZbI4rhS.js";
3
- import { __fix_cloudflare, findSourceMapURL, transformRscCssExport, vitePluginFindSourceMapURL, vitePluginRsc, vitePluginRscCss } from "./plugin-BZEsXXjV.js";
3
+ import { __fix_cloudflare, findSourceMapURL, transformRscCssExport, vitePluginFindSourceMapURL, vitePluginRsc, vitePluginRscCss } from "./plugin-DgH7V82E.js";
4
4
  import "./encryption-utils-BDwwcMVT.js";
5
5
  import "./rpc-tGuLT8PD.js";
6
6
  import "./vite-utils-CcqBE-C4.js";
@@ -1,4 +1,4 @@
1
1
  import { CallServerCallback } from "../index-BHqtj9tT.js";
2
2
  import { setRequireModule } from "../browser-Dw18EFgE.js";
3
- import { callServer, createFromFetch, createFromReadableStream, createServerReference, createTemporaryReferenceSet, encodeReply, findSourceMapURL, setServerCallback } from "../browser-DjnGtEmB.js";
3
+ import { callServer, createFromFetch, createFromReadableStream, createServerReference, createTemporaryReferenceSet, encodeReply, findSourceMapURL, setServerCallback } from "../browser-CeSkQWD5.js";
4
4
  export { CallServerCallback, callServer, createFromFetch, createFromReadableStream, createServerReference, createTemporaryReferenceSet, encodeReply, findSourceMapURL, setRequireModule, setServerCallback };
@@ -28,8 +28,9 @@ initialize();
28
28
  function initialize() {
29
29
  setRequireModule({ load: async (id) => {
30
30
  if (!import.meta.env.__vite_rsc_build__) return import(
31
- /* @vite-ignore */
32
- id);
31
+ /* @vite-ignore */
32
+ id
33
+ );
33
34
  else {
34
35
  const import_ = serverReferences[id];
35
36
  if (!import_) throw new Error(`server reference not found '${id}'`);
@@ -6,6 +6,9 @@ type RscPayload = {
6
6
  formState?: ReactFormState;
7
7
  returnValue?: unknown;
8
8
  };
9
+ /**
10
+ * @deprecated Use `@vitejs/plugin-rsc/rsc` API instead.
11
+ */
9
12
  declare function renderRequest(request: Request, root: React.ReactNode, options?: {
10
13
  nonce?: string;
11
14
  }): Promise<Response>;
@@ -1,4 +1,5 @@
1
1
  //#region src/rsc-html-stream/browser.d.ts
2
+ /** @deprecated use `rsc-html-stream/client` instead */
2
3
  declare const getRscStreamFromHtml: () => ReadableStream<Uint8Array>;
3
4
  //#endregion
4
5
  export { getRscStreamFromHtml };
@@ -1,6 +1,7 @@
1
- import { rscStream } from "../client-edAdk2GF.js";
1
+ import { rscStream } from "../client-CPc-spDn.js";
2
2
 
3
3
  //#region src/rsc-html-stream/browser.ts
4
+ /** @deprecated use `rsc-html-stream/client` instead */
4
5
  const getRscStreamFromHtml = () => rscStream;
5
6
 
6
7
  //#endregion
@@ -1,4 +1,5 @@
1
1
  //#region src/rsc-html-stream/ssr.d.ts
2
+ /** @deprecated use `rsc-html-stream/server` instead */
2
3
  declare const injectRscStreamToHtml: (stream: ReadableStream<Uint8Array>, options?: {
3
4
  nonce?: string;
4
5
  }) => TransformStream<Uint8Array, Uint8Array>;
@@ -1,6 +1,7 @@
1
- import { injectRSCPayload } from "../server-DS3S6m0g.js";
1
+ import { injectRSCPayload } from "../server-C50j-DRF.js";
2
2
 
3
3
  //#region src/rsc-html-stream/ssr.ts
4
+ /** @deprecated use `rsc-html-stream/server` instead */
4
5
  const injectRscStreamToHtml = (stream, options) => injectRSCPayload(stream, options);
5
6
 
6
7
  //#endregion
package/dist/rsc.d.ts CHANGED
@@ -3,10 +3,6 @@ import { createClientManifest, createServerManifest, loadServerAction, setRequir
3
3
  import { createClientTemporaryReferenceSet, createFromReadableStream, createTemporaryReferenceSet, decodeAction, decodeFormState, decodeReply, encodeReply, registerClientReference, registerServerReference, renderToReadableStream } from "./rsc-DgrejoNf.js";
4
4
 
5
5
  //#region src/utils/encryption-runtime.d.ts
6
- // based on
7
- // https://github.com/parcel-bundler/parcel/blob/9855f558a69edde843b1464f39a6010f6b421efe/packages/transformers/js/src/rsc-utils.js
8
- // https://github.com/vercel/next.js/blob/c10c10daf9e95346c31c24dc49d6b7cda48b5bc8/packages/next/src/server/app-render/encryption.ts
9
- // https://github.com/vercel/next.js/pull/56377
10
6
  declare function encryptActionBoundArgs(originalValue: unknown): Promise<string>;
11
7
  declare function decryptActionBoundArgs(encrypted: ReturnType<typeof encryptActionBoundArgs>): Promise<unknown>;
12
8
  //#endregion
package/dist/rsc.js CHANGED
@@ -3,6 +3,6 @@ import "./shared-CEyKoKAb.js";
3
3
  import "./encryption-utils-BDwwcMVT.js";
4
4
  import { createClientManifest, createServerManifest, loadServerAction, setRequireModule } from "./rsc-DKA6wwTB.js";
5
5
  import { createClientTemporaryReferenceSet, createFromReadableStream, createTemporaryReferenceSet, decodeAction, decodeFormState, decodeReply, encodeReply, registerClientReference, registerServerReference, renderToReadableStream } from "./rsc-DHfL29FT.js";
6
- import { decryptActionBoundArgs, encryptActionBoundArgs } from "./rsc-DmPsJrxF.js";
6
+ import { decryptActionBoundArgs, encryptActionBoundArgs } from "./rsc-BIUd01vh.js";
7
7
 
8
8
  export { createClientManifest, createClientTemporaryReferenceSet, createFromReadableStream, createServerManifest, createTemporaryReferenceSet, decodeAction, decodeFormState, decodeReply, decryptActionBoundArgs, encodeReply, encryptActionBoundArgs, loadServerAction, registerClientReference, registerServerReference, renderToReadableStream, setRequireModule };
@@ -1,4 +1,4 @@
1
- //#region ../../node_modules/.pnpm/rsc-html-stream@0.0.6/node_modules/rsc-html-stream/server.js
1
+ //#region ../../node_modules/.pnpm/rsc-html-stream@0.0.7/node_modules/rsc-html-stream/server.js
2
2
  const encoder = new TextEncoder();
3
3
  const trailer = "</body></html>";
4
4
  function injectRSCPayload(rscStream, options) {
@@ -28,7 +28,13 @@ function injectRSCPayload(rscStream, options) {
28
28
  buffered.push(chunk);
29
29
  if (timeout) return;
30
30
  timeout = setTimeout(async () => {
31
- flushBufferedChunks(controller);
31
+ try {
32
+ flushBufferedChunks(controller);
33
+ } catch (e) {
34
+ controller.error(e);
35
+ resolveFlightDataPromise();
36
+ return;
37
+ }
32
38
  if (!startedRSC) {
33
39
  startedRSC = true;
34
40
  writeRSCStream(rscStream, controller, nonce).catch((err) => controller.error(err)).then(resolveFlightDataPromise);
@@ -9,11 +9,13 @@ function initialize() {
9
9
  setRequireModule({ load: async (id) => {
10
10
  if (!import.meta.env.__vite_rsc_build__) {
11
11
  const mod = await import(
12
- /* @vite-ignore */
13
- id);
12
+ /* @vite-ignore */
13
+ id
14
+ );
14
15
  const modCss = await import(
15
- /* @vite-ignore */
16
- "/@id/__x00__virtual:vite-rsc/css/dev-ssr/" + id);
16
+ /* @vite-ignore */
17
+ "/@id/__x00__virtual:vite-rsc/css/dev-ssr/" + id
18
+ );
17
19
  return wrapResourceProxy(mod, {
18
20
  js: [],
19
21
  css: modCss.default
package/dist/ssr.js CHANGED
@@ -2,6 +2,6 @@ import "./dist-DEF94lDJ.js";
2
2
  import "./shared-CEyKoKAb.js";
3
3
  import { createServerConsumerManifest, setRequireModule } from "./ssr-BOIYlvSn.js";
4
4
  import { callServer, createFromReadableStream, createServerReference, findSourceMapURL } from "./ssr-D5pxP29F.js";
5
- import "./ssr-Do_Ok_bB.js";
5
+ import "./ssr-DNwSdZ9T.js";
6
6
 
7
7
  export { callServer, createFromReadableStream, createServerConsumerManifest, createServerReference, findSourceMapURL, setRequireModule };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@vitejs/plugin-rsc",
3
- "version": "0.4.11",
3
+ "version": "0.4.13",
4
4
  "description": "React Server Components (RSC) support for Vite.",
5
5
  "keywords": [
6
6
  "vite",
@@ -48,19 +48,19 @@
48
48
  },
49
49
  "devDependencies": {
50
50
  "@hiogawa/utils": "^1.7.0",
51
- "@playwright/test": "^1.53.2",
51
+ "@playwright/test": "^1.54.1",
52
52
  "@tsconfig/strictest": "^2.0.5",
53
53
  "@types/estree": "^1.0.8",
54
- "@types/node": "^22.16.0",
54
+ "@types/node": "^22.16.5",
55
55
  "@types/react": "^19.1.8",
56
56
  "@types/react-dom": "^19.1.6",
57
57
  "@vitejs/plugin-react": "workspace:*",
58
58
  "react": "^19.1.0",
59
59
  "react-dom": "^19.1.0",
60
60
  "react-server-dom-webpack": "^19.1.0",
61
- "rsc-html-stream": "^0.0.6",
61
+ "rsc-html-stream": "^0.0.7",
62
62
  "tinyexec": "^1.0.1",
63
- "tsdown": "^0.12.9"
63
+ "tsdown": "^0.13.0"
64
64
  },
65
65
  "peerDependencies": {
66
66
  "react": "*",