question-mark
Stuck on an issue?

Lightrun Answers was designed to reduce the constant googling that comes with debugging 3rd party libraries. It collects links to all the places you might be looking at while hunting down a tough bug.

And, if you’re still stuck at the end, we’re happy to hop on a call to see how we can help out.

Vite injects css assets in wrong order with dynamic import and css modules.

See original GitHub issue

Describe the bug

Vite injects css assets in wrong order with dynamic import and css modules.

Reproduction

Repo to reproduce

For example:

  1. 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
}
  1. 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;
}
  1. 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
  1. You exepect page styles will override button styles, but they are not (as vite injects styles in wrong order)
Screenshot 2021-06-23 at 19 12 44

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:open
  • Created 2 years ago
  • Reactions:37
  • Comments:34 (7 by maintainers)

github_iconTop GitHub Comments

14reactions
Winston-Guesscommented, Apr 20, 2022

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?

5reactions
sonic-knucklescommented, Oct 17, 2022

@poyoho Can we please get an update on the progress of this and the open PR https://github.com/vitejs/vite/pull/9278?

Read more comments on GitHub >

github_iconTop 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 >

github_iconTop Related Medium Post

No results found

github_iconTop Related StackOverflow Question

No results found

github_iconTroubleshoot Live Code

Lightrun enables developers to add logs, metrics and snapshots to live code - no restarts or redeploys required.
Start Free

github_iconTop Related Hackernoon Post

No results found

github_iconTop Related Tweet

No results found

github_iconTop Related Dev.to Post

No results found

github_iconTop Related Hashnode Post

No results found