diff --git a/packages/rsc/README.md b/packages/rsc/README.md index e25f00e9c..1a8c7fbdb 100644 --- a/packages/rsc/README.md +++ b/packages/rsc/README.md @@ -1,7 +1,6 @@ # @hiogawa/vite-rsc This package provides [React Server Components](https://react.dev/reference/rsc/server-components) (RSC) support for Vite. -Any feedback is welcome, please feel free to share an idea in [the discussion](https://github.com/hi-ogawa/vite-plugins/discussions/979). ## Features @@ -22,12 +21,14 @@ npx degit hi-ogawa/vite-plugins/packages/rsc/examples/starter my-app - [`./examples/starter`](./examples/starter) - This example provides an in-depth overview of API with inline comments to explain how they function within RSC-powered React application. -- [`./examples/starter-cf-single`](./examples/starter-cf-single) - - [`@cloudflare/vite-plugin`](https://github.com/cloudflare/workers-sdk/tree/main/packages/vite-plugin-cloudflare) integration example with a single worker setup. - [`./examples/react-router`](./examples/react-router) - - This demonstrates how to integrate [experimental React Router RSC API](https://remix.run/blog/rsc-preview) with this plugin. It also includes `@cloudflare/vite-plugin` integration with multi workers setup. + - This demonstrates how to integrate [experimental React Router RSC API](https://remix.run/blog/rsc-preview) with this plugin. + It also includes `@cloudflare/vite-plugin` integration. - [`./examples/basic`](./examples/basic) - - This is mainly used for e2e testing and include various edge cases. It also uses a high level `@hiogawa/vite-rsc/extra/{rsc,ssr,browser}` API for quick setup. + - This is mainly used for e2e testing and include various advanced RSC usages (e.g. `"use cache"` example). + It also uses a high level `@hiogawa/vite-rsc/extra/{rsc,ssr,browser}` API for quick setup. +- [`./examples/ssg`](./examples/ssg) + - Static site generation (SSG) example with MDX and client components for interactivity. ## Basic Concepts @@ -68,9 +69,10 @@ graph TD - [`vite.config.ts`](./examples/starter/vite.config.ts) ```js -import rsc from "@hiogawa/vite-rsc/plugin"; +import rsc from "@hiogawa/vite-rsc"; +import { defineConfig } from "vite"; -export default defineConfig() { +export default defineConfig({ plugins: [ // add plugin rsc(), @@ -123,7 +125,7 @@ export default defineConfig() { }, }, }, -} +}); ``` - [`entry.rsc.tsx`](./examples/starter/src/framework/entry.rsc.tsx) @@ -141,14 +143,14 @@ export default async function handler(request: Request): Promise { if (request.url.endsWith(".rsc")) { return new Response(rscStream, { headers: { - 'Content-type': 'text/html' + 'Content-type': 'text/x-component;charset=utf-8' } - }) + }); } // delegate to SSR environment for html rendering - // `loadSsrModule` is a helper API provided by the plugin for multi environment interaction. - const ssrEntry = await import.meta.viteRsc.loadSsrModule(); + // `loadModule` is a helper API provided by the plugin for multi environment interaction. + const ssrEntry = await import.meta.viteRsc.loadModule("ssr", "index"); const htmlStream = await ssrEntry.handleSsr(rscStream); // respond html @@ -176,7 +178,7 @@ export async function handleSsr(rscStream: ReadableStream) { // render html (traditional SSR) const htmlStream = ReactDOMServer.renderToReadableStream(root, { bootstrapScriptContent, - }) + }); return htmlStream; } @@ -190,7 +192,7 @@ import * as ReactDOMClient from "react-dom/client"; async function main() { // fetch and deserialize RSC stream back to React VDOM - const rscResponse = await fetch(window.location.href + ".rsc"); + const rscResponse = await fetch(window.location.href + ".rsc); const root = await ReactClient.createFromReadableStream(rscResponse.body); // hydration (traditional CSR) @@ -325,12 +327,6 @@ function __Page(props) { export { __Page as Page } ``` -Underlying transform utility is available from `@hiogawa/vite-rsc/plugin`: - -```tsx -import { transformRscCssExport } from "@hiogawa/vite-rsc/plugin"; -``` - ### available on `ssr` environment #### `import.meta.viteRsc.loadBootstrapScriptContent("index")` @@ -363,10 +359,10 @@ import.meta.hot.on("rsc:update", async () => { ## Plugin API -### `@hiogawa/vite-rsc/plugin` +### `@hiogawa/vite-rsc` ```js -import rsc from "@hiogawa/vite-rsc/plugin"; +import rsc from "@hiogawa/vite-rsc"; import { defineConfig } from "vite"; export default defineConfig({ @@ -420,3 +416,14 @@ This is a wrapper of `react-server-dom` API and helper API to setup a minimal RS ### `@hiogawa/vite-rsc/extra/browser` - `hydrate` + +## Credits + +This project builds on fundamental techniques and insights from pioneering Vite RSC implementations. +Additionally, Parcel and React Router's work on standardizing the RSC bundler/app responsibility has guided this plugin's API design: + +- [Waku](https://github.com/wakujs/waku) +- [@lazarv/react-server](https://github.com/lazarv/react-server) +- [@jacob-ebey/vite-react-server-dom](https://github.com/jacob-ebey/vite-plugins/tree/main/packages/vite-react-server-dom) +- [React Router RSC](https://remix.run/blog/rsc-preview) +- [Parcel RSC](https://parceljs.org/recipes/rsc)