Vite Plugin Lazy CSS Modules Inliner

raw JSON →
0.2.0 verified Mon Apr 27 auth: no javascript

A Vite plugin (v0.2.0) that enables true on-demand CSS injection for dynamically imported code by virtualizing CSS Modules. It prevents lazy components' styles from being bundled into the page's initial CSS, injecting them only when the corresponding JavaScript chunk is actually loaded. Supports Vite 4+, TypeScript, and frameworks like React, Vue, Svelte (via external *.module.css imports). Unlike typical CSS-in-JS solutions or code-splitting plugins, it preserves CSS Modules hashing, avoids preloading CSS via __vitePreload, and includes built-in RTL support via runtimeIsRtlCondition. Released as a proof-of-concept with active maintenance.

error Error: Cannot find module 'vite-plugin-lazy-css-modules-inliner'
cause Package not installed or import path incorrect
fix
Install with npm install --save-dev vite-plugin-lazy-css-modules-inliner and verify package.json includes it.
error TypeError: viteLazyCssInliner is not a function
cause Using default import instead of named import
fix
Change import viteLazyCssInliner from ... to import { viteLazyCssInliner } from ....
error Error: The plugin 'vite-plugin-lazy-css-modules-inliner' requires Vite >=4 but current version is 3.x
cause Incompatible Vite version
fix
Update Vite to version 4 or higher: npm install vite@^4.
error Error: getModuleInfo(id).dynamicImporters is not a function
cause Using a Vite version older than 4 where getModuleInfo returns undefined
fix
Upgrade Vite to >=4, as the plugin relies on dynamicImporters property added in Vite 4.
error Warning: You are using stripPreloadDepsMode: 'all' which may break chunk loading in some scenarios
cause Using a configuration option that is not recommended for general use
fix
Set stripPreloadDepsMode to 'css' (default) unless you have a specific reason to use 'all'.
breaking requires node >= 18 and vite >= 4
fix Update Node.js to 18+ and Vite to 4+. Check engines field in package.json.
deprecated stripPreloadDepsMode: 'all' may cause unexpected behavior in shared chunks
fix Use 'css' (default) unless you fully understand the implications. 'all' strips all dependencies from __vitePreload which can break chunk loading.
gotcha Mixed static and dynamic imports of the same CSS module can duplicate CSS
fix Use only dynamic imports for CSS modules that are lazy-loaded, or accept the duplication. Do not mix import styles for the same module.
gotcha The plugin re-routes CSS imports inside lazy graphs to virtual modules; if you see 'Cannot find module' errors for virtual IDs, your bundler may not support virtual modules
fix Ensure you are using Vite (not a custom bundler). Virtual modules are Vite-specific and won't work with plain Rollup.
gotcha RTL support requires rtlcss to be installed as a dependency if runtimeIsRtlCondition is set
fix Run `npm install --save-dev rtlcss` and set runtimeIsRtlCondition in plugin options.
gotcha SSR build: virtual CSS modules are loaded as empty, so styles won't be injected server-side; client hydration will inject them, causing potential flash of unstyled content
fix Ensure you have a ClientRouter or wait for hydration. Consider using a CSS-in-JS solution for SSR if flashes are unacceptable.
npm install vite-plugin-lazy-css-modules-inliner
yarn add vite-plugin-lazy-css-modules-inliner
pnpm add vite-plugin-lazy-css-modules-inliner

Shows basic setup with vite.config.ts plugin initialization and a lazy-loaded React component using CSS Modules. The plugin intercepts dynamic imports to inline CSS only when the component is actually rendered.

// vite.config.ts
import { defineConfig } from 'vite';
import { viteLazyCssInliner } from 'vite-plugin-lazy-css-modules-inliner';

export default defineConfig({
  plugins: [
    viteLazyCssInliner({
      stripPreloadDepsMode: 'css', // default
      isDev: process.env.NODE_ENV !== 'production',
      includedPathes: ['src'],
      excludedPathes: ['node_modules'],
    }),
  ],
});

// MyComponent.jsx
import styles from './MyComponent.module.css';
const MyComponent = () => <div className={styles.root}>Hello</div>;
export default MyComponent;