Skip to content

Commit d59f1b3

Browse files
Vite: Fix issues when loading files via static asset queries (#14716)
Fixes: #14558 This PR fixes an issue where our Vite plugin would crash when trying to load stylesheets via certain static asset query parameters: ```ts import raw from './style.css?raw' import url from './style.css?url' ``` The proper behavior for our extension is to _not touch these file at all_. The `?raw` identifier should never transform anything and the `?url` one will emit a module which points to the asset URL. However, if that URL is loaded as a stylesheet, another transform hook is called and the file is properly transformed. I verified this in the Vite setup and have added an integration test ensuring these two features work as expected. I've also greatly reduced the complexity of the Vite playground to make it easier to set up examples like this in the future.
1 parent 557ed8c commit d59f1b3

File tree

15 files changed

+75
-88
lines changed

15 files changed

+75
-88
lines changed

CHANGELOG.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
1818
- Ensure color opacity modifiers work with OKLCH colors ([#14741](https://github.com/tailwindlabs/tailwindcss/pull/14741))
1919
- Ensure changes to the input CSS file result in a full rebuild ([#14744](https://github.com/tailwindlabs/tailwindcss/pull/14744))
2020
- Add `postcss` as a dependency of `@tailwindcss/postcss` ([#14750](https://github.com/tailwindlabs/tailwindcss/pull/14750))
21+
- Ensure loading stylesheets via the `?raw` and `?url` static asset query works when using the Vite plugin ([#14716](https://github.com/tailwindlabs/tailwindcss/pull/14716))
2122
- _Upgrade (experimental)_: Migrate `flex-grow` to `grow` and `flex-shrink` to `shrink` ([#14721](https://github.com/tailwindlabs/tailwindcss/pull/14721))
2223
- _Upgrade (experimental)_: Minify arbitrary values when printing candidates ([#14720](https://github.com/tailwindlabs/tailwindcss/pull/14720))
2324
- _Upgrade (experimental)_: Ensure legacy theme values ending in `1` (like `theme(spacing.1)`) are correctly migrated to custom properties ([#14724](https://github.com/tailwindlabs/tailwindcss/pull/14724))

integrations/vite/index.test.ts

Lines changed: 61 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -504,3 +504,64 @@ test(
504504
})
505505
},
506506
)
507+
508+
test(
509+
`does not interfere with ?raw and ?url static asset handling`,
510+
{
511+
fs: {
512+
'package.json': json`
513+
{
514+
"type": "module",
515+
"dependencies": {
516+
"@tailwindcss/vite": "workspace:^",
517+
"tailwindcss": "workspace:^"
518+
},
519+
"devDependencies": {
520+
"vite": "^5.3.5"
521+
}
522+
}
523+
`,
524+
'vite.config.ts': ts`
525+
import tailwindcss from '@tailwindcss/vite'
526+
import { defineConfig } from 'vite'
527+
528+
export default defineConfig({
529+
build: { cssMinify: false },
530+
plugins: [tailwindcss()],
531+
})
532+
`,
533+
'index.html': html`
534+
<head>
535+
<script type="module" src="./src/index.js"></script>
536+
</head>
537+
`,
538+
'src/index.js': js`
539+
import url from './index.css?url'
540+
import raw from './index.css?raw'
541+
`,
542+
'src/index.css': css`@import 'tailwindcss';`,
543+
},
544+
},
545+
async ({ spawn, getFreePort }) => {
546+
let port = await getFreePort()
547+
await spawn(`pnpm vite dev --port ${port}`)
548+
549+
await retryAssertion(async () => {
550+
// We have to load the .js file first so that the static assets are
551+
// resolved
552+
await fetch(`http://localhost:${port}/src/index.js`).then((r) => r.text())
553+
554+
let [raw, url] = await Promise.all([
555+
fetch(`http://localhost:${port}/src/index.css?raw`).then((r) => r.text()),
556+
fetch(`http://localhost:${port}/src/index.css?url`).then((r) => r.text()),
557+
])
558+
559+
expect(firstLine(raw)).toBe(`export default "@import 'tailwindcss';"`)
560+
expect(firstLine(url)).toBe(`export default "/src/index.css"`)
561+
})
562+
},
563+
)
564+
565+
function firstLine(str: string) {
566+
return str.split('\n')[0]
567+
}

packages/@tailwindcss-vite/src/index.ts

Lines changed: 8 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,8 @@ import { Features, transform } from 'lightningcss'
55
import path from 'path'
66
import type { Plugin, ResolvedConfig, Rollup, Update, ViteDevServer } from 'vite'
77

8+
const SPECIAL_QUERY_RE = /[?&](raw|url)\b/
9+
810
export default function tailwindcss(): Plugin[] {
911
let servers: ViteDevServer[] = []
1012
let config: ResolvedConfig | null = null
@@ -261,9 +263,12 @@ function getExtension(id: string) {
261263
function isPotentialCssRootFile(id: string) {
262264
let extension = getExtension(id)
263265
let isCssFile =
264-
extension === 'css' ||
265-
(extension === 'vue' && id.includes('&lang.css')) ||
266-
(extension === 'astro' && id.includes('&lang.css'))
266+
(extension === 'css' ||
267+
(extension === 'vue' && id.includes('&lang.css')) ||
268+
(extension === 'astro' && id.includes('&lang.css'))) &&
269+
// Don't intercept special static asset resources
270+
!SPECIAL_QUERY_RE.test(id)
271+
267272
return isCssFile
268273
}
269274

playgrounds/vite/package.json

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,6 @@
1919
"@types/react": "^18.3.9",
2020
"@types/react-dom": "^18.3.1",
2121
"bun": "^1.1.29",
22-
"vite": "catalog:",
23-
"vite-plugin-handlebars": "^2.0.0"
22+
"vite": "catalog:"
2423
}
2524
}

playgrounds/vite/src/animate.js

Lines changed: 0 additions & 1 deletion
This file was deleted.

playgrounds/vite/src/app.tsx

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,7 @@
1-
import { Foo } from './foo'
2-
31
export function App() {
42
return (
53
<div className="m-3 p-3 border">
64
<h1 className="text-blue-500">Hello World</h1>
7-
<button className="hocus:underline">Click me</button>
8-
<Foo />
95
</div>
106
)
117
}

playgrounds/vite/src/bar.tsx

Lines changed: 0 additions & 7 deletions
This file was deleted.

playgrounds/vite/src/foo.tsx

Lines changed: 0 additions & 10 deletions
This file was deleted.

playgrounds/vite/src/forms.js

Lines changed: 0 additions & 1 deletion
This file was deleted.
Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,2 +1 @@
11
@import 'tailwindcss';
2-
@plugin "./plugin.js";

0 commit comments

Comments
 (0)