tailwindcss icon indicating copy to clipboard operation
tailwindcss copied to clipboard

[v4] Vite plugin breaks when setting `css.transformer` to `"lightningcss"`

Open aaronadamsCA opened this issue 1 year ago • 12 comments

What version of Tailwind CSS are you using?

4.0.0-alpha.19

What build tool (or framework if it abstracts the build tool) are you using?

Vite 5.4.0

What version of Node.js are you using?

20.16.0

What browser are you using?

N/A

What operating system are you using?

Ubuntu 22.04

Reproduction URL

Let me know if you need this and how you'd like it. It works fine on Tailwind Play but fails in Vite.

Describe your issue

With a Vite config specifies "lightningcss" as the CSS transformer:

import tailwindcss from "@tailwindcss/vite";
import react from "@vitejs/plugin-react";
import { defineConfig } from "vite";

export default defineConfig({
  css: {
    transformer: "lightningcss",
  },
  plugins: [react(), tailwindcss()],
});

The behaviour of the Vite plugin is undefined and buggy.

It crashes when using @apply with class names containing characters * or /:

@import "tailwindcss";

@utility foo {
  @apply text-3xl/tight;
}
12:44:49 PM [vite] Pre-transform error: Cannot apply unknown utility class: /
12:44:49 PM [vite] Internal server error: Cannot apply unknown utility class: /
  Plugin: @tailwindcss/vite:generate:serve
  File: /workspace/packages/ui/src/tailwind.css
      at onInvalidCandidate (file:///workspace/node_modules/.pnpm/[email protected]/node_modules/tailwindcss/dist/lib.mjs:6:109810)
...

It pollutes the console with warnings:

Error running vite:css on Tailwind CSS output. Skipping.
Error running vite:css on Tailwind CSS output. Skipping.
Error running vite:css on Tailwind CSS output. Skipping.

And it seems to ignore @layer base classes.

You can work around the problem by removing the offending part of the Vite config.

aaronadamsCA avatar Aug 16 '24 12:08 aaronadamsCA

Heya! I tried to reproduce this but both vite dev and vite build seems to work for me if I add this @utility rule:

Screenshot 2024-08-16 at 15 05 42

Do you mind sharing your Vite config? Maybe there's another preprocessor that rewrites the @apply rule.

philipp-spiess avatar Aug 16 '24 13:08 philipp-spiess

Thanks @philipp-spiess, that narrows down the problem. It's because I was configuring "lightningcss" as my transformer:

import tailwindcss from "@tailwindcss/vite";
import react from "@vitejs/plugin-react";
import { defineConfig } from "vite";

export default defineConfig({
  css: {
    transformer: "lightningcss",
  },
  plugins: [react(), tailwindcss()],
});

If I remove it, everything works as expected! No more mystery problems.

This was also breaking a few other features, like using @layer base to set global styles, and the console was littered with these warnings:

Error running vite:css on Tailwind CSS output. Skipping.
Error running vite:css on Tailwind CSS output. Skipping.
Error running vite:css on Tailwind CSS output. Skipping.
Error running vite:css on Tailwind CSS output. Skipping.

All of this is resolved by removing that (redundant?) part of the config.

I've updated the original bug report. Hopefully you can reproduce this and then decide how to fix it, even if it's just erroring out for now, since "completely broken with a clear error message" is a lot better than "mysteriously half-broken".

aaronadamsCA avatar Aug 16 '24 13:08 aaronadamsCA

@aaronadamsCA Thank you so much! Yeah, this doesn't work right now 😞 We currently rely on the default postcss transformer for two reasons:

  1. It won't rewrite CSS rules like the @apply text-3xl/tight example you shared above.
  2. We rely on postcss for @import resolution and we're hooking into it by making sure relative imports (e.g. @plugin "./src/foo.ts") are rewritten correctly when imports are flattened.

I agree, though, that this is something that should work much better than it does right now. I'll brainstorm some ideas and will get back to you.

philipp-spiess avatar Aug 16 '24 14:08 philipp-spiess

@aaronadamsCA I'll continue to look into it but wanted to give a quick update since we just talked about this. Our current thinking is that tailwindcss currently already runs lightningcss for you so technically we're a superset of lightningcss and it would be better for us to either replace lightningcss in that case or hook into it more instead of having to run the same computation twice.

For the very short term, this unfortunately means that we won't have a good solution for this and the current alpha releases of @tailwindcss/vite won't be working with css.transformer set to lightningcss. I'll do some more digging next week though.

philipp-spiess avatar Aug 16 '24 15:08 philipp-spiess

Sounds good @philipp-spiess! Maybe you could just throw an error if the Vite config is invalid.

In the meantime, hopefully anybody who runs into any of the same problems can now find this issue report!

aaronadamsCA avatar Aug 16 '24 15:08 aaronadamsCA

Reopening this. It's fixed now for the majority of cases (so normal CSS files going through Vite) but plugins that use the preprocessCSS() pipeline (e.g. Astro when writing CSS inside <style> blocks) still have this issue as there is no way for us to hook into it before the processing (yet).

philipp-spiess avatar Sep 05 '24 09:09 philipp-spiess

Not sure if this should be noted here or in a new issue, but there is currently also an issue with setting css.transformer: 'lightningcss' when trying to use @custom-media

lightningcss can handle custom media queries, however Tailwind will throw an error Custom media query --XXXXX is not defined

corneliusio avatar Sep 05 '24 21:09 corneliusio

@corneliusio Which version of Tailwind CSS and the Tailwind Vite plugin are you on? I was just trying this out with the Tailwind CSS Alpha 23 releases and the following Vite config:

import tailwindcss from '@tailwindcss/vite'
import { defineConfig } from 'vite'

export default defineConfig({
  css: {
    transformer: 'lightningcss',
    lightningcss: {
      drafts: {
        customMedia: true,
      },
    },
  },
  plugins: [tailwindcss()],
})

And custom-media queries seem to be correctly transpiled.

philipp-spiess avatar Sep 06 '24 09:09 philipp-spiess

Ah, I'm glad you posted your config. I had missed that I needed to add drafts: { customMedia: true }. Once I added that it handled the custom media at rules as expected.

However, one thing I did discover after making this update that may or may not be an issue that can be addressed is that lightningcss will throw an error if you attempt to use the Tailwind theme() as part of the @custom-media definition.

@custom-media --screen-sm (width >= theme(--breakpoint-sm));
@custom-media --screen-md (width >= theme(--breakpoint-md));
@custom-media --screen-lg (width >= theme(--breakpoint-lg));
@custom-media --screen-xl (width >= theme(--breakpoint-xl));
@custom-media --screen-2xl (width >= theme(--breakpoint-2xl));
error during build:
[vite:css] Unexpected token Function("theme")

Edit: Using @tailwindcss/[email protected] and [email protected]

corneliusio avatar Sep 06 '24 15:09 corneliusio

Oh gotcha yes we will need to replace theme inside @custom-media. We don't do that yet. Let me add a PR :)

philipp-spiess avatar Sep 06 '24 15:09 philipp-spiess

@corneliusio Fixed in https://github.com/tailwindlabs/tailwindcss/pull/14358 :)

philipp-spiess avatar Sep 06 '24 17:09 philipp-spiess

🙌🏼 Fantastic! Now I just need Bun to get this odd edge case resolve. 🙃

corneliusio avatar Sep 06 '24 17:09 corneliusio

Going to close this one as the original issue was resolved. If anyone is still running into any issues related to the lightningcss pre processor, please let us know 🙂

philipp-spiess avatar Nov 19 '24 12:11 philipp-spiess