Skip to content

Commit 4ae3f18

Browse files
authored
fix(rsc): remove server style when css import is removed (#849)
1 parent ba16c34 commit 4ae3f18

File tree

4 files changed

+62
-16
lines changed

4 files changed

+62
-16
lines changed

packages/plugin-rsc/e2e/basic.test.ts

Lines changed: 27 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -855,31 +855,42 @@ function defineTest(f: Fixture) {
855855
'rgb(255, 165, 0)',
856856
)
857857

858-
// remove css import
859858
const editor = f.createEditor('src/routes/style-server/server.tsx')
860-
editor.edit((s) =>
861-
s.replaceAll(`import './server.css'`, `/* import './server.css' */`),
862-
)
859+
860+
// removing and adding new css works via hmr
861+
{
862+
await using _ = await expectNoReload(page)
863+
864+
// remove css import
865+
editor.edit((s) =>
866+
s.replaceAll(`import './server.css'`, `/* import './server.css' */`),
867+
)
868+
await expect(page.locator('.test-style-server')).toHaveCSS(
869+
'color',
870+
'rgb(0, 0, 0)',
871+
)
872+
873+
// add new css
874+
editor.edit((s) =>
875+
s.replaceAll(`/* import './server.css' */`, `import './server2.css'`),
876+
)
877+
await expect(page.locator('.test-style-server')).toHaveCSS(
878+
'color',
879+
'rgb(0, 255, 165)',
880+
)
881+
}
882+
883+
// TODO: React doesn't re-inert same css link. so manual reload is required.
884+
editor.reset()
863885
await page.waitForTimeout(100)
864886
await expect(async () => {
865-
// TODO: shouldn't require reload
866887
await page.reload()
867888
await expect(page.locator('.test-style-server')).toHaveCSS(
868889
'color',
869-
'rgb(0, 0, 0)',
890+
'rgb(255, 165, 0)',
870891
{ timeout: 10 },
871892
)
872893
}).toPass()
873-
874-
// adding css works without reload
875-
await waitForHydration(page)
876-
await using _ = await expectNoReload(page)
877-
878-
editor.reset()
879-
await expect(page.locator('.test-style-server')).toHaveCSS(
880-
'color',
881-
'rgb(255, 165, 0)',
882-
)
883894
})
884895

885896
testNoJs('adding/removing css server @nojs', async ({ page }) => {

packages/plugin-rsc/examples/basic/src/routes/style-server/server.tsx

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,3 +27,7 @@ export function TestStyleServer() {
2727
</div>
2828
)
2929
}
30+
31+
// add no-op `import.meta.hot` to trigger `prune` event.
32+
// this is needed until we land https://github.com/vitejs/vite/pull/20768
33+
import.meta.hot
Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
.test-style-server {
2+
color: rgb(0, 255, 165);
3+
}

packages/plugin-rsc/src/plugin.ts

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1026,6 +1026,17 @@ import.meta.hot.on("rsc:update", () => {
10261026
document.querySelectorAll("vite-error-overlay").forEach((n) => n.close())
10271027
});
10281028
`
1029+
// remove stylesheet links when css import is removed on rsc envrionment
1030+
code += `import.meta.hot.on("rsc:prune", ${(e: vite.PrunePayload) => {
1031+
const nodes = document.querySelectorAll<HTMLLinkElement>(
1032+
"link[rel='stylesheet']",
1033+
)
1034+
nodes.forEach((node) => {
1035+
if (e.paths.includes(node.dataset.rscCssHref!)) {
1036+
node.remove()
1037+
}
1038+
})
1039+
}});`
10291040
return code
10301041
},
10311042
),
@@ -2031,6 +2042,22 @@ function vitePluginRscCss(
20312042
},
20322043
{
20332044
name: 'rsc:importer-resources',
2045+
configureServer(server) {
2046+
// delegate 'prune' event from rsc environment to browser
2047+
const hot = server.environments.rsc!.hot
2048+
const original = hot.send
2049+
hot.send = function (this, ...args: any[]) {
2050+
const e = args[0] as vite.PrunePayload
2051+
if (e && typeof e === 'object' && e.type === 'prune') {
2052+
server.environments.client.hot.send({
2053+
type: 'custom',
2054+
event: 'rsc:prune',
2055+
data: e,
2056+
})
2057+
}
2058+
return original.apply(this, args as any)
2059+
}
2060+
},
20342061
async transform(code, id) {
20352062
if (!code.includes('import.meta.viteRsc.loadCss')) return
20362063

@@ -2175,6 +2202,7 @@ function generateResourcesCode(depsCode: string, manager: RscPluginManager) {
21752202
rel: 'stylesheet',
21762203
precedence: 'vite-rsc/importer-resources',
21772204
href: href,
2205+
'data-rsc-css-href': href,
21782206
}),
21792207
),
21802208
RemoveDuplicateServerCss &&

0 commit comments

Comments
 (0)