Vite injects css assets in wrong order with dynamic import and css modules.
See original GitHub issueDescribe the bug
Vite injects css assets in wrong order with dynamic import and css modules.
Reproduction
For example:
- You have component Button with default styles (text color: red)
/* button.tsx */
import React from "react"
import classnames from 'classnames'
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}</button>
}
export default Button
/* button.module.css */
.button {
color: red
}
- You have Page component. This page use Button component and overrides it styles by passing custom class name as a prop (text color: green)
/* home.tsx /*
import React from "react"
import Button from "../../components/button/button"
import styles from './home.module.css'
function HomePage() {
return <div>
<h1>Home page</h1>
<Button className={styles.greenTextButton}>should be green</Button>
</div>
}
export default HomePage
/* home.module.css */
.greenTextButton {
color: green;
}
- You import Page component with dynamic import.
import React, { lazy, Suspense, useState } from 'react'
const HomePage = lazy(() => import('./pages/home/home'))
const AboutPage = lazy(() => import('./pages/about/about'))
function App() {
const [page, setPage] = useState('home')
return (
<div>
<a href="#" onClick={() => setPage('home')} style={{ marginRight: '5px' }}>home page</a>
<a href="#" onClick={() => setPage('about')}>about page</a>
<Suspense fallback={<div>loading</div>}>
{page === 'home' && (
<HomePage />
)}
{page === 'about' && (
<AboutPage />
)}
</Suspense>
</div>
)
}
export default App
- You exepect page styles will override button styles, but they are not (as vite injects styles in wrong order)

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
:
System:
OS: macOS 11.4
CPU: (12) x64 Intel(R) Core(TM) i7-9750H CPU @ 2.60GHz
Memory: 94.85 MB / 16.00 GB
Shell: 5.8 - /bin/zsh
Binaries:
Node: 14.16.1 - ~/.volta/tools/image/node/14.16.1/bin/node
npm: 6.14.12 - ~/.volta/tools/image/node/14.16.1/bin/npm
Browsers:
Chrome: 91.0.4472.114
Firefox: 89.0
Safari: 14.1.1
npmPackages:
vite: ^2.3.8 => 2.3.8
Used package manager:
Logs
vite:config bundled config file loaded in 42ms +0ms
vite:config using resolved config: {
vite:config plugins: [
vite:config 'alias',
vite:config 'react-refresh',
vite:config 'vite:dynamic-import-polyfill',
vite:config 'vite:resolve',
vite:config 'vite:html',
vite:config 'vite:css',
vite:config 'vite:esbuild',
vite:config 'vite:json',
vite:config 'vite:wasm',
vite:config 'vite:worker',
vite:config 'vite:asset',
vite:config 'vite:define',
vite:config 'vite:css-post',
vite:config 'vite:build-html',
vite:config 'commonjs',
vite:config 'vite:data-uri',
vite:config 'rollup-plugin-dynamic-import-variables',
vite:config 'vite:import-analysis',
vite:config 'vite:esbuild-transpile',
vite:config 'vite:terser',
vite:config 'vite:reporter'
vite:config ],
vite:config build: {
vite:config target: [ 'es2019', 'edge88', 'firefox78', 'chrome87', 'safari13.1' ],
vite:config polyfillDynamicImport: false,
vite:config outDir: 'dist',
vite:config assetsDir: 'assets',
vite:config assetsInlineLimit: 4096,
vite:config cssCodeSplit: true,
vite:config sourcemap: false,
vite:config rollupOptions: {},
vite:config commonjsOptions: { include: [Array], extensions: [Array] },
vite:config minify: 'terser',
vite:config terserOptions: {},
vite:config cleanCssOptions: {},
vite:config write: true,
vite:config emptyOutDir: null,
vite:config manifest: false,
vite:config lib: false,
vite:config ssr: false,
vite:config ssrManifest: false,
vite:config brotliSize: true,
vite:config chunkSizeWarningLimit: 500,
vite:config watch: null
vite:config },
vite:config configFile: '/Users/anatoliidomaratskyi/Work/Mimy/css-code-split-order/vite.config.ts',
vite:config configFileDependencies: [ 'vite.config.ts' ],
vite:config inlineConfig: {
vite:config root: undefined,
vite:config base: undefined,
vite:config mode: undefined,
vite:config configFile: undefined,
vite:config logLevel: undefined,
vite:config clearScreen: undefined,
vite:config build: {}
vite:config },
vite:config root: '/Users/anatoliidomaratskyi/Work/Mimy/css-code-split-order',
vite:config base: '/',
vite:config resolve: { dedupe: undefined, alias: [ [Object] ] },
vite:config publicDir: '/Users/anatoliidomaratskyi/Work/Mimy/css-code-split-order/public',
vite:config cacheDir: '/Users/anatoliidomaratskyi/Work/Mimy/css-code-split-order/node_modules/.vite',
vite:config command: 'build',
vite:config mode: 'production',
vite:config isProduction: true,
vite:config server: {
vite:config fsServe: {
vite:config root: '/Users/anatoliidomaratskyi/Work/Mimy/css-code-split-order',
vite:config strict: false
vite:config }
vite:config },
vite:config env: { BASE_URL: '/', MODE: 'production', DEV: false, PROD: true },
vite:config assetsInclude: [Function: assetsInclude],
vite:config logger: {
vite:config hasWarned: false,
vite:config info: [Function: info],
vite:config warn: [Function: warn],
vite:config warnOnce: [Function: warnOnce],
vite:config error: [Function: error],
vite:config clearScreen: [Function: clearScreen]
vite:config },
vite:config createResolver: [Function: createResolver],
vite:config optimizeDeps: { esbuildOptions: { keepNames: undefined } }
vite:config } +6ms
vite v2.3.8 building for production...
✓ 33 modules transformed.
dist/assets/favicon.17e50649.svg 1.49kb
dist/index.html 0.45kb
dist/assets/home.5d3a6e0a.js 0.26kb / brotli: 0.15kb
dist/assets/button.14aa6fb9.js 0.80kb / brotli: 0.41kb
dist/assets/home.deac2baa.css 0.04kb / brotli: 0.04kb
dist/assets/about.563410d2.js 0.60kb / brotli: 0.28kb
dist/assets/button.a44dba50.css 0.03kb / brotli: 0.03kb
dist/assets/index.3938cd91.js 1.55kb / brotli: 0.60kb
dist/assets/about.d57e38e3.css 0.06kb / brotli: 0.05kb
dist/assets/vendor.cc984a25.js 127.61kb / brotli: 36.05kb
Before submitting the issue, please make sure you do the following
- [ +] Read the Contributing Guidelines.
- [ +] Read the docs.
- [ +] 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.
- [ +] Check that this is a concrete bug. For Q&A open a GitHub Discussion or join our Discord Chat Server.
Issue Analytics
- State:
- Created 2 years ago
- Reactions:37
- Comments:34 (7 by maintainers)
Top Results From Across the Web
Features | Vite
In this case, the processed CSS string is returned as the module's default export as usual, but the styles aren't injected to the...
Read more >Can't import CSS/SCSS modules. TypeScript says "Cannot ...
I think there's something wrong with my Webpack config but I'm not sure where the problem is. I'm using the following tools: "typescript":...
Read more >vite build - patak-dev
Vite supports code splitting, both JS and CSS assets. When a dynamic import is encountered, an async JS chunk and a CSS chunk...
Read more >rollup.js
Import a specific item from a source module, with its original name. import { something } from '. ... Import modules using the...
Read more >Setting up a dev environment with React, Vite, and Tailwind
Both Vite and Tailwind CSS excel in simplicity, performance, and developer ... Vite implements the code split dynamic import calls in a ...
Read more >
Top Related Medium Post
No results found
Top Related StackOverflow Question
No results found
Troubleshoot Live Code
Lightrun enables developers to add logs, metrics and snapshots to live code - no restarts or redeploys required.
Start Free
Top Related Reddit Thread
Top Related Hackernoon Post
No results found
Top Related Tweet
No results found
Top Related Dev.to Post
No results found
Top Related Hashnode Post
No results found
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?
@poyoho Can we please get an update on the progress of this and the open PR https://github.com/vitejs/vite/pull/9278?