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) + } + }, + } +}