diff --git a/playground/hmr/__tests__/hmr.spec.ts b/playground/hmr/__tests__/hmr.spec.ts
index d4281ec1b..8b7aa09d1 100644
--- a/playground/hmr/__tests__/hmr.spec.ts
+++ b/playground/hmr/__tests__/hmr.spec.ts
@@ -999,11 +999,20 @@ if (!isBuild) {
await untilUpdated(() => el.evaluate((it) => `${it.clientHeight}`), '40')
})
- test('CSS HMR with this.addWatchFile', async () => {
+ test('CSS HMR with this.addWatchFile in transform hook', async () => {
await page.goto(viteTestUrl + '/css-deps/index.html')
- expect(await getColor('.css-deps')).toMatch('red')
- editFile('css-deps/dep.js', (code) => code.replace(`red`, `green`))
- await untilUpdated(() => getColor('.css-deps'), 'green')
+ expect(await getColor('.css-deps-transform')).toMatch('red')
+ editFile('css-deps/dep-transform.js', (code) =>
+ code.replace(`red`, `green`),
+ )
+ await untilUpdated(() => getColor('.css-deps-transform'), 'green')
+ })
+
+ test('CSS HMR with this.addWatchFile in load hook', async () => {
+ await page.goto(viteTestUrl + '/css-deps/index.html')
+ expect(await getColor('.css-deps-load')).toMatch('red')
+ editFile('css-deps/dep-load.js', (code) => code.replace(`red`, `green`))
+ await untilUpdated(() => getColor('.css-deps-load'), 'green')
})
test('hmr should happen after missing file is created', async () => {
diff --git a/playground/hmr/css-deps/dep.js b/playground/hmr/css-deps/dep-load.js
similarity index 76%
rename from playground/hmr/css-deps/dep.js
rename to playground/hmr/css-deps/dep-load.js
index 07f62c424..447f0b0dd 100644
--- a/playground/hmr/css-deps/dep.js
+++ b/playground/hmr/css-deps/dep-load.js
@@ -1,4 +1,4 @@
-// This file is depended by main.css via this.addWatchFile
+// This file is depended by main-load.css via this.addWatchFile
export const color = 'red'
// Self-accept so that updating this file would not trigger a page reload.
diff --git a/playground/hmr/css-deps/dep-transform.js b/playground/hmr/css-deps/dep-transform.js
new file mode 100644
index 000000000..3e6cc741c
--- /dev/null
+++ b/playground/hmr/css-deps/dep-transform.js
@@ -0,0 +1,8 @@
+// This file is depended by main-transform.css via this.addWatchFile
+export const color = 'red'
+
+// Self-accept so that updating this file would not trigger a page reload.
+// We only want to observe main.css updating itself.
+if (import.meta.hot) {
+ import.meta.hot.accept()
+}
diff --git a/playground/hmr/css-deps/index.html b/playground/hmr/css-deps/index.html
index 6ff27f565..0b1a81df5 100644
--- a/playground/hmr/css-deps/index.html
+++ b/playground/hmr/css-deps/index.html
@@ -1,8 +1,11 @@
-
should be red
+should be red
+should be red
diff --git a/playground/hmr/css-deps/main-transform.css b/playground/hmr/css-deps/main-transform.css
new file mode 100644
index 000000000..88aaac9ee
--- /dev/null
+++ b/playground/hmr/css-deps/main-transform.css
@@ -0,0 +1,3 @@
+.css-deps-transform {
+ color: replaced;
+}
diff --git a/playground/hmr/css-deps/main.css b/playground/hmr/css-deps/main.css
deleted file mode 100644
index 65cea880b..000000000
--- a/playground/hmr/css-deps/main.css
+++ /dev/null
@@ -1,3 +0,0 @@
-.css-deps {
- color: replaced;
-}
diff --git a/playground/hmr/vite.config.ts b/playground/hmr/vite.config.ts
index 46641f3e2..e573bcd33 100644
--- a/playground/hmr/vite.config.ts
+++ b/playground/hmr/vite.config.ts
@@ -29,7 +29,8 @@ export default defineConfig({
},
virtualPlugin(),
transformCountPlugin(),
- watchCssDepsPlugin(),
+ watchCssDepsTransformPlugin(),
+ watchCssDepsLoadPlugin(),
],
})
@@ -76,14 +77,15 @@ function transformCountPlugin(): Plugin {
}
}
-function watchCssDepsPlugin(): Plugin {
+// `addWatchFile` called from `transform` hook
+function watchCssDepsTransformPlugin(): Plugin {
return {
- name: 'watch-css-deps',
+ name: 'watch-css-deps-transform',
async transform(code, id) {
// replace the `replaced` identifier in the CSS file with the adjacent
// `dep.js` file's `color` variable.
- if (id.includes('css-deps/main.css')) {
- const depPath = path.resolve(__dirname, './css-deps/dep.js')
+ if (id.includes('css-deps/main-transform.css')) {
+ const depPath = path.resolve(__dirname, './css-deps/dep-transform.js')
const dep = await fs.readFile(depPath, 'utf-8')
const color = dep.match(/color = '(.+?)'/)[1]
this.addWatchFile(depPath)
@@ -92,3 +94,35 @@ function watchCssDepsPlugin(): Plugin {
},
}
}
+
+// `addWatchFile` called from `load` hook
+function watchCssDepsLoadPlugin(): Plugin {
+ return {
+ name: 'watch-css-deps-load',
+ resolveId(id) {
+ if (id === 'virtual:css-deps-load.css') {
+ return '\0virtual:css-deps-load.css'
+ }
+ },
+ async load(id) {
+ if (id === '\0virtual:css-deps-load.css') {
+ const depPath = path.resolve(__dirname, './css-deps/dep.js')
+ this.addWatchFile(depPath)
+ return `\
+.css-deps-load {
+ color: replaced;
+}`
+ }
+ },
+ async transform(code, id) {
+ // replace the `replaced` identifier in the CSS file with the adjacent
+ // `dep.js` file's `color` variable.
+ if (id === '\0virtual:css-deps-load.css') {
+ const depPath = path.resolve(__dirname, './css-deps/dep-load.js')
+ const dep = await fs.readFile(depPath, 'utf-8')
+ const color = dep.match(/color = '(.+?)'/)[1]
+ return code.replace('replaced', color)
+ }
+ },
+ }
+}