mirror of
https://github.com/tailwindlabs/tailwindcss.git
synced 2025-12-08 21:36:08 +00:00
Alternative to #16425 Fixes #16585 Fixes #16389 Fixes #16252 Fixes #15794 Fixes #16646 Fixes #16358 This PR changes the Vite plugin to use the file-system to discover potential class names instead of relying on the module-graph. This comes after a lot of testing and various issue reports where builds that span different Vite instances were missing class names. Because we now scan for candidates using the file-system, we can also remove a lot of the bookkeeping necessary to make production builds and development builds work as we no longer have to change the resulting stylesheet based on the `transform` callbacks of other files that might happen later. This change comes at a small performance penalty that is noticeable especially on very large projects with many files to scan. However, we offset that change by fixing an issue that I found in the current Vite integration that did a needless rebuild of the whole Tailwind root whenever any source file changed. Because of how impactful this change is, I expect many normal to medium sized projects to actually see a performance improvement after these changes. Furthermore we do plan to continue to use the module-graph to further improve the performance in dev mode. ## Test plan - Added new integration tests with cases found across the issues above. - Manual testing by adding a local version of the Vite plugin to repos from the issue list above and the [tailwindcss playgrounds](https://github.com/philipp-spiess/tailwindcss-playgrounds).
122 lines
2.7 KiB
TypeScript
122 lines
2.7 KiB
TypeScript
import { candidate, css, html, json, test, ts } from '../utils'
|
|
|
|
const WORKSPACE = {
|
|
'index.html': html`
|
|
<body>
|
|
<div id="app"></div>
|
|
<script type="module" src="./src/index.ts"></script>
|
|
</body>
|
|
`,
|
|
'src/index.css': css`@import 'tailwindcss';`,
|
|
'src/index.ts': ts`
|
|
import './index.css'
|
|
|
|
document.querySelector('#app').innerHTML = \`
|
|
<div class="underline m-2">Hello, world!</div>
|
|
\`
|
|
`,
|
|
'server.ts': ts`
|
|
import css from './src/index.css?url'
|
|
|
|
document.querySelector('#app').innerHTML = \`
|
|
<link rel="stylesheet" href="\${css}">
|
|
<div class="overline m-3">Hello, world!</div>
|
|
\`
|
|
`,
|
|
}
|
|
|
|
test(
|
|
'Vite 5',
|
|
{
|
|
fs: {
|
|
'package.json': json`
|
|
{
|
|
"type": "module",
|
|
"dependencies": {
|
|
"@tailwindcss/vite": "workspace:^",
|
|
"tailwindcss": "workspace:^"
|
|
},
|
|
"_comment": "This test uses Vite 5.3 on purpose. Do not upgrade it to Vite 6.",
|
|
"devDependencies": {
|
|
"vite": "^5.3"
|
|
}
|
|
}
|
|
`,
|
|
'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`,
|
|
])
|
|
},
|
|
)
|
|
|
|
test(
|
|
`Vite 6`,
|
|
{
|
|
fs: {
|
|
'package.json': json`
|
|
{
|
|
"type": "module",
|
|
"dependencies": {
|
|
"@tailwindcss/vite": "workspace:^",
|
|
"tailwindcss": "workspace:^"
|
|
},
|
|
"devDependencies": {
|
|
"vite": "^6.0"
|
|
}
|
|
}
|
|
`,
|
|
'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`,
|
|
])
|
|
},
|
|
)
|