diff --git a/playground/css/__tests__/postcss-plugins-different-dir/postcss-plugins-different-dir.spec.ts b/playground/css/__tests__/postcss-plugins-different-dir/postcss-plugins-different-dir.spec.ts index fb748bf2c8fff2..1d21eb760dabfd 100644 --- a/playground/css/__tests__/postcss-plugins-different-dir/postcss-plugins-different-dir.spec.ts +++ b/playground/css/__tests__/postcss-plugins-different-dir/postcss-plugins-different-dir.spec.ts @@ -21,7 +21,7 @@ test.runIf(isServe)('postcss plugins in different dir', async () => { await server.listen() try { await page.goto(`http://localhost:${port}`) - const tailwindStyle = await page.$('.tailwind-style') + const tailwindStyle = page.locator('#tailwind-style') expect(await getBgColor(tailwindStyle)).toBe('rgb(254, 226, 226)') expect(await getColor(tailwindStyle)).toBe('rgb(136, 136, 136)') } finally { diff --git a/playground/tailwind/__test__/tailwind.spec.ts b/playground/tailwind/__test__/tailwind.spec.ts index e639678331e9e5..c67ef115073b69 100644 --- a/playground/tailwind/__test__/tailwind.spec.ts +++ b/playground/tailwind/__test__/tailwind.spec.ts @@ -1,84 +1,82 @@ import { expect, test } from 'vitest' import { editFile, - getBgColor, getColor, - isBuild, + isServe, page, untilBrowserLogAfter, untilUpdated, } from '~utils' test('should render', async () => { - expect(await page.textContent('#pagetitle')).toBe('|Page title|') + expect(await page.textContent('#pagetitle')).toBe('Page title') }) -if (!isBuild) { - test('regenerate CSS and HMR (glob pattern)', async () => { - const el = await page.$('#pagetitle') - const el2 = await page.$('#helloroot') - expect(await getColor(el)).toBe('rgb(11, 22, 33)') +test.runIf(isServe)('regenerate CSS and HMR (glob pattern)', async () => { + const el = page.locator('#view1-text') + expect(await getColor(el)).toBe('rgb(22, 163, 74)') - await untilBrowserLogAfter( - () => - editFile('src/views/Page.vue', (code) => - code.replace('|Page title|', '|Page title updated|'), - ), - [ - '[vite] css hot updated: /index.css', - '[vite] hot updated: /src/views/Page.vue', - ], - false, - ) - await untilUpdated(() => el.textContent(), '|Page title updated|') + await untilBrowserLogAfter( + () => + editFile('src/views/view1.js', (code) => + code.replace('|view1|', '|view1 updated|'), + ), + [ + '[vite] css hot updated: /index.css', + '[vite] hot updated: /src/views/view1.js via /src/main.js', + ], + false, + ) + await untilUpdated(() => el.textContent(), '|view1 updated|') - await untilBrowserLogAfter( - () => - editFile('src/components/HelloWorld.vue', (code) => - code.replace('text-gray-800', 'text-[rgb(10,20,30)]'), - ), - [ - '[vite] css hot updated: /index.css', - '[vite] hot updated: /src/components/HelloWorld.vue', - ], - false, - ) - await untilUpdated(() => getColor(el2), 'rgb(10, 20, 30)') - }) + await untilBrowserLogAfter( + () => + editFile('src/views/view1.js', (code) => + code.replace('text-green-600', 'text-orange-600'), + ), + [ + '[vite] css hot updated: /index.css', + '[vite] hot updated: /src/views/view1.js via /src/main.js', + ], + false, + ) + // await new Promise(resolve => setTimeout(resolve, 10)) + await untilUpdated(async () => getColor(el), 'rgb(234, 88, 12)') +}) - test('regenerate CSS and HMR (relative path)', async () => { - const el = await page.$('h1') - expect(await getColor(el)).toBe('black') +test.runIf(isServe)( + 'same file duplicated in module graph (#4267)', + async () => { + const el = page.locator('#component1') + expect(await getColor(el)).toBe('rgb(220, 38, 38)') + // when duplicated, page reload happens await untilBrowserLogAfter( () => - editFile('src/App.vue', (code) => - code.replace('text-black', 'text-[rgb(11,22,33)]'), + editFile('src/components/component1.js', (code) => + code.replace('text-red-600', 'text-blue-600'), ), [ '[vite] css hot updated: /index.css', - '[vite] hot updated: /src/App.vue', + '[vite] hot updated: /src/components/component1.js', ], false, ) - await untilUpdated(() => getColor(el), 'rgb(11, 22, 33)') - }) + await untilUpdated(() => getColor(el), 'rgb(37, 99, 235)') + }, +) - test('regenerate CSS and HMR (pug template)', async () => { - const el = await page.$('.pug') - expect(await getBgColor(el)).toBe('rgb(248, 113, 113)') +test.runIf(isServe)('regenerate CSS and HMR (relative path)', async () => { + const el = page.locator('#pagetitle') + expect(await getColor(el)).toBe('rgb(124, 58, 237)') - await untilBrowserLogAfter( - () => - editFile('src/components/PugTemplate.vue', (code) => - code.replace('bg-red-400', 'bg-red-600'), - ), - [ - '[vite] css hot updated: /index.css', - '[vite] hot updated: /src/components/PugTemplate.vue?vue&type=template&lang.js', - ], - false, - ) - await untilUpdated(() => getBgColor(el), 'rgb(220, 38, 38)') - }) -} + await untilBrowserLogAfter( + () => + editFile('src/main.js', (code) => + code.replace('text-violet-600', 'text-cyan-600'), + ), + ['[vite] css hot updated: /index.css', '[vite] hot updated: /src/main.js'], + false, + ) + await untilUpdated(() => getColor(el), 'rgb(8, 145, 178)') +}) diff --git a/playground/tailwind/index.html b/playground/tailwind/index.html index d28c699ba6d465..0c7bee6b26884f 100644 --- a/playground/tailwind/index.html +++ b/playground/tailwind/index.html @@ -1,14 +1,5 @@ - - - - - - - Vite App - - - -
- - - + + +
+ + diff --git a/playground/tailwind/src/App.vue b/playground/tailwind/src/App.vue deleted file mode 100644 index 25835fc414a06f..00000000000000 --- a/playground/tailwind/src/App.vue +++ /dev/null @@ -1,12 +0,0 @@ - - - diff --git a/playground/tailwind/src/assets/logo.png b/playground/tailwind/src/assets/logo.png deleted file mode 100644 index f3d2503fc2a44b..00000000000000 Binary files a/playground/tailwind/src/assets/logo.png and /dev/null differ diff --git a/playground/tailwind/src/components/HelloWorld.vue b/playground/tailwind/src/components/HelloWorld.vue deleted file mode 100644 index b1ce4248557b39..00000000000000 --- a/playground/tailwind/src/components/HelloWorld.vue +++ /dev/null @@ -1,10 +0,0 @@ - - - diff --git a/playground/tailwind/src/components/PugTemplate.vue b/playground/tailwind/src/components/PugTemplate.vue deleted file mode 100644 index 4169b534dee4ef..00000000000000 --- a/playground/tailwind/src/components/PugTemplate.vue +++ /dev/null @@ -1,3 +0,0 @@ - diff --git a/playground/tailwind/src/components/component1.js b/playground/tailwind/src/components/component1.js new file mode 100644 index 00000000000000..df5e36f0bacd56 --- /dev/null +++ b/playground/tailwind/src/components/component1.js @@ -0,0 +1,9 @@ +export const component1 = /* html */ ` +
component1
+` + +import.meta.hot?.accept((mod) => { + document.querySelectorAll('[data-id="component1"]').forEach((d) => { + d.outerHTML = mod.component1 + }) +}) diff --git a/playground/tailwind/src/main.js b/playground/tailwind/src/main.js index 78494e75b4741d..b9f0c5956232d5 100644 --- a/playground/tailwind/src/main.js +++ b/playground/tailwind/src/main.js @@ -1,6 +1,18 @@ -import { createApp } from 'vue' -import App from './App.vue' -import router from './router' -// import '../index.css'; +import { view1 } from './views/view1' -createApp(App).use(router).mount('#app') +export const main = (view1Content) => /* html */ ` +

Page title

+ ${view1Content} + +
style
+` + +document.getElementById('app').innerHTML = main(view1) + +import.meta.hot?.accept((mod) => { + document.getElementById('app').innerHTML = mod.main(view1) +}) + +import.meta.hot?.accept(['./views/view1'], ([mod]) => { + document.getElementById('app').innerHTML = main(mod.view1) +}) diff --git a/playground/tailwind/src/router.ts b/playground/tailwind/src/router.ts deleted file mode 100644 index 10e3980cb07cb8..00000000000000 --- a/playground/tailwind/src/router.ts +++ /dev/null @@ -1,16 +0,0 @@ -import { createRouter, createWebHistory } from 'vue-router' -import Page from './views/Page.vue' - -const history = createWebHistory() - -const router = createRouter({ - history: history, - routes: [ - { - path: '/', - component: Page, - }, - ], -}) - -export default router diff --git a/playground/tailwind/src/utils.ts b/playground/tailwind/src/utils.ts deleted file mode 100644 index 38c21ae7a0f8d8..00000000000000 --- a/playground/tailwind/src/utils.ts +++ /dev/null @@ -1,2 +0,0 @@ -export const NAME = 'Tailwind' -export const INITIAL_COUNT = 1 diff --git a/playground/tailwind/src/views/Page.vue b/playground/tailwind/src/views/Page.vue deleted file mode 100644 index 76f8aabf13d7d3..00000000000000 --- a/playground/tailwind/src/views/Page.vue +++ /dev/null @@ -1,33 +0,0 @@ - - - diff --git a/playground/tailwind/src/views/view1.js b/playground/tailwind/src/views/view1.js new file mode 100644 index 00000000000000..c9e0c0d1745fe2 --- /dev/null +++ b/playground/tailwind/src/views/view1.js @@ -0,0 +1,8 @@ +import { component1 } from '../components/component1' + +export const view1 = /* html */ ` +
+
|view1|
+ ${component1} +
+` diff --git a/playground/tailwind/tailwind.config.js b/playground/tailwind/tailwind.config.js index 1b80b08aba2ef1..e4504c499e78f0 100644 --- a/playground/tailwind/tailwind.config.js +++ b/playground/tailwind/tailwind.config.js @@ -2,10 +2,10 @@ module.exports = { content: [ - // Before editing this section, make sure no paths are matching with `/src/App.vue` + // Before editing this section, make sure no paths are matching with `/src/main.js` // Look https://github.com/vitejs/vite/pull/6959 for more details - __dirname + '/src/{components,views}/**/*.vue', - __dirname + '/src/App.vue', + __dirname + '/src/{components,views}/**/*.js', + __dirname + '/src/main.js', ], theme: { extend: {}, diff --git a/playground/tailwind/vite.config.ts b/playground/tailwind/vite.config.ts index d3680f6c39c3e3..5b97ed1053e382 100644 --- a/playground/tailwind/vite.config.ts +++ b/playground/tailwind/vite.config.ts @@ -1,5 +1,4 @@ import { defineConfig } from 'vite' -import vue from '@vitejs/plugin-vue' export default defineConfig({ resolve: { @@ -7,7 +6,6 @@ export default defineConfig({ '/@': __dirname, }, }, - plugins: [vue()], build: { // to make tests faster minify: false, @@ -17,4 +15,15 @@ export default defineConfig({ // although it should not affect the build origin: 'http://localhost:8080', }, + plugins: [ + { + name: 'delay view', + enforce: 'pre', + async transform(_code, id) { + if (id.includes('views/view1.js')) { + await new Promise((resolve) => setTimeout(resolve, 100)) + } + }, + }, + ], }) diff --git a/playground/test-utils.ts b/playground/test-utils.ts index df68dce9c5e66f..39e2f56c5e6a86 100644 --- a/playground/test-utils.ts +++ b/playground/test-utils.ts @@ -4,7 +4,11 @@ import fs from 'node:fs' import path from 'node:path' import colors from 'css-color-names' -import type { ConsoleMessage, ElementHandle } from 'playwright-chromium' +import type { + ConsoleMessage, + ElementHandle, + Locator, +} from 'playwright-chromium' import type { DepOptimizationMetadata, Manifest } from 'vite' import { normalizePath } from 'vite' import { fromComment } from 'convert-source-map' @@ -74,7 +78,9 @@ function rgbToHex(rgb: string): string { const timeout = (n: number) => new Promise((r) => setTimeout(r, n)) -async function toEl(el: string | ElementHandle): Promise { +async function toEl( + el: string | ElementHandle | Locator, +): Promise { if (typeof el === 'string') { const realEl = await page.$(el) if (realEl == null) { @@ -82,21 +88,30 @@ async function toEl(el: string | ElementHandle): Promise { } return realEl } + if ('elementHandle' in el) { + return el.elementHandle() + } return el } -export async function getColor(el: string | ElementHandle): Promise { +export async function getColor( + el: string | ElementHandle | Locator, +): Promise { el = await toEl(el) const rgb = await el.evaluate((el) => getComputedStyle(el as Element).color) return hexToNameMap[rgbToHex(rgb)] ?? rgb } -export async function getBg(el: string | ElementHandle): Promise { +export async function getBg( + el: string | ElementHandle | Locator, +): Promise { el = await toEl(el) return el.evaluate((el) => getComputedStyle(el as Element).backgroundImage) } -export async function getBgColor(el: string | ElementHandle): Promise { +export async function getBgColor( + el: string | ElementHandle | Locator, +): Promise { el = await toEl(el) return el.evaluate((el) => getComputedStyle(el as Element).backgroundColor) }