From 93b922dcb6e40ef78d893a002ee35b93521caa34 Mon Sep 17 00:00:00 2001 From: Alem Tuzlak Date: Mon, 2 Dec 2024 23:08:13 +0100 Subject: [PATCH] Fix resolution of imported CSS files in Vite SSR builds (#15279) Fixes #15237 --------- Co-authored-by: Jordan Pittman --- CHANGELOG.md | 1 + integrations/vite/ssr.test.ts | 139 ++++++++++++++++++++++++ packages/@tailwindcss-vite/src/index.ts | 2 +- 3 files changed, 141 insertions(+), 1 deletion(-) create mode 100644 integrations/vite/ssr.test.ts diff --git a/CHANGELOG.md b/CHANGELOG.md index 8b1c70ddf..1d460d1ac 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -11,6 +11,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 - Ensure absolute `url()`s inside imported CSS files are not rebased when using `@tailwindcss/vite` - Fix issues with dev servers using Svelte 5 with the Vite plugin ([#15274](https://github.com/tailwindlabs/tailwindcss/issues/15274)) +- Fix resolution of imported CSS files in Vite SSR builds ([#15279](https://github.com/tailwindlabs/tailwindcss/issues/15279)) ### Added diff --git a/integrations/vite/ssr.test.ts b/integrations/vite/ssr.test.ts new file mode 100644 index 000000000..e66970f88 --- /dev/null +++ b/integrations/vite/ssr.test.ts @@ -0,0 +1,139 @@ +import { expect } from 'vitest' +import { candidate, css, html, json, test, ts } from '../utils' + +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()], + ssr: { resolve: { conditions: [] } }, + }) + `, + 'index.html': html` + +
+ + + `, + 'src/index.css': css`@import 'tailwindcss';`, + 'src/index.ts': ts` + import './index.css' + + document.querySelector('#app').innerHTML = \` +
Hello, world!
+ \` + `, + 'server.ts': ts` + import css from './src/index.css?url' + + document.querySelector('#app').innerHTML = \` + +
Hello, world!
+ \` + `, + }, + }, + async ({ fs, exec }) => { + 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`, + ]) + }, +) + +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()], + ssr: { resolve: { conditions: [] } }, + }) + `, + 'index.html': html` + +
+ + + `, + 'src/index.css': css`@import 'tailwindcss';`, + 'src/index.ts': ts` + import './index.css' + + document.querySelector('#app').innerHTML = \` +
Hello, world!
+ \` + `, + 'server.ts': ts` + import css from './src/index.css?url' + + document.querySelector('#app').innerHTML = \` + +
Hello, world!
+ \` + `, + }, + }, + async ({ fs, exec }) => { + 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`, + ]) + }, +) diff --git a/packages/@tailwindcss-vite/src/index.ts b/packages/@tailwindcss-vite/src/index.ts index 9c92699fa..a6ba5db3f 100644 --- a/packages/@tailwindcss-vite/src/index.ts +++ b/packages/@tailwindcss-vite/src/index.ts @@ -44,7 +44,7 @@ export default function tailwindcss(): Plugin[] { preferRelative: true, }) function customCssResolver(id: string, base: string) { - return cssResolver(id, base, false, isSSR) + return cssResolver(id, base, true, isSSR) } let jsResolver = config!.createResolver(config!.resolve)