mirror of
https://github.com/tailwindlabs/tailwindcss.git
synced 2025-12-08 21:36:08 +00:00
When your Vite or postcss project has multiple Tailwind CSS roots with different configs, they should not influence each other (with the exception of the same candidates being used).
165 lines
4.6 KiB
TypeScript
165 lines
4.6 KiB
TypeScript
import { expect } from 'vitest'
|
|
import { candidate, css, fetchStyles, html, json, retryAssertion, test, ts } from '../utils'
|
|
|
|
test(
|
|
`production build`,
|
|
{
|
|
fs: {
|
|
'package.json': json`
|
|
{
|
|
"type": "module",
|
|
"dependencies": {
|
|
"@tailwindcss/vite": "workspace:^",
|
|
"tailwindcss": "workspace:^"
|
|
},
|
|
"devDependencies": {
|
|
"vite": "^5.3.5"
|
|
}
|
|
}
|
|
`,
|
|
'vite.config.ts': ts`
|
|
import tailwindcss from '@tailwindcss/vite'
|
|
import path from 'node:path'
|
|
import { defineConfig } from 'vite'
|
|
|
|
export default defineConfig({
|
|
build: {
|
|
cssMinify: false,
|
|
rollupOptions: {
|
|
input: {
|
|
root1: path.resolve(__dirname, 'root1.html'),
|
|
root2: path.resolve(__dirname, 'root2.html'),
|
|
},
|
|
},
|
|
},
|
|
plugins: [tailwindcss()],
|
|
})
|
|
`,
|
|
'root1.html': html`
|
|
<head>
|
|
<link rel="stylesheet" href="./src/root1.css" />
|
|
</head>
|
|
<body>
|
|
<div class="one:underline two:underline">Hello, world!</div>
|
|
</body>
|
|
`,
|
|
'src/shared.css': css`
|
|
@import 'tailwindcss/theme' theme(reference);
|
|
@import 'tailwindcss/utilities';
|
|
`,
|
|
'src/root1.css': css`
|
|
@import './shared.css';
|
|
@variant one (&:is([data-root='1']));
|
|
`,
|
|
'root2.html': html`
|
|
<head>
|
|
<link rel="stylesheet" href="./src/root2.css" />
|
|
</head>
|
|
<body>
|
|
<div class="one:underline two:underline">Hello, world!</div>
|
|
</body>
|
|
`,
|
|
'src/root2.css': css`
|
|
@import './shared.css';
|
|
@variant two (&:is([data-root='2']));
|
|
`,
|
|
},
|
|
},
|
|
async ({ fs, exec }) => {
|
|
await exec('pnpm vite build')
|
|
|
|
let files = await fs.glob('dist/**/*.css')
|
|
expect(files).toHaveLength(2)
|
|
|
|
let root1 = files.find(([filename]) => filename.includes('root1'))
|
|
let root2 = files.find(([filename]) => filename.includes('root2'))
|
|
|
|
expect(root1).toBeDefined()
|
|
expect(root2).toBeDefined()
|
|
|
|
expect(root1![1]).toContain(candidate`one:underline`)
|
|
expect(root1![1]).not.toContain(candidate`two:underline`)
|
|
|
|
expect(root2![1]).not.toContain(candidate`one:underline`)
|
|
expect(root2![1]).toContain(candidate`two:underline`)
|
|
},
|
|
)
|
|
|
|
test(
|
|
`dev mode`,
|
|
{
|
|
fs: {
|
|
'package.json': json`
|
|
{
|
|
"type": "module",
|
|
"dependencies": {
|
|
"@tailwindcss/vite": "workspace:^",
|
|
"tailwindcss": "workspace:^"
|
|
},
|
|
"devDependencies": {
|
|
"vite": "^5.3.5"
|
|
}
|
|
}
|
|
`,
|
|
'vite.config.ts': ts`
|
|
import tailwindcss from '@tailwindcss/vite'
|
|
import path from 'node:path'
|
|
import { defineConfig } from 'vite'
|
|
|
|
export default defineConfig({
|
|
build: { cssMinify: false },
|
|
plugins: [tailwindcss()],
|
|
})
|
|
`,
|
|
'root1.html': html`
|
|
<head>
|
|
<link rel="stylesheet" href="./src/root1.css" />
|
|
</head>
|
|
<body>
|
|
<div class="one:underline two:underline">Hello, world!</div>
|
|
</body>
|
|
`,
|
|
'src/shared.css': css`
|
|
@import 'tailwindcss/theme' theme(reference);
|
|
@import 'tailwindcss/utilities';
|
|
`,
|
|
'src/root1.css': css`
|
|
@import './shared.css';
|
|
@variant one (&:is([data-root='1']));
|
|
`,
|
|
'root2.html': html`
|
|
<head>
|
|
<link rel="stylesheet" href="./src/root2.css" />
|
|
</head>
|
|
<body>
|
|
<div class="one:underline two:underline">Hello, world!</div>
|
|
</body>
|
|
`,
|
|
'src/root2.css': css`
|
|
@import './shared.css';
|
|
@variant two (&:is([data-root='2']));
|
|
`,
|
|
},
|
|
},
|
|
async ({ root, spawn, getFreePort, fs }) => {
|
|
let port = await getFreePort()
|
|
await spawn(`pnpm vite dev --port ${port}`)
|
|
|
|
// Candidates are resolved lazily, so the first visit of index.html
|
|
// will only have candidates from this file.
|
|
await retryAssertion(async () => {
|
|
let styles = await fetchStyles(port, '/root1.html')
|
|
expect(styles).toContain(candidate`one:underline`)
|
|
expect(styles).not.toContain(candidate`two:underline`)
|
|
})
|
|
|
|
// Going to about.html will extend the candidate list to include
|
|
// candidates from about.html.
|
|
await retryAssertion(async () => {
|
|
let styles = await fetchStyles(port, '/root2.html')
|
|
expect(styles).not.toContain(candidate`one:underline`)
|
|
expect(styles).toContain(candidate`two:underline`)
|
|
})
|
|
},
|
|
)
|