Configuring Bundlers for Packages with CSS Imports
Learn how to configure popular bundlers to correctly handle CSS imports from within npm packages.
When working with npm packages that include CSS imports directly within their files, it's crucial to ensure the project's bundler is correctly configured to handle these styles. This guide provides an overview of how various popular bundlers support such packages and any necessary configuration change required.
Next.js
App Router
✅ Works out of the box.
Pages Router
❌ Configuration change is required.
Add the desired package(s) to the transpilePackages
array item.
const nextConfig = {
// ...rest of the config
transpilePackages: ['@mui/x-data-grid'],
};
export default nextConfig;
Parcel
✅ Works out of the box.
Rsbuild
✅ Works out of the box.
Rspack
✅ Works out of the box.
Vite
For client side apps
✅ Works out of the box.
For apps using Vite's SSR
❌ Works with a minor configuration change.
Add the desired packages to ssr.noExternal
array.
import { defineConfig } from 'vite';
// ...
export default defineConfig({
plugins: [
// plugins,
],
ssr: {
noExternal: ['@mui/x-data-grid'],
},
});
webpack
❌ Configuration change is required.
We'll have to configure css-loader
to target CSS files within node_modules
of the packages.
In both the development and production modes, we'll need to add one more loader to module.rules
key of the config as shown.
Development mode -
module.exports = {
module: {
rules: [
// rest of the loaders
{
test: /node_modules\/(@mui\/x-data-grid|package2)\/(.*)\.css$/,
use: ['style-loader', 'css-loader'],
},
],
},
};
Make sure that css-loader
and style-loader
is already installed.
Production mode -
module.exports = {
module: {
rules: [
// rest of the loaders
{
test: /node_modules\/(@mui\/x-data-grid|package2)\/(.*)\.css$/,
use: [
// or add other minifier's loader as per your app
MiniCssExtractPlugin.loader,
'css-loader',
],
},
],
},
};
These rules specifically target CSS files within packages inside node_modules
. If there's already a CSS loader configured for app specific CSS files, make sure to add the exclude: /node_modules/
key so that the same CSS file doesn't go through both the loaders.
Node.js
❌ Configuration change is required.
To run scripts directly with Node.js (or Bun) where CSS imports are also involved, we need to configure loader for the runtime to ignore such imports. At the bare minimum, we need a loader file and slight modification to the script invocation.
function load(url, context, nextLoad) {
if (url.substring(url.length - 4) === '.css') {
return {
format: 'module',
shortCircuit: true,
source: '',
};
}
// Do default loading for other files
return nextLoad(url, context);
}
// Or
// exports.load = load;
// for CJS
export { load };
and modify the script call -
{
"scripts": {
"start": "node --loader ./loader.js my-script.js"
}
}
This might log a warning for older Node.js version like -
(node:56826) ExperimentalWarning: `--experimental-loader` may be removed in the future; instead use `register()`:
In that case, the script call would be -
{
"scripts": {
"start": "node --import 'data:text/javascript,import { register } from \"node:module\"; import { pathToFileURL } from \"node:url\"; register(\"./loader.js\", pathToFileURL(\"./\"));' my-script.js"
}
}
Conclusion
Most modern bundlers handle CSS imports from npm packages quite well, often requiring no extra setup. However, certain setups like webpack or specific server-rendering contexts might need explicit configuration to transpile or correctly process these packages.
Feel free to open a PR to this doc (through Edit this page
link at the bottom) if certain runtimes or bundler configurations are wrong or missing.