fix(vite): resolve tsconfig paths in CSS and JS resolvers (#19803)
Change `aliasOnly` from `true` to `false` when calling Vite's resolver so that the full resolution pipeline runs, including the oxc resolver responsible for tsconfig path resolution. When `aliasOnly` was `true`, only the @rollup/plugin-alias plugin ran, which meant `resolve.tsconfigPaths: true` had no effect on CSS `@import` or JS `@plugin` resolution in `@tailwindcss/vite`. Closes #19802. --------- Co-authored-by: Robin Malfait <malfait.robin@gmail.com>
This commit is contained in:
parent
bd30a716e6
commit
5cb1efdf41
3 changed files with 177 additions and 5 deletions
|
|
@ -27,6 +27,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
|
|||
- Add support for Vite 8 in `@tailwindcss/vite` ([#19790](https://github.com/tailwindlabs/tailwindcss/pull/19790))
|
||||
- Improve canonicalization for bare values exceeding default spacing scale suggestions (e.g. `w-1234 h-1234` → `size-1234`) ([#19809](https://github.com/tailwindlabs/tailwindcss/pull/19809))
|
||||
- Fix canonicalization resulting in empty list (e.g. `w-5 h-5 size-5` → `''` instead of `size-5`) ([#19812](https://github.com/tailwindlabs/tailwindcss/pull/19812))
|
||||
- Resolve tsconfig paths to allow for `@import '@/path/to/file';` when using `@tailwindcss/vite` ([#19803](https://github.com/tailwindlabs/tailwindcss/pull/19803))
|
||||
|
||||
## [4.2.1] - 2026-02-23
|
||||
|
||||
|
|
|
|||
|
|
@ -1,5 +1,168 @@
|
|||
import { describe } from 'vitest'
|
||||
import { candidate, css, fetchStyles, html, js, retryAssertion, test, ts, txt } from '../utils'
|
||||
import {
|
||||
candidate,
|
||||
css,
|
||||
fetchStyles,
|
||||
html,
|
||||
js,
|
||||
json,
|
||||
retryAssertion,
|
||||
test,
|
||||
ts,
|
||||
txt,
|
||||
} from '../utils'
|
||||
|
||||
test(
|
||||
'resolves tsconfig paths in production build',
|
||||
{
|
||||
fs: {
|
||||
'package.json': json`
|
||||
{
|
||||
"type": "module",
|
||||
"dependencies": {
|
||||
"@tailwindcss/vite": "workspace:^",
|
||||
"tailwindcss": "workspace:^"
|
||||
},
|
||||
"devDependencies": {
|
||||
"vite": "^8"
|
||||
}
|
||||
}
|
||||
`,
|
||||
'tsconfig.json': json`
|
||||
{
|
||||
"compilerOptions": {
|
||||
"baseUrl": ".",
|
||||
"paths": {
|
||||
"@/*": ["./src/*"]
|
||||
}
|
||||
}
|
||||
}
|
||||
`,
|
||||
'vite.config.ts': ts`
|
||||
import tailwindcss from '@tailwindcss/vite'
|
||||
import { defineConfig } from 'vite'
|
||||
|
||||
export default defineConfig({
|
||||
build: { cssMinify: false },
|
||||
plugins: [tailwindcss()],
|
||||
resolve: {
|
||||
tsconfigPaths: true,
|
||||
},
|
||||
})
|
||||
`,
|
||||
'index.html': html`
|
||||
<head>
|
||||
<link rel="stylesheet" href="./src/index.css" />
|
||||
</head>
|
||||
<body>
|
||||
<div class="underline custom-underline">Hello, world!</div>
|
||||
</body>
|
||||
`,
|
||||
'src/index.css': css`
|
||||
@import '@/styles/base.css';
|
||||
@plugin '@/plugin.js';
|
||||
`,
|
||||
'src/styles/base.css': css`
|
||||
@reference 'tailwindcss/theme';
|
||||
@import 'tailwindcss/utilities';
|
||||
`,
|
||||
'src/plugin.js': js`
|
||||
export default function ({ addUtilities }) {
|
||||
addUtilities({ '.custom-underline': { 'border-bottom': '1px solid green' } })
|
||||
}
|
||||
`,
|
||||
},
|
||||
},
|
||||
async ({ fs, exec, expect }) => {
|
||||
await exec('pnpm vite build')
|
||||
|
||||
let files = await fs.glob('dist/**/*.css')
|
||||
expect(files).toHaveLength(1)
|
||||
let [filename] = files[0]
|
||||
|
||||
await fs.expectFileToContain(filename, [candidate`underline`, candidate`custom-underline`])
|
||||
},
|
||||
)
|
||||
|
||||
test(
|
||||
'resolves tsconfig paths in dev mode',
|
||||
{
|
||||
fs: {
|
||||
'package.json': json`
|
||||
{
|
||||
"type": "module",
|
||||
"dependencies": {
|
||||
"@tailwindcss/vite": "workspace:^",
|
||||
"tailwindcss": "workspace:^"
|
||||
},
|
||||
"devDependencies": {
|
||||
"vite": "^8"
|
||||
}
|
||||
}
|
||||
`,
|
||||
'tsconfig.json': json`
|
||||
{
|
||||
"compilerOptions": {
|
||||
"baseUrl": ".",
|
||||
"paths": {
|
||||
"@/*": ["./src/*"]
|
||||
}
|
||||
}
|
||||
}
|
||||
`,
|
||||
'vite.config.ts': ts`
|
||||
import tailwindcss from '@tailwindcss/vite'
|
||||
import { defineConfig } from 'vite'
|
||||
|
||||
export default defineConfig({
|
||||
build: { cssMinify: false },
|
||||
plugins: [tailwindcss()],
|
||||
resolve: {
|
||||
tsconfigPaths: true,
|
||||
},
|
||||
})
|
||||
`,
|
||||
'index.html': html`
|
||||
<head>
|
||||
<link rel="stylesheet" href="./src/index.css" />
|
||||
</head>
|
||||
<body>
|
||||
<div class="underline custom-underline">Hello, world!</div>
|
||||
</body>
|
||||
`,
|
||||
'src/index.css': css`
|
||||
@import '@/styles/base.css';
|
||||
@plugin '@/plugin.js';
|
||||
`,
|
||||
'src/styles/base.css': css`
|
||||
@reference 'tailwindcss/theme';
|
||||
@import 'tailwindcss/utilities';
|
||||
`,
|
||||
'src/plugin.js': js`
|
||||
export default function ({ addUtilities }) {
|
||||
addUtilities({ '.custom-underline': { 'border-bottom': '1px solid green' } })
|
||||
}
|
||||
`,
|
||||
},
|
||||
},
|
||||
async ({ spawn, expect }) => {
|
||||
let process = await spawn('pnpm vite dev')
|
||||
await process.onStdout((m) => m.includes('ready in'))
|
||||
|
||||
let url = ''
|
||||
await process.onStdout((m) => {
|
||||
let match = /Local:\s*(http.*)\//.exec(m)
|
||||
if (match) url = match[1]
|
||||
return Boolean(url)
|
||||
})
|
||||
|
||||
await retryAssertion(async () => {
|
||||
let styles = await fetchStyles(url, '/index.html')
|
||||
expect(styles).toContain(candidate`underline`)
|
||||
expect(styles).toContain(candidate`custom-underline`)
|
||||
})
|
||||
},
|
||||
)
|
||||
|
||||
describe.each(['postcss', 'lightningcss'])('%s', (transformer) => {
|
||||
test(
|
||||
|
|
|
|||
|
|
@ -62,8 +62,12 @@ export default function tailwindcss(opts: PluginOptions = {}): Plugin[] {
|
|||
|
||||
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)
|
||||
customCssResolver = async (id: string, base: string) => {
|
||||
let resolved = await cssResolver(id, base, false, isSSR)
|
||||
if (resolved && !resolved.endsWith('.css')) return undefined
|
||||
return resolved
|
||||
}
|
||||
customJsResolver = (id: string, base: string) => jsResolver(id, base, false, isSSR)
|
||||
} else {
|
||||
type ResolveIdFn = (
|
||||
environment: Environment,
|
||||
|
|
@ -105,8 +109,12 @@ export default function tailwindcss(opts: PluginOptions = {}): Plugin[] {
|
|||
|
||||
let jsResolver = createBackCompatIdResolver(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)
|
||||
customCssResolver = async (id: string, base: string) => {
|
||||
let resolved = await cssResolver(env, id, base, false)
|
||||
if (resolved && !resolved.endsWith('.css')) return undefined
|
||||
return resolved
|
||||
}
|
||||
customJsResolver = (id: string, base: string) => jsResolver(env, id, base, false)
|
||||
}
|
||||
|
||||
return new Root(
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue