feat: add Vite 7 support to the @tailwindcss/vite plugin (#18384)

Closes #18381 

* [Changelog for Vite 7.0.0
(2025-06-24)](https://github.com/vitejs/vite/blob/main/packages/vite/CHANGELOG.md#700-2025-06-24)

Starting from Vite 7, Node 18 support will be dropped, which doesn't
really affect Tailwind. It might be worth mentioning in the
documentation that the recommended minimum Node versions are 20.19 and
22.12.

Vite 7 is only available in ESM format, which is also not an issue.

Vite's browser support aligns with the v4 guidelines:
```
Chrome 87 → 107       (tw: 111)
Edge 88 → 107         (tw: 111)
Firefox 78 → 104      (tw: 128)
Safari 14.0 → 16.0    (tw: 16.4)
```
* [Vite 7 - Browser
Support](https://vite.dev/guide/migration.html#default-browser-target-change)
* [Tailwind CSS v4 - Browser
Support](https://tailwindcss.com/docs/compatibility#browser-support)

So, at first glance, there's nothing more to do except enabling support
for these versions.

---------

Co-authored-by: Jordan Pittman <jordan@cryptica.me>
This commit is contained in:
Rózsa Zoltán 2025-06-24 18:31:17 +02:00 • committed by GitHub
parent b9007dd9f8
commit aa859314d9
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
19 changed files with 434 additions and 407 deletions

View file

@ -10,6 +10,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
- Add heuristic to skip candidate migrations inside `emit(…)` ([#18330](https://github.com/tailwindlabs/tailwindcss/pull/18330))
- Extract candidates with variants in Clojure/ClojureScript keywords ([#18338](https://github.com/tailwindlabs/tailwindcss/pull/18338))
- Document `--watch=always` in the CLI's usage ([#18337](https://github.com/tailwindlabs/tailwindcss/pull/18337))
- Add support for Vite 7 to `@tailwindcss/vite` ([#18384](https://github.com/tailwindlabs/tailwindcss/pull/18384))
## [4.1.10] - 2025-06-11

View file

@ -12,7 +12,7 @@ test(
"tailwindcss": "workspace:^"
},
"devDependencies": {
"vite": "^6"
"vite": "^7"
}
}
`,
@ -76,7 +76,7 @@ test(
"tailwindcss": "workspace:^"
},
"devDependencies": {
"vite": "^6"
"vite": "^7"
}
}
`,
@ -140,7 +140,7 @@ test(
"tailwindcss": "workspace:^"
},
"devDependencies": {
"vite": "^6"
"vite": "^7"
}
}
`,
@ -219,7 +219,7 @@ test(
"tailwindcss": "workspace:^"
},
"devDependencies": {
"vite": "^6"
"vite": "^7"
}
}
`,

View file

@ -15,7 +15,7 @@ describe.each(['postcss', 'lightningcss'])('%s', (transformer) => {
},
"devDependencies": {
${transformer === 'lightningcss' ? `"lightningcss": "^1",` : ''}
"vite": "^6"
"vite": "^7"
}
}
`,

View file

@ -12,7 +12,7 @@ test(
},
"devDependencies": {
"@tailwindcss/vite": "workspace:^",
"vite": "^6"
"vite": "^7"
}
}
`,

View file

@ -11,7 +11,7 @@ const WORKSPACE = {
"tailwindcss": "workspace:^"
},
"devDependencies": {
"vite": "^6"
"vite": "^7"
}
}
`,

View file

@ -34,7 +34,7 @@ describe.each(['postcss', 'lightningcss'])('%s', (transformer) => {
},
"devDependencies": {
${transformer === 'lightningcss' ? `"lightningcss": "^1",` : ''}
"vite": "^6"
"vite": "^7"
}
}
`,
@ -111,7 +111,7 @@ describe.each(['postcss', 'lightningcss'])('%s', (transformer) => {
},
"devDependencies": {
${transformer === 'lightningcss' ? `"lightningcss": "^1",` : ''}
"vite": "^6"
"vite": "^7"
}
}
`,
@ -312,7 +312,7 @@ describe.each(['postcss', 'lightningcss'])('%s', (transformer) => {
},
"devDependencies": {
${transformer === 'lightningcss' ? `"lightningcss": "^1",` : ''}
"vite": "^6"
"vite": "^7"
}
}
`,
@ -491,7 +491,7 @@ describe.each(['postcss', 'lightningcss'])('%s', (transformer) => {
},
"devDependencies": {
${transformer === 'lightningcss' ? `"lightningcss": "^1",` : ''}
"vite": "^6"
"vite": "^7"
}
}
`,
@ -577,7 +577,7 @@ describe.each(['postcss', 'lightningcss'])('%s', (transformer) => {
},
"devDependencies": {
${transformer === 'lightningcss' ? `"lightningcss": "^1",` : ''}
"vite": "^6"
"vite": "^7"
}
}
`,
@ -679,7 +679,7 @@ describe.each(['postcss', 'lightningcss'])('%s', (transformer) => {
},
"devDependencies": {
${transformer === 'lightningcss' ? `"lightningcss": "^1",` : ''}
"vite": "^6"
"vite": "^7"
}
}
`,
@ -744,7 +744,7 @@ test(
"tailwindcss": "workspace:^"
},
"devDependencies": {
"vite": "^6"
"vite": "^7"
}
}
`,
@ -816,7 +816,7 @@ test(
"tailwindcss": "workspace:^"
},
"devDependencies": {
"vite": "^6"
"vite": "^7"
}
}
`,
@ -879,7 +879,7 @@ test(
"@tailwindcss/vite": "workspace:^",
"tailwindcss": "workspace:^",
"plotly.js": "^3",
"vite": "^6"
"vite": "^7"
}
}
`,

View file

@ -12,7 +12,7 @@ test(
"tailwindcss": "workspace:^"
},
"devDependencies": {
"vite": "^6"
"vite": "^7"
}
}
`,
@ -96,7 +96,7 @@ test(
"tailwindcss": "workspace:^"
},
"devDependencies": {
"vite": "^6"
"vite": "^7"
}
}
`,

View file

@ -14,7 +14,7 @@ function createSetup(transformer: 'postcss' | 'lightningcss') {
},
"devDependencies": {
${transformer === 'lightningcss' ? `"lightningcss": "^1",` : ''}
"vite": "^6"
"vite": "^7"
}
}
`,

View file

@ -13,7 +13,7 @@ test(
},
"devDependencies": {
"lightningcss": "^1",
"vite": "^6"
"vite": "^7"
}
}
`,

View file

@ -119,3 +119,50 @@ test(
])
},
)
test(
`Vite 7`,
{
fs: {
'package.json': json`
{
"type": "module",
"dependencies": {
"@tailwindcss/vite": "workspace:^",
"tailwindcss": "workspace:^"
},
"devDependencies": {
"vite": "^7"
}
}
`,
'vite.config.ts': ts`
import tailwindcss from '@tailwindcss/vite'
import { defineConfig } from 'vite'
export default defineConfig({
build: {
cssMinify: false,
ssrEmitAssets: true,
},
plugins: [tailwindcss()],
})
`,
...WORKSPACE,
},
},
async ({ fs, exec, expect }) => {
await exec('pnpm vite build --ssr server.ts')
let files = await fs.glob('dist/**/*.css')
expect(files).toHaveLength(1)
let [filename] = files[0]
await fs.expectFileToContain(filename, [
candidate`underline`,
candidate`m-2`,
candidate`overline`,
candidate`m-3`,
])
},
)

View file

@ -14,7 +14,7 @@ test(
"devDependencies": {
"@sveltejs/vite-plugin-svelte": "^5",
"@tailwindcss/vite": "workspace:^",
"vite": "^6"
"vite": "^7"
}
}
`,
@ -125,7 +125,7 @@ test(
"devDependencies": {
"@sveltejs/vite-plugin-svelte": "^5",
"@tailwindcss/vite": "workspace:^",
"vite": "^6"
"vite": "^7"
}
}
`,

View file

@ -17,7 +17,7 @@ describe.each(['postcss', 'lightningcss'])('%s', (transformer) => {
"devDependencies": {
${transformer === 'lightningcss' ? `"lightningcss": "^1",` : ''}
"@tailwindcss/vite": "workspace:^",
"vite": "^6"
"vite": "^7"
}
}
`,

View file

@ -15,7 +15,7 @@ test(
"devDependencies": {
"@vitejs/plugin-vue": "^5.1.2",
"@tailwindcss/vite": "workspace:^",
"vite": "^6"
"vite": "^7"
}
}
`,
@ -87,7 +87,7 @@ test(
"devDependencies": {
"@vitejs/plugin-vue": "^5.1.2",
"@tailwindcss/vite": "workspace:^",
"vite": "^6"
"vite": "^7"
}
}
`,

View file

@ -37,6 +37,6 @@
"vite": "catalog:"
},
"peerDependencies": {
"vite": "^5.2.0 || ^6"
"vite": "^5.2.0 || ^6 || ^7"
}
}

View file

@ -400,7 +400,7 @@ test('@layer', async () => {
})
test('supports theme(reference) imports', async () => {
expect(
await expect(
run(
css`
@tailwind utilities;
@ -542,7 +542,7 @@ test('it crashes when inside a cycle', async () => {
base: '/root',
})
expect(
await expect(
run(
css`
@import 'foo.css';

View file

@ -23,7 +23,7 @@ describe('--alpha(…)', () => {
})
test('--alpha(…) errors when no arguments are used', async () => {
expect(() =>
await expect(() =>
compileCss(css`
.foo {
margin: --alpha();
@ -35,7 +35,7 @@ describe('--alpha(…)', () => {
})
test('--alpha(…) errors when alpha value is missing', async () => {
expect(() =>
await expect(() =>
compileCss(css`
.foo {
margin: --alpha(red);
@ -47,7 +47,7 @@ describe('--alpha(…)', () => {
})
test('--alpha(…) errors multiple arguments are used', async () => {
expect(() =>
await expect(() =>
compileCss(css`
.foo {
margin: --alpha(red / 50%, blue);
@ -101,7 +101,7 @@ describe('--spacing(…)', () => {
})
test('--spacing(…) relies on `--spacing` to be defined', async () => {
expect(() =>
await expect(() =>
compileCss(css`
.foo {
margin: --spacing(4);
@ -113,7 +113,7 @@ describe('--spacing(…)', () => {
})
test('--spacing(…) requires a single value', async () => {
expect(() =>
await expect(() =>
compileCss(css`
@theme {
--spacing: 0.25rem;
@ -129,7 +129,7 @@ describe('--spacing(…)', () => {
})
test('--spacing(…) does not have multiple arguments', async () => {
expect(() =>
await expect(() =>
compileCss(css`
.foo {
margin: --spacing(4, 5, 6);
@ -364,7 +364,7 @@ describe('--theme(…)', () => {
})
test('--theme(…) can only be used with CSS variables from your @theme', async () => {
expect(() =>
await expect(() =>
compileCss(css`
@theme {
--color-red-500: #f00;
@ -377,7 +377,7 @@ describe('--theme(…)', () => {
`[Error: The --theme(…) function can only be used with CSS variables from your theme.]`,
)
expect(() =>
await expect(() =>
compileCss(css`
@theme {
--color-red-500: #f00;
@ -789,7 +789,7 @@ describe('theme(…)', () => {
})
test('theme(colors.unknown.500)', async () =>
expect(() =>
await expect(() =>
compileCss(css`
.red {
color: theme(colors.unknown.500);

View file

@ -4363,7 +4363,7 @@ test('addBase', async () => {
})
it("should error when `layer(…)` is used, but it's not the first param", async () => {
expect(async () => {
await expect(async () => {
return await compileCss(
css`
@import './bar.css' supports(display: grid) layer(utilities);

713
pnpm-lock.yaml generated

File diff suppressed because it is too large Load diff

View file

@ -6,9 +6,9 @@ packages:
- 'integrations'
catalog:
'@types/node': ^20.14.8
'@types/node': ^20.19.0
prettier: 3.5.0
vite: ^6.0.0
vite: ^7.0.0
lightningcss: 1.30.1
lightningcss-darwin-arm64: 1.30.1
lightningcss-darwin-x64: 1.30.1