Support Vite Environment API (#18970)
Fixes #18002 Very much a work in progress b/c I don't (yet) understand how the newer APIs are intended to function. - [x] Needs env specific tests that verify the environment API is being used
This commit is contained in:
parent
c532955dd1
commit
e4b6c67bcb
3 changed files with 120 additions and 24 deletions
|
|
@ -13,6 +13,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
|
|||
- Include filename and line numbers in CSS parse errors ([#19282](https://github.com/tailwindlabs/tailwindcss/pull/19282))
|
||||
- Skip comments in Ruby files when checking for class names ([#19243](https://github.com/tailwindlabs/tailwindcss/pull/19243))
|
||||
- Skip over arbitrary property utilities with a top-level `!` in the value ([#19243](https://github.com/tailwindlabs/tailwindcss/pull/19243))
|
||||
- Support environment API in `@tailwindcss/vite` ([#18970](https://github.com/tailwindlabs/tailwindcss/pull/18970))
|
||||
|
||||
### Added
|
||||
|
||||
|
|
|
|||
|
|
@ -1103,3 +1103,63 @@ test(
|
|||
expect(content).toContain('display: flex;')
|
||||
},
|
||||
)
|
||||
|
||||
test(
|
||||
`the plugin works when using the environment API`,
|
||||
{
|
||||
fs: {
|
||||
'package.json': txt`
|
||||
{
|
||||
"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({
|
||||
plugins: [tailwindcss()],
|
||||
builder: {},
|
||||
environments: {
|
||||
server: {
|
||||
build: {
|
||||
cssMinify: false,
|
||||
emitAssets: true,
|
||||
rollupOptions: { input: './src/server.ts' },
|
||||
},
|
||||
},
|
||||
},
|
||||
})
|
||||
`,
|
||||
// Has to exist or the build fails
|
||||
'index.html': html`
|
||||
<div class="content-['index.html']"></div>
|
||||
`,
|
||||
'src/server.ts': js`
|
||||
// Import the stylesheet in the server build
|
||||
import a from './index.css?url'
|
||||
console.log(a)
|
||||
`,
|
||||
'src/index.css': css`
|
||||
@reference 'tailwindcss/theme';
|
||||
@import 'tailwindcss/utilities';
|
||||
`,
|
||||
},
|
||||
},
|
||||
async ({ root, fs, exec, expect }) => {
|
||||
await exec('pnpm vite build', { cwd: root })
|
||||
|
||||
let files = await fs.glob('dist/**/*.css')
|
||||
expect(files).toHaveLength(1)
|
||||
let [filename] = files[0]
|
||||
|
||||
await fs.expectFileToContain(filename, [candidate`content-['index.html']`])
|
||||
},
|
||||
)
|
||||
|
|
|
|||
|
|
@ -11,7 +11,8 @@ import { clearRequireCache } from '@tailwindcss/node/require-cache'
|
|||
import { Scanner } from '@tailwindcss/oxide'
|
||||
import fs from 'node:fs/promises'
|
||||
import path from 'node:path'
|
||||
import type { Plugin, ResolvedConfig, ViteDevServer } from 'vite'
|
||||
import type { Environment, Plugin, ResolvedConfig, ViteDevServer } from 'vite'
|
||||
import * as vite from 'vite'
|
||||
|
||||
const DEBUG = env.DEBUG
|
||||
const SPECIAL_QUERY_RE = /[?&](?:worker|sharedworker|raw|url)\b/
|
||||
|
|
@ -28,28 +29,51 @@ export type PluginOptions = {
|
|||
export default function tailwindcss(opts: PluginOptions = {}): Plugin[] {
|
||||
let servers: ViteDevServer[] = []
|
||||
let config: ResolvedConfig | null = null
|
||||
let rootsByEnv = new DefaultMap<string, Map<string, Root>>((env: string) => new Map())
|
||||
|
||||
let isSSR = false
|
||||
let shouldOptimize = true
|
||||
let minify = true
|
||||
|
||||
let roots: DefaultMap<string, Root> = new DefaultMap((id) => {
|
||||
let cssResolver = config!.createResolver({
|
||||
...config!.resolve,
|
||||
extensions: ['.css'],
|
||||
mainFields: ['style'],
|
||||
conditions: ['style', 'development|production'],
|
||||
tryIndex: false,
|
||||
preferRelative: true,
|
||||
})
|
||||
function customCssResolver(id: string, base: string) {
|
||||
return cssResolver(id, base, true, isSSR)
|
||||
function createRoot(env: Environment | null, id: string) {
|
||||
type ResolveFn = (id: string, base: string) => Promise<string | false | undefined>
|
||||
|
||||
let customCssResolver: ResolveFn
|
||||
let customJsResolver: ResolveFn
|
||||
|
||||
if (!env) {
|
||||
// Older, pre-environment Vite API
|
||||
// TODO: Can we drop this??
|
||||
let cssResolver = config!.createResolver({
|
||||
...config!.resolve,
|
||||
extensions: ['.css'],
|
||||
mainFields: ['style'],
|
||||
conditions: ['style', 'development|production'],
|
||||
tryIndex: false,
|
||||
preferRelative: true,
|
||||
})
|
||||
|
||||
let jsResolver = config!.createResolver(config!.resolve)
|
||||
|
||||
customCssResolver = (id: string, base: string) => cssResolver(id, base, true, isSSR)
|
||||
customJsResolver = (id: string, base: string) => jsResolver(id, base, true, isSSR)
|
||||
} else {
|
||||
// Newer Vite versions
|
||||
let cssResolver = vite.createIdResolver(env.config, {
|
||||
...env.config.resolve,
|
||||
extensions: ['.css'],
|
||||
mainFields: ['style'],
|
||||
conditions: ['style', 'development|production'],
|
||||
tryIndex: false,
|
||||
preferRelative: true,
|
||||
})
|
||||
|
||||
let jsResolver = vite.createIdResolver(env.config, env.config.resolve)
|
||||
|
||||
customCssResolver = (id: string, base: string) => cssResolver(env, id, base, true)
|
||||
customJsResolver = (id: string, base: string) => jsResolver(env, id, base, true)
|
||||
}
|
||||
|
||||
let jsResolver = config!.createResolver(config!.resolve)
|
||||
function customJsResolver(id: string, base: string) {
|
||||
return jsResolver(id, base, true, isSSR)
|
||||
}
|
||||
return new Root(
|
||||
id,
|
||||
config!.root,
|
||||
|
|
@ -59,7 +83,7 @@ export default function tailwindcss(opts: PluginOptions = {}): Plugin[] {
|
|||
customCssResolver,
|
||||
customJsResolver,
|
||||
)
|
||||
})
|
||||
}
|
||||
|
||||
return [
|
||||
{
|
||||
|
|
@ -110,7 +134,12 @@ export default function tailwindcss(opts: PluginOptions = {}): Plugin[] {
|
|||
using I = new Instrumentation()
|
||||
DEBUG && I.start('[@tailwindcss/vite] Generate CSS (serve)')
|
||||
|
||||
let roots = rootsByEnv.get(this.environment?.name ?? 'default')
|
||||
let root = roots.get(id)
|
||||
if (!root) {
|
||||
root ??= createRoot(this.environment ?? null, id)
|
||||
roots.set(id, root)
|
||||
}
|
||||
|
||||
let result = await root.generate(src, (file) => this.addWatchFile(file), I)
|
||||
if (!result) {
|
||||
|
|
@ -129,7 +158,6 @@ export default function tailwindcss(opts: PluginOptions = {}): Plugin[] {
|
|||
name: '@tailwindcss/vite:generate:build',
|
||||
apply: 'build',
|
||||
enforce: 'pre',
|
||||
|
||||
transform: {
|
||||
filter: {
|
||||
id: {
|
||||
|
|
@ -143,7 +171,12 @@ export default function tailwindcss(opts: PluginOptions = {}): Plugin[] {
|
|||
using I = new Instrumentation()
|
||||
DEBUG && I.start('[@tailwindcss/vite] Generate CSS (build)')
|
||||
|
||||
let roots = rootsByEnv.get(this.environment?.name ?? 'default')
|
||||
let root = roots.get(id)
|
||||
if (!root) {
|
||||
root ??= createRoot(this.environment ?? null, id)
|
||||
roots.set(id, root)
|
||||
}
|
||||
|
||||
let result = await root.generate(src, (file) => this.addWatchFile(file), I)
|
||||
if (!result) {
|
||||
|
|
@ -174,13 +207,15 @@ function getExtension(id: string) {
|
|||
}
|
||||
|
||||
function isPotentialCssRootFile(id: string) {
|
||||
if (id.includes('/.vite/')) return
|
||||
if (id.includes('/.vite/')) return false
|
||||
|
||||
// Don't intercept special static asset resources
|
||||
if (SPECIAL_QUERY_RE.test(id)) return false
|
||||
if (COMMON_JS_PROXY_RE.test(id)) return false
|
||||
|
||||
let extension = getExtension(id)
|
||||
let isCssFile =
|
||||
(extension === 'css' || id.includes('&lang.css') || id.match(INLINE_STYLE_ID_RE)) &&
|
||||
// Don't intercept special static asset resources
|
||||
!SPECIAL_QUERY_RE.test(id) &&
|
||||
!COMMON_JS_PROXY_RE.test(id)
|
||||
let isCssFile = extension === 'css' || id.includes('&lang.css') || id.match(INLINE_STYLE_ID_RE)
|
||||
|
||||
return isCssFile
|
||||
}
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue