diff --git a/CHANGELOG.md b/CHANGELOG.md index 0657008292ef..3feec133112d 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 43406624c316..f828b5071b60 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 d7d46c77222a..3ab7c3a0f2f8 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)