Skip to content

Commit 2051f52

Browse files
committed
wip: css hmr
1 parent 7a53b1f commit 2051f52

File tree

4 files changed

+68
-10
lines changed

4 files changed

+68
-10
lines changed

packages/vite/src/node/plugins/css.ts

+1-1
Original file line numberDiff line numberDiff line change
@@ -563,7 +563,7 @@ export function cssPostPlugin(config: ResolvedConfig): RolldownPlugin {
563563
!inlined &&
564564
dataToEsm(modules, { namedExports: true, preferConst: true })
565565

566-
if (config.command === 'serve' && !config.experimental.rolldownDev) {
566+
if (config.command === 'serve') {
567567
const getContentWithSourcemap = async (content: string) => {
568568
if (config.css?.devSourcemap) {
569569
const sourcemap = this.getCombinedSourcemap()

packages/vite/src/node/server/environments/rolldown.ts

+38-7
Original file line numberDiff line numberDiff line change
@@ -64,11 +64,8 @@ export function rolldownDevHandleConfig(
6464
reactRefresh: config.experimental?.rolldownDev?.reactRefresh,
6565
}),
6666
},
67-
// NOTE
68-
// this is not "build" option any more (or is there a way to handle entry lazily?)
6967
build: {
7068
modulePreload: false,
71-
cssCodeSplit: false,
7269
assetsInlineLimit: 0,
7370
rollupOptions: {
7471
input:
@@ -192,9 +189,12 @@ class RolldownEnvironment extends DevEnvironment {
192189
'vite:css-post',
193190
'vite:asset',
194191
].includes(p.name) ||
195-
['AliasPlugin', 'TransformPlugin', 'LoadFallbackPlugin'].includes(
196-
p.constructor.name,
197-
),
192+
[
193+
'AliasPlugin',
194+
'TransformPlugin',
195+
'LoadFallbackPlugin',
196+
'ManifestPlugin',
197+
].includes(p.constructor.name),
198198
)
199199
plugins = plugins.map((p) => injectEnvironmentToHooks(this as any, p))
200200

@@ -212,8 +212,12 @@ class RolldownEnvironment extends DevEnvironment {
212212
plugins: [
213213
...plugins,
214214
patchRuntimePlugin(this.rolldownDevOptions),
215+
patchCssPlugin(),
215216
reactRefreshPlugin(),
216217
],
218+
moduleTypes: {
219+
'.css': 'js',
220+
},
217221
}
218222
this.instance = await rolldown.rolldown(inputOptions)
219223

@@ -300,6 +304,32 @@ function patchRuntimePlugin(
300304
}
301305
}
302306

307+
// patch vite:css transform for hmr
308+
function patchCssPlugin(): rolldown.Plugin {
309+
return {
310+
name: 'vite:rolldown-patch-css',
311+
transform: {
312+
filter: {
313+
id: {
314+
include: ['*.css'],
315+
},
316+
code: {
317+
include: ['__vite__updateStyle'],
318+
},
319+
},
320+
handler(code, id) {
321+
// TODO: import.meta.hot.prune
322+
const cssCode = code.match(/^const __vite__css = (.*)$/m)![1]
323+
const jsCode = `
324+
__rolldown_updateStyle(${JSON.stringify(id)}, ${cssCode});
325+
module.hot.accept();
326+
`
327+
return { code: jsCode, moduleSideEffects: true }
328+
},
329+
},
330+
}
331+
}
332+
303333
// reuse /@vite/client for Websocket API
304334
function getRolldownClientCode() {
305335
let code = fs.readFileSync(CLIENT_ENTRY, 'utf-8')
@@ -331,7 +361,8 @@ const hot = createHotContext("/__rolldown");
331361
hot.on("rolldown:hmr", (data) => {
332362
(0, eval)(data[1]);
333363
});
334-
window.__rolldown_hot = hot;
364+
self.__rolldown_hot = hot;
365+
self.__rolldown_updateStyle = updateStyle;
335366
`
336367
return `(() => {/*** @vite/client ***/\n${code}}\n)()`
337368
}

playground/rolldown-dev-react/__tests__/basic.spec.ts

+28-1
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,7 @@ test('style', async () => {
2828
).toBe('rgb(255, 165, 0)')
2929
})
3030

31-
test.runIf(!isBuild)('hmr', async () => {
31+
test.runIf(!isBuild)('hmr js', async () => {
3232
await page.goto(viteTestUrl)
3333
await page.getByRole('button', { name: 'Count: 0' }).click()
3434

@@ -38,3 +38,30 @@ test.runIf(!isBuild)('hmr', async () => {
3838
editFile('./src/app.tsx', (s) => s.replace('Count-x:', 'Count-x-y:'))
3939
await page.getByRole('button', { name: 'Count-x-y: 2' }).click()
4040
})
41+
42+
test.runIf(!isBuild)('hmr css', async () => {
43+
await page.goto(viteTestUrl)
44+
45+
await expect
46+
.poll(() =>
47+
page.locator('.test-style').evaluate((el) => getComputedStyle(el).color),
48+
)
49+
.toBe('rgb(255, 165, 0)')
50+
await page.getByRole('button', { name: 'Count: 0' }).click()
51+
52+
editFile('./src/test-style.css', (s) => s.replace('orange', 'blue'))
53+
await expect
54+
.poll(() =>
55+
page.locator('.test-style').evaluate((el) => getComputedStyle(el).color),
56+
)
57+
.toBe('rgb(0, 0, 255)')
58+
await page.getByRole('button', { name: 'Count: 1' }).click()
59+
60+
editFile('./src/test-style.css', (s) => s.replace('blue', 'green'))
61+
await expect
62+
.poll(() =>
63+
page.locator('.test-style').evaluate((el) => getComputedStyle(el).color),
64+
)
65+
.toBe('rgb(0, 128, 0)')
66+
await page.getByRole('button', { name: 'Count: 2' }).click()
67+
})

playground/rolldown-dev-react/src/app.tsx

+1-1
Original file line numberDiff line numberDiff line change
@@ -4,8 +4,8 @@ import virtualTest from 'virtual:test'
44
// @ts-expect-error no type
55
import testAlias from 'test-alias'
66
import { throwError } from './error'
7-
// TODO: hmr
87
import './test-style.css'
8+
// TODO: hmr for assets?
99
import testStyleUrl from './test-style-url.css?url'
1010
import testStyleInline from './test-style-inline.css?inline'
1111

0 commit comments

Comments
 (0)