v0.24
July 19, 2025

Waku's Migration to @vitejs/plugin-rsc

Technical details and breaking changes in Waku's migration to the official Vite React Server Components plugin.

by

Waku has migrated to use Vite's official plugin @vitejs/plugin-rsc for ReactServer Components bundler implementation. Through this plugin, Waku now adopts the Vite Environment API, which provides a unified foundation for themulti-environment build system required for RSC integration. This migration simplifies internal architecture while providing users fullaccess to the Vite plugin system and benefiting from the broader ecosystem.

Waku has pioneered RSC framework implementation on Vite and provided many insights for the official Vite plugin. Some core RSC functionalities have been incorporated into @vitejs/plugin-rsc, benefiting the entire Vite ecosystem.

While there were large changes in internal Vite development server, build pipeline and plugin architecture, core routing logic remains almost unchanged, preserving Waku's existing functionality. This is thanks to Waku's layered routing architecture where the higher level APIs (fsRouter, createPages, and defineRouter) are built up on the "minimal" API defineEntries.

New features / Breaking Changes

Custom Vite configuration

Custom Vite configuration support has been changed. Vite configuration can now be specified through vite property in waku.config.ts. @vitejs/plugin-rsc provides three environments client, ssr, and rsc for fine-grained control over the configuration and plugin pipeline. See Vite Environment API documentation for more details.

Before

// vite.config.ts
import { defineConfig } from "vite";

export default defineConfig({ ... })
// waku.config.ts
import { defineConfig } from "waku/config";

export default defineConfig({
  unstable_viteConfigs: { ... },
})

After

// waku.config.ts
import { defineConfig } from "waku/config";

export default defineConfig({
  vite: { ... }
})

Example

// waku.config.ts
import { defineConfig } from 'waku/config';

export default defineConfig({
  vite: {
    environments: {
      // environment-specific configurations.
      client: {
        build: {
          // disable minifying client assets
          minify: false,
        },
      },
      ssr: {
        optimizeeDeps: {
          include: [
            // handle cjs package for SSR
          ],
        },
      },
      rsc: {
        // ...
      },
    },
    plugins: [
      // custom plugins
      {
        name: 'my-custom-plugin',
        transform(code, id) {
          // e.g. transform only on `rsc` environment
          if (this.environment.name === 'rsc') {
            // ...
          }
        },
      },
    ],
  },
});

Transforming external packages

Previously Waku transformed all server packages on RSC module graph while externalizing all server packages SSR module graph during development. This has been changed to transform only React 3rd party packages on both server module graphs to be able to discover "use server" and "use client" inside the packages. This change causes a new error during SSR on development if there's cjs dependency (directly or transitively) used in client component. For example, swr (esm) package uses use-sync-external-store (cjs) internally and the plugin will show a warning found non-optimized CJS dependency. Currently, this needs to be manually mitigated by configuring optimizeDeps.include such as environments.ssr.optimizeDeps.include: ["swr"].

Previous Implementation

The previous implementation remains available via the --experimental-legacy-cli flag for fallback during the transition period, for example,

waku dev --experimental-legacy-cli
waku build --experimental-legacy-cli
waku start --experimental-legacy-cli

Future

  • @cloudflare/vite-plugin
  • Nitro plugin?
  • Better alignment with Vite ecosystem.
  • Rolldown-Vite support.