diff --git a/packages/playground/tailwind/__test__/tailwind.spec.ts b/packages/playground/tailwind/__test__/tailwind.spec.ts
new file mode 100644
index 00000000000000..105eb245bf207e
--- /dev/null
+++ b/packages/playground/tailwind/__test__/tailwind.spec.ts
@@ -0,0 +1,40 @@
+import { isBuild, editFile, untilUpdated, getColor } from '../../testUtils'
+
+test('should render', async () => {
+ expect(await page.textContent('#pagetitle')).toBe('|Page title|')
+})
+
+if (!isBuild) {
+ test('regenerate CSS and HMR', async () => {
+ browserLogs.length = 0
+ const el = await page.$('#pagetitle')
+ const el2 = await page.$('#helloroot')
+
+ expect(await getColor(el)).toBe('rgb(11, 22, 33)')
+
+ editFile('src/views/Page.vue', (code) =>
+ code.replace('|Page title|', '|Page title updated|')
+ )
+ await untilUpdated(() => el.textContent(), '|Page title updated|')
+
+ expect(browserLogs).toMatchObject([
+ '[vite] css hot updated: /index.css',
+ '[vite] hot updated: /src/views/Page.vue'
+ ])
+
+ browserLogs.length = 0
+
+ editFile('src/components/HelloWorld.vue', (code) =>
+ code.replace('text-gray-800', 'text-[rgb(10,20,30)]')
+ )
+
+ await untilUpdated(() => getColor(el2), 'rgb(10, 20, 30)')
+
+ expect(browserLogs).toMatchObject([
+ '[vite] css hot updated: /index.css',
+ '[vite] hot updated: /src/components/HelloWorld.vue'
+ ])
+
+ browserLogs.length = 0
+ })
+}
diff --git a/packages/playground/tailwind/index.css b/packages/playground/tailwind/index.css
new file mode 100644
index 00000000000000..04b35af2af65c8
--- /dev/null
+++ b/packages/playground/tailwind/index.css
@@ -0,0 +1,3 @@
+@tailwind base;
+@tailwind components;
+@tailwind utilities;
diff --git a/packages/playground/tailwind/index.html b/packages/playground/tailwind/index.html
new file mode 100644
index 00000000000000..5165c9f6325cde
--- /dev/null
+++ b/packages/playground/tailwind/index.html
@@ -0,0 +1,14 @@
+
+
+
+
+
+
+ Vite App
+
+
+
+
+
+
+
diff --git a/packages/playground/tailwind/package.json b/packages/playground/tailwind/package.json
new file mode 100644
index 00000000000000..7bdb376a7edd8d
--- /dev/null
+++ b/packages/playground/tailwind/package.json
@@ -0,0 +1,21 @@
+{
+ "name": "test-tailwind",
+ "private": true,
+ "version": "0.0.0",
+ "scripts": {
+ "dev": "vite",
+ "build": "vite build",
+ "debug": "node --inspect-brk ../../vite/bin/vite",
+ "serve": "vite preview"
+ },
+ "dependencies": {
+ "autoprefixer": "^10.3.0",
+ "tailwindcss": "^2.2.4",
+ "vue": "^3.0.8"
+ },
+ "devDependencies": {
+ "@vitejs/plugin-vue": "^1.0.0",
+ "@vue/compiler-sfc": "^3.0.8",
+ "vue-router": "^4.0.10"
+ }
+}
diff --git a/packages/playground/tailwind/postcss.config.js b/packages/playground/tailwind/postcss.config.js
new file mode 100644
index 00000000000000..b73493f7f96fae
--- /dev/null
+++ b/packages/playground/tailwind/postcss.config.js
@@ -0,0 +1,7 @@
+// postcss.config.js
+module.exports = {
+ plugins: {
+ tailwindcss: { config: __dirname + '/tailwind.config.js' },
+ autoprefixer: {}
+ }
+}
diff --git a/packages/playground/tailwind/public/favicon.ico b/packages/playground/tailwind/public/favicon.ico
new file mode 100644
index 00000000000000..df36fcfb72584e
Binary files /dev/null and b/packages/playground/tailwind/public/favicon.ico differ
diff --git a/packages/playground/tailwind/src/App.vue b/packages/playground/tailwind/src/App.vue
new file mode 100644
index 00000000000000..a4c63083c17349
--- /dev/null
+++ b/packages/playground/tailwind/src/App.vue
@@ -0,0 +1,12 @@
+
+
+
Tailwind app
+ {{ foo }}
+
+
+
+
+
diff --git a/packages/playground/tailwind/src/assets/logo.png b/packages/playground/tailwind/src/assets/logo.png
new file mode 100644
index 00000000000000..f3d2503fc2a44b
Binary files /dev/null and b/packages/playground/tailwind/src/assets/logo.png differ
diff --git a/packages/playground/tailwind/src/components/HelloWorld.vue b/packages/playground/tailwind/src/components/HelloWorld.vue
new file mode 100644
index 00000000000000..36bcdb634a7cd6
--- /dev/null
+++ b/packages/playground/tailwind/src/components/HelloWorld.vue
@@ -0,0 +1,7 @@
+
+ HelloWorld - {{ count }}
+
+
+
diff --git a/packages/playground/tailwind/src/main.js b/packages/playground/tailwind/src/main.js
new file mode 100644
index 00000000000000..78494e75b4741d
--- /dev/null
+++ b/packages/playground/tailwind/src/main.js
@@ -0,0 +1,6 @@
+import { createApp } from 'vue'
+import App from './App.vue'
+import router from './router'
+// import '../index.css';
+
+createApp(App).use(router).mount('#app')
diff --git a/packages/playground/tailwind/src/router.ts b/packages/playground/tailwind/src/router.ts
new file mode 100644
index 00000000000000..32f1a47b40540d
--- /dev/null
+++ b/packages/playground/tailwind/src/router.ts
@@ -0,0 +1,16 @@
+import { createWebHistory, createRouter } from 'vue-router'
+import Page from './views/Page.vue'
+
+const history = createWebHistory()
+
+const routeur = createRouter({
+ history: history,
+ routes: [
+ {
+ path: '/',
+ component: Page
+ }
+ ]
+})
+
+export default routeur
diff --git a/packages/playground/tailwind/src/views/Page.vue b/packages/playground/tailwind/src/views/Page.vue
new file mode 100644
index 00000000000000..39d66a61893e29
--- /dev/null
+++ b/packages/playground/tailwind/src/views/Page.vue
@@ -0,0 +1,26 @@
+
+
+
|Page title|
+
{{ val }}
+
Tailwind style
+
+
+
+
+
diff --git a/packages/playground/tailwind/tailwind.config.js b/packages/playground/tailwind/tailwind.config.js
new file mode 100644
index 00000000000000..eb7a876578f52e
--- /dev/null
+++ b/packages/playground/tailwind/tailwind.config.js
@@ -0,0 +1,12 @@
+module.exports = {
+ mode: 'jit',
+ purge: [__dirname + '/src/**/*.vue'],
+ darkMode: false, // or 'media' or 'class'
+ theme: {
+ extend: {}
+ },
+ variants: {
+ extend: {}
+ },
+ plugins: []
+}
diff --git a/packages/playground/tailwind/vite.config.ts b/packages/playground/tailwind/vite.config.ts
new file mode 100644
index 00000000000000..8d076bee7e2277
--- /dev/null
+++ b/packages/playground/tailwind/vite.config.ts
@@ -0,0 +1,15 @@
+import { defineConfig } from 'vite'
+import vue from '@vitejs/plugin-vue'
+
+export default defineConfig({
+ resolve: {
+ alias: {
+ '/@': __dirname
+ }
+ },
+ plugins: [vue()],
+ build: {
+ // to make tests faster
+ minify: false
+ }
+})
diff --git a/packages/vite/src/node/plugins/css.ts b/packages/vite/src/node/plugins/css.ts
index f738decd137360..f2d358d29133d0 100644
--- a/packages/vite/src/node/plugins/css.ts
+++ b/packages/vite/src/node/plugins/css.ts
@@ -41,6 +41,7 @@ import type Sass from 'sass'
import type Stylus from 'stylus' // eslint-disable-line node/no-extraneous-import
import type Less from 'less'
import { Alias } from 'types/alias'
+import type { ModuleNode } from '../server/moduleGraph'
// const debug = createDebugger('vite:css')
@@ -191,9 +192,16 @@ export function cssPlugin(config: ResolvedConfig): Plugin {
if (deps) {
// record deps in the module graph so edits to @import css can trigger
// main import to hot update
- const depModules = new Set(
- [...deps].map((file) => moduleGraph.createFileOnlyEntry(file))
- )
+ const depModules = new Set()
+ for (const file of deps) {
+ depModules.add(
+ cssLangRE.test(file)
+ ? moduleGraph.createFileOnlyEntry(file)
+ : await moduleGraph.ensureEntryFromUrl(
+ await fileToUrl(file, config, this)
+ )
+ )
+ }
moduleGraph.updateModuleInfo(
thisModule,
depModules,