From 3b2489bcd52090921689acc8c20010e5a0d5afb5 Mon Sep 17 00:00:00 2001 From: Hiroshi Ogawa Date: Sat, 5 Jul 2025 10:37:43 +0900 Subject: [PATCH 1/9] feat: directive pattern --- packages/plugin-rsc/.gitignore | 1 + packages/plugin-rsc/e2e/starter.test.ts | 19 +++++++++++++++++++ 2 files changed, 20 insertions(+) diff --git a/packages/plugin-rsc/.gitignore b/packages/plugin-rsc/.gitignore index 416330c31..e39126f5f 100644 --- a/packages/plugin-rsc/.gitignore +++ b/packages/plugin-rsc/.gitignore @@ -11,3 +11,4 @@ test-results .debug .vite-inspect .claude +.tmp diff --git a/packages/plugin-rsc/e2e/starter.test.ts b/packages/plugin-rsc/e2e/starter.test.ts index f0d6aa233..d20f0cfe7 100644 --- a/packages/plugin-rsc/e2e/starter.test.ts +++ b/packages/plugin-rsc/e2e/starter.test.ts @@ -1,6 +1,7 @@ import { expect, test } from '@playwright/test' import { type Fixture, useFixture } from './fixture' import { expectNoReload, testNoJs, waitForHydration } from './helper' +import fs from 'node:fs' test.describe('dev-default', () => { const f = useFixture({ root: 'examples/starter', mode: 'dev' }) @@ -22,6 +23,24 @@ test.describe('build-cloudflare', () => { defineTest(f) }) +test.describe(() => { + const root = '.tmp/starter-react-compiler' + test.beforeAll(async () => { + fs.rmSync(root, { recursive: true, force: true }) + fs.cpSync('examples/starter', root, { recursive: true }) + }) + + test.describe('dev-react-compiler', () => { + const f = useFixture({ root, mode: 'dev' }) + defineTest(f) + }) + + test.describe('build-react-compiler', () => { + const f = useFixture({ root, mode: 'build' }) + defineTest(f) + }) +}) + function defineTest(f: Fixture) { test('basic', async ({ page }) => { await page.goto(f.url()) From 24bce027954e7f61353bf00b0b0a67a05f056f70 Mon Sep 17 00:00:00 2001 From: Hiroshi Ogawa Date: Sun, 6 Jul 2025 12:15:35 +0900 Subject: [PATCH 2/9] chore: use `temp` --- packages/plugin-rsc/e2e/starter.test.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/plugin-rsc/e2e/starter.test.ts b/packages/plugin-rsc/e2e/starter.test.ts index d20f0cfe7..3d99d454a 100644 --- a/packages/plugin-rsc/e2e/starter.test.ts +++ b/packages/plugin-rsc/e2e/starter.test.ts @@ -24,7 +24,7 @@ test.describe('build-cloudflare', () => { }) test.describe(() => { - const root = '.tmp/starter-react-compiler' + const root = 'temp/starter-react-compiler' test.beforeAll(async () => { fs.rmSync(root, { recursive: true, force: true }) fs.cpSync('examples/starter', root, { recursive: true }) From c5c774ee2b726630febfca6ffafba35009a9572b Mon Sep 17 00:00:00 2001 From: Hiroshi Ogawa Date: Sun, 6 Jul 2025 12:36:28 +0900 Subject: [PATCH 3/9] test: wip --- packages/plugin-rsc/e2e/basic.test.ts | 26 +++++++++++++++++++ packages/plugin-rsc/e2e/starter.test.ts | 19 -------------- .../plugin-rsc/examples/basic/package.json | 1 + .../plugin-rsc/examples/basic/vite.config.ts | 4 ++- pnpm-lock.yaml | 5 +++- 5 files changed, 34 insertions(+), 21 deletions(-) diff --git a/packages/plugin-rsc/e2e/basic.test.ts b/packages/plugin-rsc/e2e/basic.test.ts index e7d63d11e..620f877e6 100644 --- a/packages/plugin-rsc/e2e/basic.test.ts +++ b/packages/plugin-rsc/e2e/basic.test.ts @@ -43,6 +43,32 @@ test.describe('build-base', () => { defineTest(f) }) +test.describe('dev-react-compiler', () => { + const f = useFixture({ + root: 'examples/basic', + mode: 'dev', + cliOptions: { + env: { + TEST_REACT_COMPILER: 'true', + }, + }, + }) + defineTest(f) +}) + +test.describe('build-react-compiler', () => { + const f = useFixture({ + root: 'examples/basic', + mode: 'build', + cliOptions: { + env: { + TEST_REACT_COMPILER: 'true', + }, + }, + }) + defineTest(f) +}) + test.describe(() => { // disabled by default if (!process.env.TEST_ISOLATED) return diff --git a/packages/plugin-rsc/e2e/starter.test.ts b/packages/plugin-rsc/e2e/starter.test.ts index 3d99d454a..f0d6aa233 100644 --- a/packages/plugin-rsc/e2e/starter.test.ts +++ b/packages/plugin-rsc/e2e/starter.test.ts @@ -1,7 +1,6 @@ import { expect, test } from '@playwright/test' import { type Fixture, useFixture } from './fixture' import { expectNoReload, testNoJs, waitForHydration } from './helper' -import fs from 'node:fs' test.describe('dev-default', () => { const f = useFixture({ root: 'examples/starter', mode: 'dev' }) @@ -23,24 +22,6 @@ test.describe('build-cloudflare', () => { defineTest(f) }) -test.describe(() => { - const root = 'temp/starter-react-compiler' - test.beforeAll(async () => { - fs.rmSync(root, { recursive: true, force: true }) - fs.cpSync('examples/starter', root, { recursive: true }) - }) - - test.describe('dev-react-compiler', () => { - const f = useFixture({ root, mode: 'dev' }) - defineTest(f) - }) - - test.describe('build-react-compiler', () => { - const f = useFixture({ root, mode: 'build' }) - defineTest(f) - }) -}) - function defineTest(f: Fixture) { test('basic', async ({ page }) => { await page.goto(f.url()) diff --git a/packages/plugin-rsc/examples/basic/package.json b/packages/plugin-rsc/examples/basic/package.json index 7db4bcf45..dbbd36342 100644 --- a/packages/plugin-rsc/examples/basic/package.json +++ b/packages/plugin-rsc/examples/basic/package.json @@ -25,6 +25,7 @@ "@vitejs/test-dep-client-in-server2": "file:./test-dep/client-in-server2", "@vitejs/test-dep-server-in-client": "file:./test-dep/server-in-client", "@vitejs/test-dep-server-in-server": "file:./test-dep/server-in-server", + "babel-plugin-react-compiler": "19.1.0-rc.2", "tailwindcss": "^4.1.4", "vite": "^7.0.2", "vite-plugin-inspect": "^11.2.0" diff --git a/packages/plugin-rsc/examples/basic/vite.config.ts b/packages/plugin-rsc/examples/basic/vite.config.ts index 67c4404e5..cccd9e71b 100644 --- a/packages/plugin-rsc/examples/basic/vite.config.ts +++ b/packages/plugin-rsc/examples/basic/vite.config.ts @@ -22,7 +22,9 @@ export default defineConfig({ clearScreen: false, plugins: [ tailwindcss(), - react(), + process.env.TEST_REACT_COMPILER + ? react({ babel: { plugins: ['babel-plugin-react-compiler'] } }) + : react(), vitePluginUseCache(), rsc({ entries: { diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 5b58d2d7a..08f8c3d2c 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -548,6 +548,9 @@ importers: '@vitejs/test-dep-server-in-server': specifier: file:./test-dep/server-in-server version: file:packages/plugin-rsc/examples/basic/test-dep/server-in-server(react@19.1.0) + babel-plugin-react-compiler: + specifier: 19.1.0-rc.2 + version: 19.1.0-rc.2 tailwindcss: specifier: ^4.1.4 version: 4.1.11 @@ -7944,7 +7947,7 @@ snapshots: babel-plugin-react-compiler@19.1.0-rc.2: dependencies: - '@babel/types': 7.27.6 + '@babel/types': 7.27.7 bail@2.0.2: {} From 09d7d3e2de0e776f676cceeeb0750b4297e95f1b Mon Sep 17 00:00:00 2001 From: Hiroshi Ogawa Date: Sun, 6 Jul 2025 13:00:45 +0900 Subject: [PATCH 4/9] patch: vite:react-babel --- packages/plugin-rsc/e2e/basic.test.ts | 2 ++ .../plugin-rsc/examples/basic/vite.config.ts | 18 +++++++++++++++++- 2 files changed, 19 insertions(+), 1 deletion(-) diff --git a/packages/plugin-rsc/e2e/basic.test.ts b/packages/plugin-rsc/e2e/basic.test.ts index 620f877e6..ca9084bf4 100644 --- a/packages/plugin-rsc/e2e/basic.test.ts +++ b/packages/plugin-rsc/e2e/basic.test.ts @@ -54,6 +54,8 @@ test.describe('dev-react-compiler', () => { }, }) defineTest(f) + + // TODO: actually verify compiler is enabled in client environment }) test.describe('build-react-compiler', () => { diff --git a/packages/plugin-rsc/examples/basic/vite.config.ts b/packages/plugin-rsc/examples/basic/vite.config.ts index cccd9e71b..a010a53cb 100644 --- a/packages/plugin-rsc/examples/basic/vite.config.ts +++ b/packages/plugin-rsc/examples/basic/vite.config.ts @@ -23,7 +23,23 @@ export default defineConfig({ plugins: [ tailwindcss(), process.env.TEST_REACT_COMPILER - ? react({ babel: { plugins: ['babel-plugin-react-compiler'] } }) + ? [ + react({ babel: { plugins: ['babel-plugin-react-compiler'] } }), + { + name: 'patch-react-transform', + configResolved(config) { + const plugin: any = config.plugins.find( + (p) => p.name === 'vite:react-babel', + ) + const original = plugin.transform.handler + plugin.transform.handler = function () { + if (this.environment.name === 'client') { + return original.apply(this, arguments) + } + } + }, + }, + ] : react(), vitePluginUseCache(), rsc({ From a5765edad1871673d4d3de031c999a119d635027 Mon Sep 17 00:00:00 2001 From: Hiroshi Ogawa Date: Sun, 6 Jul 2025 13:02:28 +0900 Subject: [PATCH 5/9] chore: cleanup --- packages/plugin-rsc/.gitignore | 1 - 1 file changed, 1 deletion(-) diff --git a/packages/plugin-rsc/.gitignore b/packages/plugin-rsc/.gitignore index e39126f5f..416330c31 100644 --- a/packages/plugin-rsc/.gitignore +++ b/packages/plugin-rsc/.gitignore @@ -11,4 +11,3 @@ test-results .debug .vite-inspect .claude -.tmp From 256a545964f8862cdf91f47f2b4afbfd70144c8f Mon Sep 17 00:00:00 2001 From: Hiroshi Ogawa Date: Sun, 6 Jul 2025 13:13:01 +0900 Subject: [PATCH 6/9] chore: simplify --- .../plugin-rsc/examples/basic/vite.config.ts | 23 +++++-------------- 1 file changed, 6 insertions(+), 17 deletions(-) diff --git a/packages/plugin-rsc/examples/basic/vite.config.ts b/packages/plugin-rsc/examples/basic/vite.config.ts index a010a53cb..09e7f4590 100644 --- a/packages/plugin-rsc/examples/basic/vite.config.ts +++ b/packages/plugin-rsc/examples/basic/vite.config.ts @@ -23,23 +23,12 @@ export default defineConfig({ plugins: [ tailwindcss(), process.env.TEST_REACT_COMPILER - ? [ - react({ babel: { plugins: ['babel-plugin-react-compiler'] } }), - { - name: 'patch-react-transform', - configResolved(config) { - const plugin: any = config.plugins.find( - (p) => p.name === 'vite:react-babel', - ) - const original = plugin.transform.handler - plugin.transform.handler = function () { - if (this.environment.name === 'client') { - return original.apply(this, arguments) - } - } - }, - }, - ] + ? react({ babel: { plugins: ['babel-plugin-react-compiler'] } }).map( + (p: any) => ({ + ...p, + applyToEnvironment: (e: any) => e.name === 'client', + }), + ) : react(), vitePluginUseCache(), rsc({ From e851bf87053b4ab7bf5fa8c58a614de59f9c948a Mon Sep 17 00:00:00 2001 From: Hiroshi Ogawa Date: Sun, 6 Jul 2025 15:18:59 +0900 Subject: [PATCH 7/9] chore: use ViteReactPluginApi --- .../plugin-rsc/examples/basic/vite.config.ts | 22 +++++++++++++------ 1 file changed, 15 insertions(+), 7 deletions(-) diff --git a/packages/plugin-rsc/examples/basic/vite.config.ts b/packages/plugin-rsc/examples/basic/vite.config.ts index 09e7f4590..9c628aa3f 100644 --- a/packages/plugin-rsc/examples/basic/vite.config.ts +++ b/packages/plugin-rsc/examples/basic/vite.config.ts @@ -1,7 +1,7 @@ import assert from 'node:assert' import rsc, { transformHoistInlineDirective } from '@vitejs/plugin-rsc' import tailwindcss from '@tailwindcss/vite' -import react from '@vitejs/plugin-react' +import react, { type ViteReactPluginApi } from '@vitejs/plugin-react' import { type Plugin, defineConfig, normalizePath, parseAstAsync } from 'vite' import inspect from 'vite-plugin-inspect' import path from 'node:path' @@ -23,12 +23,20 @@ export default defineConfig({ plugins: [ tailwindcss(), process.env.TEST_REACT_COMPILER - ? react({ babel: { plugins: ['babel-plugin-react-compiler'] } }).map( - (p: any) => ({ - ...p, - applyToEnvironment: (e: any) => e.name === 'client', - }), - ) + ? [ + react({ babel: { plugins: ['babel-plugin-react-compiler'] } }), + // skip react compiler in non CSR environments + { + name: 'react-babel-override', + api: { + reactBabel: (babelConfig, context) => { + if (context.ssr) { + babelConfig.plugins = [] + } + }, + } satisfies ViteReactPluginApi, + }, + ] : react(), vitePluginUseCache(), rsc({ From c8fa78283fd897d56e2796628c7772111791b851 Mon Sep 17 00:00:00 2001 From: Hiroshi Ogawa Date: Sun, 6 Jul 2025 15:55:42 +0900 Subject: [PATCH 8/9] chore: hack with applyToEnvironment --- .../plugin-rsc/examples/basic/vite.config.ts | 22 ++++++------------- 1 file changed, 7 insertions(+), 15 deletions(-) diff --git a/packages/plugin-rsc/examples/basic/vite.config.ts b/packages/plugin-rsc/examples/basic/vite.config.ts index 9c628aa3f..7e960be8f 100644 --- a/packages/plugin-rsc/examples/basic/vite.config.ts +++ b/packages/plugin-rsc/examples/basic/vite.config.ts @@ -1,7 +1,7 @@ import assert from 'node:assert' import rsc, { transformHoistInlineDirective } from '@vitejs/plugin-rsc' import tailwindcss from '@tailwindcss/vite' -import react, { type ViteReactPluginApi } from '@vitejs/plugin-react' +import react from '@vitejs/plugin-react' import { type Plugin, defineConfig, normalizePath, parseAstAsync } from 'vite' import inspect from 'vite-plugin-inspect' import path from 'node:path' @@ -23,20 +23,12 @@ export default defineConfig({ plugins: [ tailwindcss(), process.env.TEST_REACT_COMPILER - ? [ - react({ babel: { plugins: ['babel-plugin-react-compiler'] } }), - // skip react compiler in non CSR environments - { - name: 'react-babel-override', - api: { - reactBabel: (babelConfig, context) => { - if (context.ssr) { - babelConfig.plugins = [] - } - }, - } satisfies ViteReactPluginApi, - }, - ] + ? (react({ + babel: { plugins: ['babel-plugin-react-compiler'] }, + }).map((p) => ({ + ...p, + applyToEnvironment: (e: any) => e.name === 'client', + })) as any) : react(), vitePluginUseCache(), rsc({ From 09adb31bf90134d873e8db9ef37a1e5cc08ef833 Mon Sep 17 00:00:00 2001 From: Hiroshi Ogawa Date: Sun, 6 Jul 2025 16:09:57 +0900 Subject: [PATCH 9/9] test: verify react compiler --- packages/plugin-rsc/e2e/basic.test.ts | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/packages/plugin-rsc/e2e/basic.test.ts b/packages/plugin-rsc/e2e/basic.test.ts index ca9084bf4..76d77c79a 100644 --- a/packages/plugin-rsc/e2e/basic.test.ts +++ b/packages/plugin-rsc/e2e/basic.test.ts @@ -55,7 +55,12 @@ test.describe('dev-react-compiler', () => { }) defineTest(f) - // TODO: actually verify compiler is enabled in client environment + test('verify react compiler', async ({ page }) => { + await page.goto(f.url()) + await waitForHydration(page) + const res = await page.request.get(f.url('src/routes/client.tsx')) + expect(await res.text()).toContain('react.memo_cache_sentinel') + }) }) test.describe('build-react-compiler', () => {