From bc6e4b85bf1dce84e2947f81cbb9881a77427de7 Mon Sep 17 00:00:00 2001 From: Andrey Viktorov Date: Wed, 18 Feb 2026 02:59:57 +0700 Subject: [PATCH] Fallback to `config.createResolver` for `client` and `ssr` environments in `@tailwindcss/vite` (#19679) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit ## Summary Sometimes even if Vite Envrionment API is available, some plugins are still override `config.createResolver` function to inject own aliases Since technically `config.createResolver` was only [properly deprecated](https://github.com/vitejs/vite/pull/20031) in Vite 7.0.0, it's still a valid(-ish) to do so, even if it wasn't ever officially supported Vite already handles this in its internal css resolvers, but not exposes the code to do so as part of public API, so I've copied and adapted it Fixes #19677 ## Test plan Tested by copying built package into my repro from the issue, also ran vite integration tests --------- Co-authored-by: Robin Malfait --- CHANGELOG.md | 1 + integrations/vite/astro.test.ts | 72 ++++++++++++++++++++++++- packages/@tailwindcss-vite/src/index.ts | 40 ++++++++++++-- 3 files changed, 109 insertions(+), 4 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 065700829..3feec1331 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -29,6 +29,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 - Allow multiples of `.25` in `aspect-*` fractions ([#19688](https://github.com/tailwindlabs/tailwindcss/pull/19688)) - Ensure changes to external files listed via `@source` trigger a full page reload when using `@tailwindcss/vite` ([#19670](https://github.com/tailwindlabs/tailwindcss/pull/19670)) - Improve performance Oxide scanner in bigger projects ([#19632](https://github.com/tailwindlabs/tailwindcss/pull/19632)) +- Ensure import aliases in Astro v5 work without crashing ([#19677](https://github.com/tailwindlabs/tailwindcss/issues/19677)) ### Deprecated diff --git a/integrations/vite/astro.test.ts b/integrations/vite/astro.test.ts index 43406624c..f828b5071 100644 --- a/integrations/vite/astro.test.ts +++ b/integrations/vite/astro.test.ts @@ -1,4 +1,4 @@ -import { candidate, fetchStyles, html, js, json, retryAssertion, test, ts } from '../utils' +import { candidate, css, fetchStyles, html, js, json, retryAssertion, test, ts } from '../utils' test( 'dev mode', @@ -129,3 +129,73 @@ test( await fs.expectFileToContain(files[0][0], [candidate`underline`, candidate`overline`]) }, ) + +// https://github.com/tailwindlabs/tailwindcss/issues/19677 +test( + 'import aliases should work in + + +

Astro

+ + + `, + 'src/styles/global.css': css`@import 'tailwindcss';`, + }, + }, + async ({ fs, exec, expect }) => { + await exec('pnpm astro build') + + let files = await fs.glob('dist/**/*.css') + expect(files).toHaveLength(1) + + await fs.expectFileToContain(files[0][0], [candidate`underline`]) + }, +) diff --git a/packages/@tailwindcss-vite/src/index.ts b/packages/@tailwindcss-vite/src/index.ts index d7d46c772..3ab7c3a0f 100644 --- a/packages/@tailwindcss-vite/src/index.ts +++ b/packages/@tailwindcss-vite/src/index.ts @@ -12,7 +12,13 @@ import { Scanner } from '@tailwindcss/oxide' import { realpathSync } from 'node:fs' import fs from 'node:fs/promises' import path from 'node:path' -import type { Environment, Plugin, ResolvedConfig, ViteDevServer } from 'vite' +import type { + Environment, + InternalResolveOptions, + Plugin, + ResolvedConfig, + ViteDevServer, +} from 'vite' import * as vite from 'vite' const DEBUG = env.DEBUG @@ -59,8 +65,36 @@ export default function tailwindcss(opts: PluginOptions = {}): Plugin[] { customCssResolver = (id: string, base: string) => cssResolver(id, base, true, isSSR) customJsResolver = (id: string, base: string) => jsResolver(id, base, true, isSSR) } else { + type ResolveIdFn = ( + environment: Environment, + id: string, + importer?: string, + aliasOnly?: boolean, + ) => Promise + + // There are cases where Environment API is available, + // but `createResolver` is still overriden (for example astro v5) + // + // Copied as-is from vite, because this function is not a part of public API + // + // TODO: Remove this function and pre-environment code when Vite < 7 is no longer supported + function createBackCompatIdResolver( + config: ResolvedConfig, + options?: Partial, + ): ResolveIdFn { + const compatResolve = config.createResolver(options) + let resolve: ResolveIdFn + return async (environment, id, importer, aliasOnly) => { + if (environment.name === 'client' || environment.name === 'ssr') { + return compatResolve(id, importer, aliasOnly, environment.name === 'ssr') + } + resolve ??= vite.createIdResolver(config, options) + return resolve(environment, id, importer, aliasOnly) + } + } + // Newer Vite versions - let cssResolver = vite.createIdResolver(env.config, { + let cssResolver = createBackCompatIdResolver(env.config, { ...env.config.resolve, extensions: ['.css'], mainFields: ['style'], @@ -69,7 +103,7 @@ export default function tailwindcss(opts: PluginOptions = {}): Plugin[] { preferRelative: true, }) - let jsResolver = vite.createIdResolver(env.config, env.config.resolve) + 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)