Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
149 changes: 149 additions & 0 deletions docs/migration-vite-rsc-to-vitejs-plugin-rsc.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,149 @@
# Migration Plan: @hiogawa/vite-rsc → @vitejs/plugin-rsc

## Status: In Progress

This document tracks the migration of `@hiogawa/react-server` from `@hiogawa/vite-rsc` to `@vitejs/plugin-rsc`.

## Completed Changes

### 1. Dependency Update
- Replaced `@hiogawa/vite-rsc@^0.4.9` with `@vitejs/plugin-rsc@^0.5.9`

### 2. Import Path Updates

| Old Path | New Path |
|----------|----------|
| `@hiogawa/vite-rsc/react/rsc` | `@vitejs/plugin-rsc/rsc` |
| `@hiogawa/vite-rsc/react/ssr` | `@vitejs/plugin-rsc/ssr` |
| `@hiogawa/vite-rsc/react/browser` | `@vitejs/plugin-rsc/browser` |
| `@hiogawa/vite-rsc/core/plugin` | `@vitejs/plugin-rsc` (default export) |

### 3. Removed Custom Transform Plugins

The following plugins were removed since `@vitejs/plugin-rsc` handles transforms:
- `vitePluginServerUseClient` - "use client" transform in RSC env
- `vitePluginServerUseServer` - "use server" transform in RSC env
- `vitePluginClientUseClient` - client reference handling
- `vitePluginClientUseServer` - "use server" transform in client env

### 4. Removed Manual Initialization

`@vitejs/plugin-rsc` auto-initializes `setRequireModule` when imported:
- Removed `initializeReactServer()` from `entry/server.tsx`
- Removed `initializeReactClientSsr()` from `entry/ssr.tsx`
- Removed `initializeReactClientBrowser()` from `entry/browser.tsx`
- Simplified `features/client-component/*.tsx` and `features/server-action/*.tsx`

### 5. Simplified PluginStateManager

Removed unused properties:
- `clientReferenceMap` - was populated by removed transform plugins
- `serverReferenceMap` - was populated by removed transform plugins
- `nodeModules.useClient` - was used for node_modules client references
- `serverIds` - was used for HMR tracking
- `shouldReloadRsc()` - depended on removed maps
- `normalizeReferenceId()` - was used by transform plugins
- `prepareDestinationManifest` - was used for client reference preloading

### 6. Dropped Client Reference Preloading

Native RSC doesn't support client reference preloading. Removed:
- `prepareDestinationManifest` generation in `router/plugin.ts`
- Client reference CSS collection in `assets/plugin.ts`

TODO: https://github.com/wakujs/waku/issues/1656

### 7. Simplified HMR Logic

Removed custom RSC HMR event sending since `@vitejs/plugin-rsc` handles `rsc:update` events.

---

### 8. Removed Framework Plugins Now Handled by @vitejs/plugin-rsc

The following framework plugins were removed since `@vitejs/plugin-rsc` handles their functionality:

| Plugin | Reason |
|--------|--------|
| `rscParentPlugin` | RSC environment setup handled by plugin (replaced with `frameworkConfigPlugin`) |
| `buildOrchestrationPlugin` | Build orchestration handled by plugin |
| `inject-async-local-storage` | Async local storage injection handled by plugin |
| `validateImportPlugin` | Import validation handled by plugin |
| `serverDepsConfigPlugin()` | Server deps config handled by plugin |
| `serverAssetsPluginServer` | Server assets handling handled by plugin |
| `virtual:react-server-build` | Replaced with `import.meta.viteRsc.loadModule("rsc", "index")` |

### 9. Deleted Plugin Files

- `packages/react-server/src/features/client-component/plugin.ts`
- `packages/react-server/src/features/server-action/plugin.tsx`

### 10. Updated Build Phase Detection

Replaced `manager.buildType` checks with `this.environment.name` checks:
- `router/plugin.ts` - uses `this.environment.name === "rsc"`, `"client"`, `"ssr"`
- `prerender/plugin.ts` - uses `this.environment.name === "ssr"`
- `assets/plugin.ts` - uses `this.environment?.mode === "dev"`

---

## Remaining Work

### E2E Testing Required

E2E tests need to verify:
- Dev server works
- Production build works
- HMR works (both server and client components)
- Server actions work
- SSR streaming works
- File-based routing works

---

## Architecture Comparison

### Before (with @hiogawa/vite-rsc)

```
@hiogawa/react-server
├── Plugin layer
│ ├── rscCore() from vite-rsc - core RSC environment
│ ├── vitePluginFindSourceMapURL() - error overlay
│ ├── vitePluginServerUseClient - "use client" transform
│ ├── vitePluginServerUseServer - "use server" transform
│ ├── vitePluginClientUseClient - client reference virtual module
│ ├── vitePluginClientUseServer - "use server" in client
│ ├── buildOrchestrationPlugin - 4-phase build
│ └── Framework plugins (router, prerender, assets, etc.)
├── Entry points
│ ├── Manual setRequireModule initialization
│ └── Framework-specific routing/rendering
└── Framework features
└── File-based routing, metadata, error handling, etc.
```

### After (with @vitejs/plugin-rsc)

```
@hiogawa/react-server
├── Plugin layer
│ ├── rsc() from @vitejs/plugin-rsc - handles ALL RSC bundling
│ ├── frameworkConfigPlugin - framework-specific config (outDir, entries)
│ └── Framework plugins (router, prerender, assets, etc.)
├── Entry points
│ ├── Auto-initialized by plugin imports
│ ├── import.meta.viteRsc.loadModule for cross-environment imports
│ └── Framework-specific routing/rendering
└── Framework features
└── File-based routing, metadata, error handling, etc.
```

---

## Reference

- `@vitejs/plugin-rsc` source: `/home/hiroshi/code/others/vite-plugin-react/packages/plugin-rsc`
- Starter example: `/home/hiroshi/code/others/vite-plugin-react/packages/plugin-rsc/examples/starter`
- SSG/Prerender example: `/home/hiroshi/code/others/vite-plugin-react/packages/plugin-rsc/examples/ssg`
- Plugin API: `getPluginApi(config)` returns `{ manager: RscPluginManager }`
2 changes: 1 addition & 1 deletion packages/react-server/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,7 @@
},
"dependencies": {
"@hiogawa/transforms": "workspace:*",
"@hiogawa/vite-rsc": "^0.4.9",
"@vitejs/plugin-rsc": "^0.5.9",
"es-module-lexer": "^1.6.0",
"fast-glob": "^3.3.3",
"vitefu": "^1.0.5"
Expand Down
5 changes: 1 addition & 4 deletions packages/react-server/src/entry/browser.tsx
Original file line number Diff line number Diff line change
@@ -1,11 +1,10 @@
import * as virtualClientRoutes from "virtual:client-routes";
import { createDebug, memoize, tinyassert } from "@hiogawa/utils";
import * as ReactClient from "@hiogawa/vite-rsc/react/browser";
import type { RouterHistory } from "@tanstack/history";
import * as ReactClient from "@vitejs/plugin-rsc/browser";
import React from "react";
import ReactDOMClient from "react-dom/client";
import { rscStream } from "rsc-html-stream/client";
import { initializeReactClientBrowser } from "../features/client-component/browser";
import { ErrorBoundary } from "../features/error/error-boundary";
import { DefaultGlobalErrorPage } from "../features/error/global-error";
import {
Expand Down Expand Up @@ -34,8 +33,6 @@ import { createError } from "../server";
const debug = createDebug("react-server:browser");

async function start() {
initializeReactClientBrowser();

const history = createEncodedBrowserHistory();
const router = new Router(history);

Expand Down
9 changes: 2 additions & 7 deletions packages/react-server/src/entry/server.tsx
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import * as serverRoutes from "virtual:server-routes";
import { createDebug, objectPick, objectPickBy } from "@hiogawa/utils";
import * as ReactServer from "@hiogawa/vite-rsc/react/rsc";
import * as ReactServer from "@vitejs/plugin-rsc/rsc";
import type { RenderToReadableStreamOptions } from "react-dom/server";
import { DefaultNotFoundPage } from "../features/error/not-found";
import {
Expand All @@ -23,10 +23,7 @@ import {
createActionRedirectResponse,
createFlightRedirectResponse,
} from "../features/server-action/redirect";
import {
type ActionResult,
initializeReactServer,
} from "../features/server-action/server";
import type { ActionResult } from "../features/server-action/server";
import { unwrapStreamRequest } from "../features/server-component/utils";

const debug = createDebug("react-server:rsc");
Expand Down Expand Up @@ -57,8 +54,6 @@ export type ReactServerHandlerResult =
| ReactServerHandlerStreamResult;

export const handler: ReactServerHandler = async (ctx) => {
initializeReactServer();

const handled = handleTrailingSlash(new URL(ctx.request.url));
if (handled) return handled;

Expand Down
10 changes: 5 additions & 5 deletions packages/react-server/src/entry/ssr.tsx
Original file line number Diff line number Diff line change
@@ -1,12 +1,11 @@
import { createDebug, tinyassert } from "@hiogawa/utils";
import * as ReactClient from "@hiogawa/vite-rsc/react/ssr";
import { createMemoryHistory } from "@tanstack/history";
import * as ReactClient from "@vitejs/plugin-rsc/ssr";
import ReactDOMServer from "react-dom/server.edge";
import { injectRSCPayload } from "rsc-html-stream/server";
import type { DevEnvironment, EnvironmentModuleNode } from "vite";
import type { SsrAssetsType } from "../features/assets/plugin";
import { DEV_SSR_CSS, SERVER_CSS_PROXY } from "../features/assets/shared";
import { initializeReactClientSsr } from "../features/client-component/ssr";
import {
DEFAULT_ERROR_CONTEXT,
getErrorContext,
Expand Down Expand Up @@ -75,7 +74,10 @@ export async function importReactServer(): Promise<typeof import("./server")> {
if (import.meta.env.DEV) {
return $__global.dev.reactServerRunner.import(ENTRY_SERVER_WRAPPER);
} else {
return import("virtual:react-server-build" as string);
return import.meta.viteRsc.loadModule<typeof import("./server")>(
"rsc",
"index",
);
}
}

Expand All @@ -84,8 +86,6 @@ export async function renderHtml(
result: ReactServerHandlerStreamResult,
opitons?: { prerender?: boolean },
) {
initializeReactClientSsr();

//
// ssr root
//
Expand Down
Loading
Loading