diff --git a/packages/plugin-rsc/e2e/basic.test.ts b/packages/plugin-rsc/e2e/basic.test.ts index 6fff84076..a2c9e4c20 100644 --- a/packages/plugin-rsc/e2e/basic.test.ts +++ b/packages/plugin-rsc/e2e/basic.test.ts @@ -637,6 +637,24 @@ function defineTest(f: Fixture) { 'rgb(255, 0, 0)', ) }) + + test('tailwind no redundant server hmr', async ({ page }) => { + await page.goto(f.url()) + await waitForHydration(page) + const logs: string[] = [] + page.on('console', (msg) => { + if (msg.type() === 'log') { + logs.push(msg.text()) + } + }) + f.createEditor('src/routes/tailwind/unused.tsx').resave() + await page.waitForTimeout(200) + f.createEditor('src/routes/tailwind/server.tsx').resave() + await page.waitForTimeout(200) + expect(logs).toEqual([ + expect.stringMatching(/\[vite-rsc:update\].*\/tailwind\/server.tsx/), + ]) + }) }) test('temporary references @js', async ({ page }) => { diff --git a/packages/plugin-rsc/e2e/fixture.ts b/packages/plugin-rsc/e2e/fixture.ts index aa61f332a..1848ba3f5 100644 --- a/packages/plugin-rsc/e2e/fixture.ts +++ b/packages/plugin-rsc/e2e/fixture.ts @@ -142,6 +142,9 @@ export function useFixture(options: { reset(): void { fs.writeFileSync(filepath, originalFiles[filepath]!) }, + resave(): void { + fs.writeFileSync(filepath, current) + }, } } diff --git a/packages/plugin-rsc/examples/basic/src/framework/entry.browser.tsx b/packages/plugin-rsc/examples/basic/src/framework/entry.browser.tsx index 473fc492d..1998e86ff 100644 --- a/packages/plugin-rsc/examples/basic/src/framework/entry.browser.tsx +++ b/packages/plugin-rsc/examples/basic/src/framework/entry.browser.tsx @@ -70,7 +70,8 @@ async function main() { // implement server HMR by trigering re-fetch/render of RSC upon server code change if (import.meta.hot) { - import.meta.hot.on('rsc:update', () => { + import.meta.hot.on('rsc:update', (e) => { + console.log('[vite-rsc:update]', e.file) fetchRscPayload() }) } diff --git a/packages/plugin-rsc/examples/basic/src/routes/tailwind/unused.tsx b/packages/plugin-rsc/examples/basic/src/routes/tailwind/unused.tsx new file mode 100644 index 000000000..98476b011 --- /dev/null +++ b/packages/plugin-rsc/examples/basic/src/routes/tailwind/unused.tsx @@ -0,0 +1 @@ +console.log(
unused
) diff --git a/packages/plugin-rsc/examples/basic/src/styles.css b/packages/plugin-rsc/examples/basic/src/styles.css index e34d4399d..2cb11909b 100644 --- a/packages/plugin-rsc/examples/basic/src/styles.css +++ b/packages/plugin-rsc/examples/basic/src/styles.css @@ -1,4 +1,4 @@ -@import 'tailwindcss' source('./'); +@import 'tailwindcss'; button { @apply bg-gray-100 mx-1 px-2 border hover:bg-gray-200 active:bg-gray-300; diff --git a/packages/plugin-rsc/src/plugin.ts b/packages/plugin-rsc/src/plugin.ts index a8b946ea2..3016a3b68 100644 --- a/packages/plugin-rsc/src/plugin.ts +++ b/packages/plugin-rsc/src/plugin.ts @@ -398,6 +398,18 @@ export default function vitePluginRsc( if (!isInsideClientBoundary(ctx.modules)) { if (this.environment.name === 'rsc') { + // detect if this module is only created as css deps (e.g. tailwind) + // (NOTE: this is not necessary since Vite 7.1.0-beta.0 https://github.com/vitejs/vite/pull/20391 ) + if (ctx.modules.length === 1) { + const importers = [...ctx.modules[0]!.importers] + if ( + importers.length > 0 && + importers.every((m) => m.id && isCSSRequest(m.id)) + ) { + return [] + } + } + // transform js to surface syntax errors for (const mod of ctx.modules) { if (mod.type === 'js') { @@ -426,6 +438,7 @@ export default function vitePluginRsc( // Server files can be included in client module graph, for example, // when `addWatchFile` is used to track js files as style dependency (e.g. tailwind) // In this case, reload all importers (for css hmr), and return empty modules to avoid full-reload. + // (NOTE: this is not necessary since Vite 7.1.0-beta.0 https://github.com/vitejs/vite/pull/20391 ) const env = ctx.server.environments.rsc! const mod = env.moduleGraph.getModuleById(ctx.file) if (mod) {