Skip to content

Commit 01b3b41

Browse files
author
Brijesh Bittu
committed
[docs] Guide on supporting npm packages with css imports
This guide lists down any configuration change required for several bundlers to support npm packages that have css imports in their code.
1 parent 37d7020 commit 01b3b41

File tree

4 files changed

+182
-0
lines changed

4 files changed

+182
-0
lines changed
Lines changed: 170 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,170 @@
1+
# Configuring Bundlers for Packages with CSS Imports
2+
3+
<p class="description">Learn how to configure popular bundlers to correctly handle CSS imports from within npm packages.</p>
4+
5+
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.
6+
7+
## Next.js
8+
9+
### App Router
10+
11+
✅ Works out of the box.
12+
13+
### Pages Router
14+
15+
❌ Configuration change is required.
16+
17+
Add the desired package(s) to the `transpilePackages` array item.
18+
19+
```js title="next.config.mjs"
20+
const nextConfig = {
21+
// ...rest of the config
22+
transpilePackages: ['@mui/x-data-grid'],
23+
};
24+
25+
export default nextConfig;
26+
```
27+
28+
## Parcel
29+
30+
✅ Works out of the box.
31+
32+
## Rsbuild
33+
34+
✅ Works out of the box.
35+
36+
## Rspack
37+
38+
✅ Works out of the box.
39+
40+
## Vite
41+
42+
### For client side apps
43+
44+
✅ Works out of the box.
45+
46+
### For apps using Vite's SSR
47+
48+
❌ Works with a minor configuration change.
49+
50+
Add the desired packages to `ssr.noExternal` array.
51+
52+
```ts title="vite.config.ts"
53+
import { defineConfig } from 'vite';
54+
// ...
55+
56+
export default defineConfig({
57+
plugins: [
58+
// plugins,
59+
],
60+
ssr: {
61+
noExternal: ['@mui/x-data-grid'],
62+
},
63+
});
64+
```
65+
66+
## webpack
67+
68+
❌ Configuration change is required.
69+
70+
We'll have to configure `css-loader` to target CSS files within `node_modules` of the packages.
71+
72+
In both the development and production modes, we'll need to add one more loader to `module.rules` key of the config as shown.
73+
74+
Development mode -
75+
76+
```js title="webpack.config.js"
77+
module.exports = {
78+
module: {
79+
rules: [
80+
// rest of the loaders
81+
{
82+
test: /node_modules\/(@mui\/x-data-grid|package2)\/(.*)\.css$/,
83+
use: ['style-loader', 'css-loader'],
84+
},
85+
],
86+
},
87+
};
88+
```
89+
90+
Make sure that `css-loader` and `style-loader` is already installed.
91+
92+
Production mode -
93+
94+
```js title="webpack.config.js"
95+
module.exports = {
96+
module: {
97+
rules: [
98+
// rest of the loaders
99+
{
100+
test: /node_modules\/(@mui\/x-data-grid|package2)\/(.*)\.css$/,
101+
use: [
102+
// or add other minifier's loader as per your app
103+
MiniCssExtractPlugin.loader,
104+
'css-loader',
105+
],
106+
},
107+
],
108+
},
109+
};
110+
```
111+
112+
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.
113+
114+
## Node.js
115+
116+
❌ Configuration change is required.
117+
118+
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.
119+
120+
```js title="loader.js"
121+
function load(url, context, nextLoad) {
122+
if (url.substring(url.length - 4) === '.css') {
123+
return {
124+
format: 'module',
125+
shortCircuit: true,
126+
source: '',
127+
};
128+
}
129+
130+
// Do default loading for other files
131+
return nextLoad(url, context);
132+
}
133+
134+
// Or
135+
// exports.load = load;
136+
// for CJS
137+
export { load };
138+
```
139+
140+
and modify the script call -
141+
142+
```json title="package.json"
143+
{
144+
"scripts": {
145+
"start": "node --loader ./loader.js my-script.js"
146+
}
147+
}
148+
```
149+
150+
This might log a warning for older Node.js version like -
151+
152+
```bash
153+
(node:56826) ExperimentalWarning: `--experimental-loader` may be removed in the future; instead use `register()`:
154+
```
155+
156+
In that case, the script call would be -
157+
158+
```json title="package.json"
159+
{
160+
"scripts": {
161+
"start": "node --import 'data:text/javascript,import { register } from \"node:module\"; import { pathToFileURL } from \"node:url\"; register(\"./loader.js\", pathToFileURL(\"./\"));' my-script.js"
162+
}
163+
}
164+
```
165+
166+
## Conclusion
167+
168+
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.
169+
170+
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.

docs/data/material/pages.ts

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -265,6 +265,10 @@ const pages: MuiPage[] = [
265265
pathname: '/material-ui/guides/content-security-policy',
266266
title: 'Content Security Policy',
267267
},
268+
{
269+
pathname: '/material-ui/guides/configuring-bundlers-for-css-imports',
270+
title: 'Configuring bundlers for CSS imports',
271+
},
268272
],
269273
},
270274
{
Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
import * as React from 'react';
2+
import MarkdownDocs from 'docs/src/modules/components/MarkdownDocs';
3+
import * as pageProps from 'docs/data/material/guides/packages-with-css-imports/configuring-bundlers-for-css-imports.md?muiMarkdown';
4+
5+
export default function Page() {
6+
return <MarkdownDocs {...pageProps} />;
7+
}

docs/translations/translations.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -156,6 +156,7 @@
156156
"/material-ui/guides/typescript": "TypeScript",
157157
"/material-ui/guides/composition": "Composition",
158158
"/material-ui/guides/content-security-policy": "Content Security Policy",
159+
"/material-ui/guides/configuring-bundlers-for-css-imports": "Configuring bundlers for CSS imports",
159160
"/material-ui/integrations": "Integrations",
160161
"/material-ui/integrations/tailwindcss/tailwindcss-v4": "Tailwind CSS v4 integration",
161162
"/material-ui/integrations/nextjs": "Next.js integration",

0 commit comments

Comments
 (0)