tailwindcss
tailwindcss copied to clipboard
[v4] importing tailwindcss/utilities breaks hmr
Im using:
- tailwind v4.0.0-alpha.17 ( @tailwindcss/postcss )
- nuxt v3.12.3
- sass v1.77.8
The following code works perfectly:
@import "../theme/_index.scss" layer(theme);
@import "tailwindcss/preflight" layer(base);
@import "../base/_index.scss" layer(base);
@import "../plugins/postcss/_index.scss" layer(base);
@import "../plugins/formkit/_index.scss" layer(components);
But whenever i try and import the utilities from tailwind like so:
@import "../theme/_index.scss" layer(theme);
@import "tailwindcss/preflight" layer(base);
@import "../base/_index.scss" layer(base);
@import "../plugins/postcss/_index.scss" layer(base);
@import "../plugins/formkit/_index.scss" layer(components);
@import "tailwindcss/utilities" layer(utilities);
The HMR stops working, it does still say that the HMR got updated but it wont actually apply the changes to the front-end. Whenever i save my main scss file, the changes actually get applied.
Hello,
Is this issue still active? I would like to work on this.
Best Regards.
Yes, this is still an issue
Please read the issue before commenting, your talking about handling this issue for tailwind v3, im encountering this issue with tailwind v4.
Thus making your comment useless
Am experiencing this as well in alpha.20. Removing @import "tailwindcss/utilities" layer(utilities); from my root stylesheet fixes the problem but, of course, leaves me without any utilities.
Console logs:
[Error] TypeError: Importing a module script failed.
warnFailedUpdate (client:174)
(anonymous function) (client:213)
[Error] [hmr] Failed to reload /app/root.css. This could be due to syntax errors or importing non-existent modules. (see errors above)
warnFailedUpdate (client:176)
(anonymous function) (client:213)
Hey @Matheun and @boylett! Does either of you have a minimal repro for this issue? We're currently working on rebuilding our Vite extension but haven't encountered this particular problem.
Update: We noticed that there are some issues when using Tailwind CSS v4 in a Nuxt project. Are you both using Nuxt?
I'm using Remix. Frustratingly I can't seem to reproduce this on a fresh install - however, this does seem to be a widespread issue relegated only to Safari on macOS/iOS. Doesn't happen at all on Chrome or Firefox.
The same problem occurs when working with SvelteKit as well as in many other contexts, many of them involving Safari. Note that doing a hard-refresh (⌥+⌘+E → ⌘R) does indeed prevent the error until you next save a change.
Doesn't necessarily seem to be a Tailwind-specific issue, but possibly something to do with the way Safari caches modules constructed with frameworks like vite?
I opened Safari and Chrome side-by-side and went along developing as normal, and Chrome updated as expected with no errors at all while Safari failed miserably.
tl;dr – Likely a Safari caching issue.
Edit: Occasionally I am noticing that HMR mixes up the order of Preflight and Base/Utilities, causing preflight's reset to override all other utilities. This is fixed after a manual refresh. Should I make a separate issue for this?
Thanks for the writeup @boylett. Agree that these issues you linked don't seem to be related to Tailwind.
The latest alpha release (v4.0.0-alpha.23) contains a lot of changes in regards to how the Vite plugin works. It would be great if both of you can try to upgrade and let us know if the issue persists? I wasn't able to repro this myself so any information on how to do that would be really helpful here.
@philipp-spiess I manage to get it working now using the vite plugin and .css files. But i kindof really need to use scss files, for some reason they dont load correctly? i have no clue why or how.
When inspecting the style editor in the inspector, every variable is defined as expected and the layers are correct. But when i add the class pt-4 to an element, nothing happens. The default variables are also not defined when inspecting the root html even tho they are in the style editor.
Also, when using
nuxt.config.ts
import tailwindcss from "@tailwindcss/vite";
// https://nuxt.com/docs/api/configuration/nuxt-config
export default defineNuxtConfig({
devtools: { enabled: true },
css: ["./assets/scss/vendors/tailwind.scss"],
vite: {
plugins: [
tailwindcss(),
],
},
})
./assets/scss/vendors/tailwind.scss
@import "tailwindcss";
@philipp-spiess
To recap:
Case 1 - tailwindcss/vite
see: https://github.com/Matheun/tailwind-v4-case-1
HMR works correctly when using regular .css files and <style> tags.
This hover does result in me being forced to use .css files and regular <style> tags in my .vue files. So i won't be able to use <style scoped lang="scss"> or <style lang="scss"> tags in my .vue files. Or i won't be able to use @apply in .vue files.
Resulting in this setup being kindof useless when you need to use scss
// nuxt.config.ts
import tailwindcss from "@tailwindcss/vite";
export default defineNuxtConfig({
css: [
"./assets/style/tailwind.css",
"./assets/style/main.scss"
],
vite: {
plugins: [
tailwindcss(),
],
},
})
// app.vue
<template>
<div>
<p class="pt-4">Test paragraph</p>
</div>
</template>
<style>
@import 'tailwindcss/utilities';
@import 'tailwindcss/theme' theme(reference);
/* ^ having to declade this every time makes the project very prone to errors */
p {
@apply pl-4;
}
</style>
Case 2 - tailwindcss/vite
see: https://github.com/Matheun/tailwind-v4-case-2
Now vite doesnt load the scss files correctly - meaning the tailwind does get loaded but the dom somehow can find them/ apply the css variables
// nuxt.config.ts
import tailwindcss from "@tailwindcss/vite";
export default defineNuxtConfig({
css: ["./assets/style/tailwind.scss"],
vite: {
plugins: [
tailwindcss(),
],
},
})
Case 3 - tailwindcss/postcss
see: https://github.com/Matheun/tailwind-v4-case-3
Now i'm able to use scss and all the good stuff it provides, but @apply doesnt work in .vue files
// nuxt.config.ts
export default defineNuxtConfig({
css: ["./assets/scss/vendors/tailwind.scss"],
postcss: {
plugins: {
"@tailwindcss/postcss": {},
},
},
})
@Matheun Sorry for only getting back to you today, but yeah as you mentioned in a separat issue, this is related to the Vite plugin not supporting other pre-processors at the moment: https://github.com/tailwindlabs/tailwindcss/issues/14376
Regarding case 3: It seems unexpected that .vue files do not use the whole Post CSS pipeline when parsing style blocks. Have you tried using <style lang="postcss"> tags?
@philipp-spiess Just tried it, now i get the following error:
[postcss] Cannot apply unknown utility class: pl-4
code:
<template>
<div>
<p class="pt-4">Test paragraph</p>
</div>
</template>
<style lang="postcss">
p {
@apply pl-4;
}
</style>
The following however does work, but is there a way around importing tailwind in every style stag? since we often have 75+ components and its a hassle debugging if we accidentally import tailwind the wrong way
<template>
<div>
<p class="pt-4">Test paragraph</p>
</div>
</template>
<style lang="postcss">
@import 'tailwindcss/utilities';
@import 'tailwindcss/theme' theme(reference);
p {
@apply pl-4;
}
</style>
Also works:
<template>
<div>
<p class="pt-4">Test paragraph</p>
</div>
</template>
<style lang="scss">
@import 'tailwindcss/utilities';
@import 'tailwindcss/theme' theme(reference);
p {
@apply pl-4;
}
</style>
Ah, yeah, the issue here is that the pl utility requires the --spacing @theme to be defined, otherwise we don't know what 4 should refer to, in this case. It's enough to add only the @import 'tailwindcss/theme' theme(reference); import in this case.
Right now it's required to add that import unfortunately, since the CSS file is now our source of truth regarding the config. it's no longer one config for the whole project. You can import your own theme.css file here instead via theme(reference) too, though, if you want to adjust the theme.
We will have to think how we can make this easier, though. I'll get back to you about this.
Allright, can see why thats the case.
And if i want to import a custom theme, i would do it like so?
@import 'tailwindcss/theme' theme(url.scss);
Wouldn't the additionalData option in postcss be a possible fix for now? i can remember that i used this back in the day to load my sass variables globally
And where can i read up on some more info about these options? i kept going through the release notes, but its kinda hard to get a good overview.
Also, where do you recommend i start/ what path/ which roadmap do i follow in doing my research into the source code of tailwind, since i want to start contributing and get a deeper understanding as to how the entire codebase works?
And if i want to import a custom theme, i would do it like so?
That would be:
@import './src/tailwind-theme.css' theme(reference);
The theme(reference) makes it so that this import will not emit CSS variables for the theme, since you usually want those only once in your globals.
Wouldn't the
additionalDataoption in postcss be a possible fix for now? i can remember that i used this back in the day to load my sass variables globally
Ah, yep, maybe this works (although for relative imports I’m not sure it will use the right base path?). It does seem to only be a SCSS option though, so it won't work for all postcss setups.
Also, where do you recommend i start/ what path/ which roadmap do i follow in doing my research into the source code of tailwind, since i want to start contributing and get a deeper understanding as to how the entire codebase works?
Yeah most of that info is only in PR descriptions right now, we haven't gotten around to writing docs yet, sorry! 😞
I would like to setup some nuxt and vue examples so people have a base to get started, would this be of value/ usefull? i could maybe do a pull request into the playgrounds folder? or should i create a repo on my own github and get it linked somewhere?
Also, i would be down to get some documentation going? i'm currently diving into every v4 release and code. Where should i then put the base of the doc?
@philipp-spiess, @boylett Quick update on my HMR issue, i found the problem:
I imported my theme index file like so (which works perfectly fine):
@import "../theme/_index.scss" layer(theme);
But in my _index.scss i imported my files like so:
@import "_spacing";
Now, this doesnt get updated which i realize right now, makes sense. What makes the HMR work is the following:
@import "./_spacing.scss" layer(theme);
I would like to setup some nuxt and vue examples so people have a base to get started, would this be of value/ usefull? i could maybe do a pull request into the playgrounds folder? or should i create a repo on my own github and get it linked somewhere?
I think that would help but we don't want to add too many playgrounds in the repo since these quickly go outdated. There are some integration tests for both vue and nuxt though that we already maintain, which might be a good thing to look into:
- https://github.com/tailwindlabs/tailwindcss/blob/next/integrations/vite/nuxt.test.ts
- https://github.com/tailwindlabs/tailwindcss/blob/next/integrations/vite/vue.test.ts
I don't think we want to add one for the SCSS setup via postcss just yet, mostly because we're still thinking about wether we will make this setup easier. However one general test inside the postcss set of tests where we have the postcss processor first and then tailwind and ensure features work would actually be really helpful. So something like this one:
- https://github.com/tailwindlabs/tailwindcss/blob/next/integrations/postcss/index.test.ts#L4-L80
Also, i would be down to get some documentation going? i'm currently diving into every v4 release and code. Where should i then put the base of the doc?
Yea so the unfortunate answer is that we don't have a place for this yet. We just talked about docs in our sync yesterdan and it's likely going to be a fork off the v3 docs but with some larger changes planned. I don't think we know exactly what we want there yet so I don't think we can guarantee that a contribution there will be merged. I think timeline wise it'll be a few more weeks before we fully start this I'm afraid.
Quick update on my HMR issue, i found the problem
I’m not sure I quite understand the issue yet. Maybe it helps if you share a repro here with the contents of your CSS file. Thank you!
I'll setup some repo for you to have a look at.
Side question, is there any way to get @tailwindcss/typography working with postcss or do i need vite for that
@Matheun The plugin support should be independent of which client is used, so @plugin '@tailwindcss/typography' should work regardless of you using Vite or Postcss!
@Matheun The plugin support should be independent of which client is used, so
@plugin '@tailwindcss/typography'should work regardless of you using Vite or Postcss!
Aaaaaah, yea i was doing it the vite way with a js file, didnt know is was this simple
@philipp-spiess Updated the repo to show which import breaks the HMR and which works with HMR
https://github.com/Matheun/tailwind-v4-case-3
@philipp-spiess ?
Also, When i use the following code, the HMR for that file will not work when i save the file instead of the main scss
@import "tailwindcss/preflight" layer(base);
@import "../../../components/button/button.scss";
This makes the HMR work
@import "tailwindcss/preflight" layer(base);
@import "../../../components/button/button.scss" layer(components);
@Matheun Hey! Thank you for reporting. There indeed was something wrong with CSS file dependencies not being watched. We have a PR to fix this here: https://github.com/tailwindlabs/tailwindcss/pull/14561
Hey!
This should be fixed by #14561, and will be available in the next alpha release.
@Matheun Hey! Responding here since you said you still have issues with HMR and this setup. I was looking into it a bit and what happens here seems really funny. I noticed in the logs of Vite that if you have the syntax without the layer() modifier, the SCSS extension is actually inlining the @import. When this happens, it doesn't tell Vite that it now has a new dependency so changes to the .scss files are never picked up. The custom layer() works because it will bypass the SCSS import rules leaving it to Tailwind to do the imports where we do properly track these.
A workaround for you is to not rely on the SCSS extension built-into Nuxt but instead put postcss-import into the stack manually. This will resolve imports correctly.
Our official recommendation though is to not use SCSS at all if you use Tailwind CSS 😄 Curious what kind of features you are missing?