[ +] Check that there isn't already an issue that reports the same bug to avoid creating a duplicate.
[ +] Provide a description in this issue that describes the bug.
[+] Make sure this is a Vite issue and not a framework-specific issue. For example, if it's a Vue SFC related bug, it should likely be reported to https://github.com/vuejs/vue-next instead.
I'm seeing this issue as well, now that I've started to use storybook's new dynamic loading feature, my styles are broken in production stories. I've found that the css files are directly after the component in the network tab. So, in one example, I have a RadioButton component that imports Label (which has its own styles that I want to override), and then it imports some css module with the overrides. However, when building now, I see this:
Which puts the RadioButton styles higher in the cascade, and they are overwritten by the Label styles, which is backwards from what I want.
I finally found the culprit, and FOR a while I thought vite-plugin-pages and unplugin-vue-components were causing the problem, my bad. Glad to use them again.
My temporary solution is to load influenced page synchronously in router configuration.
I wonder whether Vite could maybe look for a __vite__injectStyle global hook to allow overriding the head.appendChild behavior.
With Webpack's style-loader one can specify a function/hook that will be called to place the style tag into the DOM (by default it will just append it to the head like Vite does).
Webpack Configuration
```
// webpack.config.js
{
test: /\.css$/,
use: [
{
loader: "style-loader",
options: {
injectType: "singletonStyleTag",
// this hook will be
insert: require.resolve("./tools/insertStyleTag.ts"),
},
},
{ loader: "css-loader" },
],
},
```
```
// insertStyleTag.ts
function insertStyleTag(element) {
element.dataset.styleLoader = "";
// Custom logic, could be more complicated. Here I added a marker
// to ensure `import ...` styles are added before `styled-component`
// styles.
document.head.insertBefore(
element,
document.head.querySelector("[data-styled]")
);
}
module.exports = insertStyleTag;
```
For those who (like me) had to ship and need a temporary workaround: Depending on your project, you may be able to use build.cssCodeSplit to extract a single css file which has the classes in the correct order.
It's almost finished now, but it's stuck at one point. Now the loading order should be as expected, but there is still a problem with the execution order
Why pre-load blue.module.css but execute first __vite__updateStyle is post-load red.module.css 🥲
However change the import order I do, it always load order by red -> green -> blue in dev mod.
This is a pretty big issue. The production build styling order also differs in order compared with the dev build making working with Vite a nightmare for me. Is there no workaround I can use in the meanwhile, it seems we are a long way from having this fixed?
I tried out the latest vite 2.9.14 version, and the situation seems to be improved (not as many style errors as before), but not quite yet resolved. I rebased https://github.com/vitejs/vite/pull/6301 onto the latest 2.9 branch as well, but its test is still failing.
I have this problem i add antd css in main file and other css in component but in dev ant last style and component css before antd.
Any have solution until fix it?
I import css end of all import in component before and now most first import all css and then import other component and solved this issue.
Component A
This is a really big issue which is now open for over one and a half year and more. Is there any progress? anything on the horizon?
We are using BEM. But with this problem parent component is not able to overwrite child css with a class which forces us to do parent > child selectors to get higher specifity which is against what we want to do with BEM. So we are a bit in trouble.
Any workaround on this, or idea when this will get solved?
@awacode21
not really a solution, but yet another workaround when you can't use (or it would be tricky) a parent selector -> .something:not(#\#) (or actually any other bogus value for :not(...)) to make a selector more specific easily.
(still struggling with this issue here since forever (already had it in webpack too))
As far as I know, it is not fixed and I don't think anyone is actively working on it. @poyoho made some heroic efforts on it, but was never able to handle all the edge cases. I wonder if code splitting is just fundamentally incompatible with css modules.
just to be certain, is the goal with https://github.com/vitejs/vite/pull/9278 is to make CSS insertion (in dev) follow what's already happening in production builds?
I don't think so. If anything, it is to make production builds behave similarly to dev.
The only way to preserve CSS ordering when bundling is to bundle all CSS into 1 CSS file per-page. Once you chunk common dependencies you are creating scenarios where ordering will be different on some pages. In Astro we are reconsidering whether to use the :where selector due to this. We might also come up with some other solutions. Just chiming in that the underlying problem is probably unsolvable.
I suppose it's also not possible to just bundle all CSS into a single bundle at build, because the order of the dynamic imports can't be known until runtime, right?
@IanVS For the entire site or a single page? For an entire site that's typically unwanted because the CSS file is going to be quite large and it will cause unwanted styles on some pages. If you mean on a single page you can do that, but it just means that shared CSS gets loaded once for each page, and people often don't like that.
In my case, I have a single-page-app (so I guess, both?). Right now, I'm not able to use dynamic imports / lazy loading because of the style problems. Even if I had to load the entire site's CSS up front, that would be a bit of an improvement if I could start to code-split the JS. But, I doubt that it's possible to bundle all the CSS in the correct order in that situation.
This issue is specifically about css modules. I suppose other styling approaches do not suffer this same problem, and perhaps I need to investigate other approaches if I want to use dynamic imports. Has anyone else here had any luck working around this problem by changing your approach to styling?
i mentioned above that i worked around it using cascade layers. it was a long time ago so i don't remember the exact details (i think it was with css modules).
when you define your layers upfront, the order of imports doesn't matter anymore so it will behave predictably even if vite messes it up.
Describe the bug
Vite injects css assets in wrong order with dynamic import and css modules.
Reproduction
Repo to reproduce
For example:
import styles from './button.module.css'
type ButtonProps = { children: string className?: string onClick?: () => void }
function Button({ children, className, onClick }: ButtonProps) { return <button className={classnames(styles.button, className)} onClick={onClick}>{children} }
export default Button
import Button from "../../components/button/button"
import styles from './home.module.css'
function HomePage() { return
Home page
}
export default HomePage
P.S. You can reproduce this but with cssCodeSplit: true or false.
System Info
Output of
npx envinfo --system --npmPackages vite,@vitejs/plugin-vue --binaries --browsers
:Used package manager:
Logs
Before submitting the issue, please make sure you do the following
the same issue for vue vite
i also meet the same problem
I also have the same problem with React
+1
How did you solve it
Same problem.
Same problem.
Same problem.
Same problem.
Same problem.
Any updates?(
Maybe @sodatea will provide some thoughts where to find problem in project and i will try to make pull request to vite?
I'm seeing this issue as well, now that I've started to use storybook's new dynamic loading feature, my styles are broken in production stories. I've found that the css files are directly after the component in the network tab. So, in one example, I have a RadioButton component that imports Label (which has its own styles that I want to override), and then it imports some css module with the overrides. However, when building now, I see this:
Which puts the RadioButton styles higher in the cascade, and they are overwritten by the Label styles, which is backwards from what I want.
Here is a minimal stackblitz reproduction: https://stackblitz.com/edit/vite-gu874q?file=main.jsx
vite: 2.7.1 @vitejs/plugin-react: 1.1.1
Great work @IanVS! Really hope this helps resolving the issue. I would help, but have no idea on where to start unfortunately.
I finally found the culprit, and FOR a while I thought
vite-plugin-pages
andunplugin-vue-components
were causing the problem, my bad. Glad to use them again.My temporary solution is to load influenced page synchronously in router configuration.
any idea when will #6301 be merged?
As far as I know it's not ready, @mgiraldo. This is a sticky problem to solve. If you have any ideas or can help out, please do!
i understand. thanks for all this work!
I wonder whether Vite could maybe look for a
__vite__injectStyle
global hook to allow overriding thehead.appendChild
behavior.With Webpack's
style-loader
one can specify a function/hook that will be called to place the style tag into the DOM (by default it will just append it to the head like Vite does).Webpack Configuration
``` // webpack.config.js { test: /\.css$/, use: [ { loader: "style-loader", options: { injectType: "singletonStyleTag", // this hook will be insert: require.resolve("./tools/insertStyleTag.ts"), }, }, { loader: "css-loader" }, ], }, ``` ``` // insertStyleTag.ts function insertStyleTag(element) { element.dataset.styleLoader = ""; // Custom logic, could be more complicated. Here I added a marker // to ensure `import ...` styles are added before `styled-component` // styles. document.head.insertBefore( element, document.head.querySelector("[data-styled]") ); } module.exports = insertStyleTag; ```For those who (like me) had to ship and need a temporary workaround: Depending on your project, you may be able to use
build.cssCodeSplit
to extract a single css file which has the classes in the correct order.sadly this didnt work out for me @laurentvd 😔 i might need to refactor my components 🤔
hay!
It's almost finished now, but it's stuck at one point. Now the loading order should be as expected, but there is still a problem with the execution order
Why pre-load
blue.module.css
but execute first__vite__updateStyle
is post-loadred.module.css
🥲However change the import order I do, it always load order by
red -> green -> blue
in dev mod.This is a pretty big issue. The production build styling order also differs in order compared with the dev build making working with Vite a nightmare for me. Is there no workaround I can use in the meanwhile, it seems we are a long way from having this fixed?
same issue
Same
@poyoho Any progress?
Same problem.
I tried out the latest vite 2.9.14 version, and the situation seems to be improved (not as many style errors as before), but not quite yet resolved. I rebased https://github.com/vitejs/vite/pull/6301 onto the latest 2.9 branch as well, but its test is still failing.
I have this problem i add antd css in main file and other css in component but in dev ant last style and component css before antd. Any have solution until fix it?
While this is frustrating, I was able to work around it using CSS layers.
If you're worried about browser support, there is a PostCSS plugin to help with that.
I import css end of all import in component before and now most first import all css and then import other component and solved this issue. Component A
ComponentB
But with CRA haven't this problem
This is a really big issue which is now open for over one and a half year and more. Is there any progress? anything on the horizon? We are using BEM. But with this problem parent component is not able to overwrite child css with a class which forces us to do parent > child selectors to get higher specifity which is against what we want to do with BEM. So we are a bit in trouble.
Any workaround on this, or idea when this will get solved?
@awacode21 not really a solution, but yet another workaround when you can't use (or it would be tricky) a parent selector ->
.something:not(#\#)
(or actually any other bogus value for:not(...)
) to make a selector more specific easily.(still struggling with this issue here since forever (already had it in webpack too))
@poyoho Can we please get an update on the progress of this and the open PR https://github.com/vitejs/vite/pull/9278?
has this issue perfectly resolved? Or still working on fixing?
As far as I know, it is not fixed and I don't think anyone is actively working on it. @poyoho made some heroic efforts on it, but was never able to handle all the edge cases. I wonder if code splitting is just fundamentally incompatible with css modules.
just to be certain, is the goal with #9278 is to make CSS insertion (in dev) follow what's already happening in production builds?
I don't think so. If anything, it is to make production builds behave similarly to dev.
The only way to preserve CSS ordering when bundling is to bundle all CSS into 1 CSS file per-page. Once you chunk common dependencies you are creating scenarios where ordering will be different on some pages. In Astro we are reconsidering whether to use the
:where
selector due to this. We might also come up with some other solutions. Just chiming in that the underlying problem is probably unsolvable.I suppose it's also not possible to just bundle all CSS into a single bundle at build, because the order of the dynamic imports can't be known until runtime, right?
@IanVS For the entire site or a single page? For an entire site that's typically unwanted because the CSS file is going to be quite large and it will cause unwanted styles on some pages. If you mean on a single page you can do that, but it just means that shared CSS gets loaded once for each page, and people often don't like that.
I'm curious if it's possible to deploy a true unbundled build that just loads the CSS the same as in dev..
akin to the "granular chunking" in project aurora: https://developer.chrome.com/blog/introducing-aurora/
In my case, I have a single-page-app (so I guess, both?). Right now, I'm not able to use dynamic imports / lazy loading because of the style problems. Even if I had to load the entire site's CSS up front, that would be a bit of an improvement if I could start to code-split the JS. But, I doubt that it's possible to bundle all the CSS in the correct order in that situation.
This issue is specifically about css modules. I suppose other styling approaches do not suffer this same problem, and perhaps I need to investigate other approaches if I want to use dynamic imports. Has anyone else here had any luck working around this problem by changing your approach to styling?
i mentioned above that i worked around it using cascade layers. it was a long time ago so i don't remember the exact details (i think it was with css modules).
when you define your layers upfront, the order of imports doesn't matter anymore so it will behave predictably even if vite messes it up.
I'm very excited about cascade layers. I even created https://github.com/DefinedNet/postcss-assign-layer to make it possible to automatically assign component css to a particular layer based on a glob. Unfortunately browser support is not yet good enough for me, and the postcss polyfill requires that all styles are known up-front: https://github.com/csstools/postcss-plugins/issues/376#issuecomment-1126511448.
I have the same issue. Vite --host works fine, but code after Vite build mixes order css files. My workaround is !important property but it is crap
This reference could help with this issue?
Vite css.modules
Any progress on this issue please? I'm having the same problem when packaging my application using the Federation module.
I'm having the same problem when packaging multiple page apps.