UNPKG

31.8 kBMarkdownView Raw
1<div align="center">
2 <img width="200" height="200" src="https://cdn.worldvectorlogo.com/logos/logo-javascript.svg">
3 <a href="https://webpack.js.org/">
4 <img width="200" height="200" vspace="" hspace="25" src="https://cdn.rawgit.com/webpack/media/e7485eb2/logo/icon-square-big.svg">
5 </a>
6 <h1>mini-css-extract-plugin</h1>
7</div>
8
9[![npm][npm]][npm-url]
10[![node][node]][node-url]
11[![deps][deps]][deps-url]
12[![tests][tests]][tests-url]
13[![coverage][cover]][cover-url]
14[![chat][chat]][chat-url]
15[![size][size]][size-url]
16
17# mini-css-extract-plugin
18
19This plugin extracts CSS into separate files. It creates a CSS file per JS file which contains CSS. It supports On-Demand-Loading of CSS and SourceMaps.
20
21It builds on top of a new webpack v5 feature and requires webpack 5 to work.
22
23Compared to the extract-text-webpack-plugin:
24
25- Async loading
26- No duplicate compilation (performance)
27- Easier to use
28- Specific to CSS
29
30## Getting Started
31
32To begin, you'll need to install `mini-css-extract-plugin`:
33
34```bash
35npm install --save-dev mini-css-extract-plugin
36```
37
38It's recommended to combine `mini-css-extract-plugin` with the [`css-loader`](https://github.com/webpack-contrib/css-loader)
39
40Then add the loader and the plugin to your `webpack` config. For example:
41
42**style.css**
43
44```css
45body {
46 background: green;
47}
48```
49
50**component.js**
51
52```js
53import "./style.css";
54```
55
56**webpack.config.js**
57
58```js
59const MiniCssExtractPlugin = require("mini-css-extract-plugin");
60
61module.exports = {
62 plugins: [new MiniCssExtractPlugin()],
63 module: {
64 rules: [
65 {
66 test: /\.css$/i,
67 use: [MiniCssExtractPlugin.loader, "css-loader"],
68 },
69 ],
70 },
71};
72```
73
74> ⚠️ Note that if you import CSS from your webpack entrypoint or import styles in the [initial](https://webpack.js.org/concepts/under-the-hood/#chunks) chunk, `mini-css-extract-plugin` will not load this CSS into the page. Please use [`html-webpack-plugin`](https://github.com/jantimon/html-webpack-plugin) for automatic generation `link` tags or create `index.html` file with `link` tag.
75
76> ⚠️ Source maps works only for `source-map`/`nosources-source-map`/`hidden-nosources-source-map`/`hidden-source-map` values because CSS only supports source maps with the `sourceMappingURL` comment (i.e. `//# sourceMappingURL=style.css.map`). If you need set `devtool` to another value you can enable source maps generation for extracted CSS using [`sourceMap: true`](https://github.com/webpack-contrib/css-loader#sourcemap) for `css-loader`.
77
78## Options
79
80### Plugin Options
81
82| Name | Type | Default | Description |
83| :---------------------------------------------------------------: | :------------------: | :-----------------------------------: | :---------------------------------------------------------------------------------------------------------------------------------------- |
84| **[`filename`](#filename)** | `{String\|Function}` | `[name].css` | This option determines the name of each output CSS file |
85| **[`chunkFilename`](#chunkFilename)** | `{String\|Function}` | `based on filename` | This option determines the name of non-entry chunk files |
86| **[`ignoreOrder`](#ignoreOrder)** | `{Boolean}` | `false` | Remove Order Warnings |
87| **[`insert`](#insert)** | `{String\|Function}` | `document.head.appendChild(linkTag);` | Inserts the `link` tag at the given position for [non-initial (async)](https://webpack.js.org/concepts/under-the-hood/#chunks) CSS chunks |
88| **[`attributes`](#attributes)** | `{Object}` | `{}` | Adds custom attributes to the `link` tag for [non-initial (async)](https://webpack.js.org/concepts/under-the-hood/#chunks) CSS chunks |
89| **[`linkType`](#linkType)** | `{String\|Boolean}` | `text/css` | Allows loading asynchronous chunks with a custom link type |
90| **[`runtime`](#runtime)** | `{Boolean}` | `true` | Allows to enable/disable the runtime generation |
91| **[`experimentalUseImportModule`](#experimentalUseImportModule)** | `{Boolean}` | `undefined` | Use an experimental webpack API to execute modules instead of child compilers |
92
93#### `filename`
94
95Type: `String|Function`
96Default: `[name].css`
97
98This option determines the name of each output CSS file.
99
100Works like [`output.filename`](https://webpack.js.org/configuration/output/#outputfilename)
101
102#### `chunkFilename`
103
104Type: `String|Function`
105Default: `based on filename`
106
107> i Specifying `chunkFilename` as a `function` is only available in webpack@5
108
109This option determines the name of non-entry chunk files.
110
111Works like [`output.chunkFilename`](https://webpack.js.org/configuration/output/#outputchunkfilename)
112
113#### `ignoreOrder`
114
115Type: `Boolean`
116Default: `false`
117
118Remove Order Warnings.
119See [examples](#remove-order-warnings) below for details.
120
121#### `insert`
122
123Type: `String|Function`
124Default: `document.head.appendChild(linkTag);`
125
126> ⚠️ Only for [non-initial (async)](https://webpack.js.org/concepts/under-the-hood/#chunks) chunks.
127
128By default, the `mini-css-extract-plugin` appends styles (`<link>` elements) to `document.head` of the current `window`.
129
130However in some circumstances it might be necessary to have finer control over the append target or even delay `link` elements insertion.
131For example this is the case when you asynchronously load styles for an application that runs inside of an iframe.
132In such cases `insert` can be configured to be a function or a custom selector.
133
134If you target an [iframe](https://developer.mozilla.org/en-US/docs/Web/API/HTMLIFrameElement) make sure that the parent document has sufficient access rights to reach into the frame document and append elements to it.
135
136##### `String`
137
138Allows to setup custom [query selector](https://developer.mozilla.org/en-US/docs/Web/API/Document/querySelector).
139A new `<link>` element will be inserted after the found item.
140
141**webpack.config.js**
142
143```js
144new MiniCssExtractPlugin({
145 insert: "#some-element",
146});
147```
148
149A new `<link>` element will be inserted after the element with id `some-element`.
150
151##### `Function`
152
153Allows to override default behavior and insert styles at any position.
154
155> ⚠ Do not forget that this code will run in the browser alongside your application. Since not all browsers support latest ECMA features like `let`, `const`, `arrow function expression` and etc we recommend you to use only ECMA 5 features and syntax.
156
157> > ⚠ The `insert` function is serialized to string and passed to the plugin. This means that it won't have access to the scope of the webpack configuration module.
158
159**webpack.config.js**
160
161```js
162new MiniCssExtractPlugin({
163 insert: function (linkTag) {
164 var reference = document.querySelector("#some-element");
165 if (reference) {
166 reference.parentNode.insertBefore(linkTag, reference);
167 }
168 },
169});
170```
171
172A new `<link>` element will be inserted before the element with id `some-element`.
173
174#### `attributes`
175
176Type: `Object`
177Default: `{}`
178
179> ⚠️ Only for [non-initial (async)](https://webpack.js.org/concepts/under-the-hood/#chunks) chunks.
180
181If defined, the `mini-css-extract-plugin` will attach given attributes with their values on `<link>` element.
182
183**webpack.config.js**
184
185```js
186const MiniCssExtractPlugin = require("mini-css-extract-plugin");
187
188module.exports = {
189 plugins: [
190 new MiniCssExtractPlugin({
191 attributes: {
192 id: "target",
193 "data-target": "example",
194 },
195 }),
196 ],
197 module: {
198 rules: [
199 {
200 test: /\.css$/i,
201 use: [MiniCssExtractPlugin.loader, "css-loader"],
202 },
203 ],
204 },
205};
206```
207
208Note: It's only applied to dynamically loaded css chunks, if you want to modify link attributes inside html file, please using [html-webpack-plugin](https://github.com/jantimon/html-webpack-plugin)
209
210#### `linkType`
211
212Type: `String|Boolean`
213Default: `text/css`
214
215This option allows loading asynchronous chunks with a custom link type, such as `<link type="text/css" ...>`.
216
217##### `String`
218
219Possible values: `text/css`
220
221**webpack.config.js**
222
223```js
224const MiniCssExtractPlugin = require("mini-css-extract-plugin");
225
226module.exports = {
227 plugins: [
228 new MiniCssExtractPlugin({
229 linkType: "text/css",
230 }),
231 ],
232 module: {
233 rules: [
234 {
235 test: /\.css$/i,
236 use: [MiniCssExtractPlugin.loader, "css-loader"],
237 },
238 ],
239 },
240};
241```
242
243##### `Boolean`
244
245`false` disables the link `type` attribute
246
247**webpack.config.js**
248
249```js
250const MiniCssExtractPlugin = require("mini-css-extract-plugin");
251
252module.exports = {
253 plugins: [
254 new MiniCssExtractPlugin({
255 linkType: false,
256 }),
257 ],
258 module: {
259 rules: [
260 {
261 test: /\.css$/i,
262 use: [MiniCssExtractPlugin.loader, "css-loader"],
263 },
264 ],
265 },
266};
267```
268
269#### `runtime`
270
271Type: `Boolean`
272Default: `true`
273
274Allows to enable/disable the runtime generation.
275CSS will be still extracted and can be used for a custom loading methods.
276For example, you can use [assets-webpack-plugin](https://github.com/ztoben/assets-webpack-plugin) to retreive them then use your own runtime code to download assets when needed.
277
278`true` to skip.
279
280**webpack.config.js**
281
282```js
283const MiniCssExtractPlugin = require("mini-css-extract-plugin");
284
285module.exports = {
286 plugins: [
287 new MiniCssExtractPlugin({
288 runtime: false,
289 }),
290 ],
291 module: {
292 rules: [
293 {
294 test: /\.css$/i,
295 use: [MiniCssExtractPlugin.loader, "css-loader"],
296 },
297 ],
298 },
299};
300```
301
302#### `experimentalUseImportModule`
303
304Type: `Boolean`
305Default: `undefined`
306
307Enabled by default if not explicitly enabled (i.e. `true` and `false` allow you to explicitly control this option) and new API is available (at least webpack `5.52.0` is required).
308Boolean values are available since version `5.33.2`, but you need to enable `experiments.executeModule` (not required from webpack `5.52.0`).
309
310Use a new webpack API to execute modules instead of child compilers.
311This improves performance and memory usage a lot.
312
313When combined with `experiments.layers`, this adds a `layer` option to the loader options to specify the layer of the css execution.
314
315**webpack.config.js**
316
317```js
318const MiniCssExtractPlugin = require("mini-css-extract-plugin");
319
320module.exports = {
321 plugins: [
322 new MiniCssExtractPlugin({
323 // You don't need this for `>= 5.52.0` due to the fact that this is enabled by default
324 // Required only for `>= 5.33.2 & <= 5.52.0`
325 // Not avaliable/unsafe for `<= 5.33.2`
326 experimentalUseImportModule: true,
327 }),
328 ],
329 module: {
330 rules: [
331 {
332 test: /\.css$/i,
333 use: [MiniCssExtractPlugin.loader, "css-loader"],
334 },
335 ],
336 },
337};
338```
339
340### Loader Options
341
342| Name | Type | Default | Description |
343| :-----------------------------: | :------------------: | :--------------------------------: | :-------------------------------------------------------------------------------- |
344| **[`publicPath`](#publicPath)** | `{String\|Function}` | `webpackOptions.output.publicPath` | Specifies a custom public path for the external resources like images, files, etc |
345| **[`emit`](#emit)** | `{Boolean}` | `true` | If false, the plugin will extract the CSS but **will not** emit the file |
346| **[`esModule`](#esModule)** | `{Boolean}` | `true` | Use ES modules syntax |
347
348#### `publicPath`
349
350Type: `String|Function`
351Default: the `publicPath` in `webpackOptions.output`
352
353Specifies a custom public path for the external resources like images, files, etc inside `CSS`.
354Works like [`output.publicPath`](https://webpack.js.org/configuration/output/#outputpublicpath)
355
356##### `String`
357
358**webpack.config.js**
359
360```js
361const MiniCssExtractPlugin = require("mini-css-extract-plugin");
362
363module.exports = {
364 plugins: [
365 new MiniCssExtractPlugin({
366 // Options similar to the same options in webpackOptions.output
367 // both options are optional
368 filename: "[name].css",
369 chunkFilename: "[id].css",
370 }),
371 ],
372 module: {
373 rules: [
374 {
375 test: /\.css$/,
376 use: [
377 {
378 loader: MiniCssExtractPlugin.loader,
379 options: {
380 publicPath: "/public/path/to/",
381 },
382 },
383 "css-loader",
384 ],
385 },
386 ],
387 },
388};
389```
390
391##### `Function`
392
393**webpack.config.js**
394
395```js
396const MiniCssExtractPlugin = require("mini-css-extract-plugin");
397
398module.exports = {
399 plugins: [
400 new MiniCssExtractPlugin({
401 // Options similar to the same options in webpackOptions.output
402 // both options are optional
403 filename: "[name].css",
404 chunkFilename: "[id].css",
405 }),
406 ],
407 module: {
408 rules: [
409 {
410 test: /\.css$/,
411 use: [
412 {
413 loader: MiniCssExtractPlugin.loader,
414 options: {
415 publicPath: (resourcePath, context) => {
416 return path.relative(path.dirname(resourcePath), context) + "/";
417 },
418 },
419 },
420 "css-loader",
421 ],
422 },
423 ],
424 },
425};
426```
427
428#### `emit`
429
430Type: `Boolean`
431Default: `true`
432
433If true, emits a file (writes a file to the filesystem). If false, the plugin will extract the CSS but **will not** emit the file.
434It is often useful to disable this option for server-side packages.
435
436#### `esModule`
437
438Type: `Boolean`
439Default: `true`
440
441By default, `mini-css-extract-plugin` generates JS modules that use the ES modules syntax.
442There are some cases in which using ES modules is beneficial, like in the case of [module concatenation](https://webpack.js.org/plugins/module-concatenation-plugin/) and [tree shaking](https://webpack.js.org/guides/tree-shaking/).
443
444You can enable a CommonJS syntax using:
445
446**webpack.config.js**
447
448```js
449const MiniCssExtractPlugin = require("mini-css-extract-plugin");
450
451module.exports = {
452 plugins: [new MiniCssExtractPlugin()],
453 module: {
454 rules: [
455 {
456 test: /\.css$/i,
457 use: [
458 {
459 loader: MiniCssExtractPlugin.loader,
460 options: {
461 esModule: false,
462 },
463 },
464 "css-loader",
465 ],
466 },
467 ],
468 },
469};
470```
471
472## Examples
473
474### Recommend
475
476For `production` builds it's recommended to extract the CSS from your bundle being able to use parallel loading of CSS/JS resources later on.
477This can be achieved by using the `mini-css-extract-plugin`, because it creates separate css files.
478For `development` mode (including `webpack-dev-server`) you can use [style-loader](https://github.com/webpack-contrib/style-loader), because it injects CSS into the DOM using multiple <style></style> and works faster.
479
480> i Do not use together `style-loader` and `mini-css-extract-plugin`.
481
482**webpack.config.js**
483
484```js
485const MiniCssExtractPlugin = require("mini-css-extract-plugin");
486const devMode = process.env.NODE_ENV !== "production";
487
488module.exports = {
489 module: {
490 rules: [
491 {
492 test: /\.(sa|sc|c)ss$/,
493 use: [
494 devMode ? "style-loader" : MiniCssExtractPlugin.loader,
495 "css-loader",
496 "postcss-loader",
497 "sass-loader",
498 ],
499 },
500 ],
501 },
502 plugins: [].concat(devMode ? [] : [new MiniCssExtractPlugin()]),
503};
504```
505
506### Minimal example
507
508**webpack.config.js**
509
510```js
511const MiniCssExtractPlugin = require("mini-css-extract-plugin");
512
513module.exports = {
514 plugins: [
515 new MiniCssExtractPlugin({
516 // Options similar to the same options in webpackOptions.output
517 // all options are optional
518 filename: "[name].css",
519 chunkFilename: "[id].css",
520 ignoreOrder: false, // Enable to remove warnings about conflicting order
521 }),
522 ],
523 module: {
524 rules: [
525 {
526 test: /\.css$/,
527 use: [
528 {
529 loader: MiniCssExtractPlugin.loader,
530 options: {
531 // you can specify a publicPath here
532 // by default it uses publicPath in webpackOptions.output
533 publicPath: "../",
534 },
535 },
536 "css-loader",
537 ],
538 },
539 ],
540 },
541};
542```
543
544### Named export for CSS Modules
545
546> ⚠ Names of locals are converted to `camelCase`.
547
548> ⚠ It is not allowed to use JavaScript reserved words in css class names.
549
550> ⚠ Options `esModule` and `modules.namedExport` in `css-loader` should be enabled.
551
552**styles.css**
553
554```css
555.foo-baz {
556 color: red;
557}
558.bar {
559 color: blue;
560}
561```
562
563**index.js**
564
565```js
566import { fooBaz, bar } from "./styles.css";
567
568console.log(fooBaz, bar);
569```
570
571You can enable a ES module named export using:
572
573**webpack.config.js**
574
575```js
576const MiniCssExtractPlugin = require("mini-css-extract-plugin");
577
578module.exports = {
579 plugins: [new MiniCssExtractPlugin()],
580 module: {
581 rules: [
582 {
583 test: /\.css$/,
584 use: [
585 {
586 loader: MiniCssExtractPlugin.loader,
587 },
588 {
589 loader: "css-loader",
590 options: {
591 esModule: true,
592 modules: {
593 namedExport: true,
594 localIdentName: "foo__[name]__[local]",
595 },
596 },
597 },
598 ],
599 },
600 ],
601 },
602};
603```
604
605### The `publicPath` option as function
606
607**webpack.config.js**
608
609```js
610const MiniCssExtractPlugin = require("mini-css-extract-plugin");
611
612module.exports = {
613 plugins: [
614 new MiniCssExtractPlugin({
615 // Options similar to the same options in webpackOptions.output
616 // both options are optional
617 filename: "[name].css",
618 chunkFilename: "[id].css",
619 }),
620 ],
621 module: {
622 rules: [
623 {
624 test: /\.css$/,
625 use: [
626 {
627 loader: MiniCssExtractPlugin.loader,
628 options: {
629 publicPath: (resourcePath, context) => {
630 // publicPath is the relative path of the resource to the context
631 // e.g. for ./css/admin/main.css the publicPath will be ../../
632 // while for ./css/main.css the publicPath will be ../
633 return path.relative(path.dirname(resourcePath), context) + "/";
634 },
635 },
636 },
637 "css-loader",
638 ],
639 },
640 ],
641 },
642};
643```
644
645### Advanced configuration example
646
647This plugin should not be used with `style-loader` in the loaders chain.
648
649Here is an example to have both HMR in `development` and your styles extracted in a file for `production` builds.
650
651(Loaders options left out for clarity, adapt accordingly to your needs.)
652
653You should not use `HotModuleReplacementPlugin` plugin if you are using a `webpack-dev-server`.
654`webpack-dev-server` enables / disables HMR using `hot` option.
655
656**webpack.config.js**
657
658```js
659const webpack = require("webpack");
660const MiniCssExtractPlugin = require("mini-css-extract-plugin");
661const devMode = process.env.NODE_ENV !== "production";
662
663const plugins = [
664 new MiniCssExtractPlugin({
665 // Options similar to the same options in webpackOptions.output
666 // both options are optional
667 filename: devMode ? "[name].css" : "[name].[contenthash].css",
668 chunkFilename: devMode ? "[id].css" : "[id].[contenthash].css",
669 }),
670];
671if (devMode) {
672 // only enable hot in development
673 plugins.push(new webpack.HotModuleReplacementPlugin());
674}
675
676module.exports = {
677 plugins,
678 module: {
679 rules: [
680 {
681 test: /\.(sa|sc|c)ss$/,
682 use: [
683 MiniCssExtractPlugin.loader,
684 "css-loader",
685 "postcss-loader",
686 "sass-loader",
687 ],
688 },
689 ],
690 },
691};
692```
693
694### Hot Module Reloading (HMR)
695
696Note: HMR is automatically supported in webpack 5. No need to configure it. Skip the following:
697
698The `mini-css-extract-plugin` supports hot reloading of actual css files in development.
699Some options are provided to enable HMR of both standard stylesheets and locally scoped CSS or CSS modules.
700Below is an example configuration of mini-css for HMR use with CSS modules.
701
702You should not use `HotModuleReplacementPlugin` plugin if you are using a `webpack-dev-server`.
703`webpack-dev-server` enables / disables HMR using `hot` option.
704
705**webpack.config.js**
706
707```js
708const webpack = require("webpack");
709const MiniCssExtractPlugin = require("mini-css-extract-plugin");
710
711const plugins = [
712 new MiniCssExtractPlugin({
713 // Options similar to the same options in webpackOptions.output
714 // both options are optional
715 filename: devMode ? "[name].css" : "[name].[contenthash].css",
716 chunkFilename: devMode ? "[id].css" : "[id].[contenthash].css",
717 }),
718];
719if (devMode) {
720 // only enable hot in development
721 plugins.push(new webpack.HotModuleReplacementPlugin());
722}
723
724module.exports = {
725 plugins,
726 module: {
727 rules: [
728 {
729 test: /\.css$/,
730 use: [
731 {
732 loader: MiniCssExtractPlugin.loader,
733 options: {},
734 },
735 "css-loader",
736 ],
737 },
738 ],
739 },
740};
741```
742
743### Minimizing For Production
744
745To minify the output, use a plugin like [css-minimizer-webpack-plugin](https://github.com/webpack-contrib/css-minimizer-webpack-plugin).
746
747**webpack.config.js**
748
749```js
750const MiniCssExtractPlugin = require("mini-css-extract-plugin");
751const CssMinimizerPlugin = require("css-minimizer-webpack-plugin");
752
753module.exports = {
754 plugins: [
755 new MiniCssExtractPlugin({
756 filename: "[name].css",
757 chunkFilename: "[id].css",
758 }),
759 ],
760 module: {
761 rules: [
762 {
763 test: /\.css$/,
764 use: [MiniCssExtractPlugin.loader, "css-loader"],
765 },
766 ],
767 },
768 optimization: {
769 minimizer: [
770 // For webpack@5 you can use the `...` syntax to extend existing minimizers (i.e. `terser-webpack-plugin`), uncomment the next line
771 // `...`,
772 new CssMinimizerPlugin(),
773 ],
774 },
775};
776```
777
778This will enable CSS optimization only in production mode. If you want to run it also in development set the `optimization.minimize` option to true.
779
780### Using preloaded or inlined CSS
781
782The runtime code detects already added CSS via `<link>` or `<style>` tag.
783This can be useful when injecting CSS on server-side for Server-Side-Rendering.
784The `href` of the `<link>` tag has to match the URL that will be used for loading the CSS chunk.
785The `data-href` attribute can be used for `<link>` and `<style>` too.
786When inlining CSS `data-href` must be used.
787
788### Extracting all CSS in a single file
789
790The CSS can be extracted in one CSS file using `optimization.splitChunks.cacheGroups`.
791
792**webpack.config.js**
793
794```js
795const MiniCssExtractPlugin = require("mini-css-extract-plugin");
796
797module.exports = {
798 optimization: {
799 splitChunks: {
800 cacheGroups: {
801 styles: {
802 name: "styles",
803 type: "css/mini-extract",
804 chunks: "all",
805 enforce: true,
806 },
807 },
808 },
809 },
810 plugins: [
811 new MiniCssExtractPlugin({
812 filename: "[name].css",
813 }),
814 ],
815 module: {
816 rules: [
817 {
818 test: /\.css$/,
819 use: [MiniCssExtractPlugin.loader, "css-loader"],
820 },
821 ],
822 },
823};
824```
825
826Note that `type` should be used instead of `test` in Webpack 5, or else an extra `.js` file can be generated besides the `.css` file. This is because `test` doesn't know which modules should be dropped (in this case, it won't detect that `.js` should be dropped).
827
828### Extracting CSS based on entry
829
830You may also extract the CSS based on the webpack entry name.
831This is especially useful if you import routes dynamically but want to keep your CSS bundled according to entry.
832This also prevents the CSS duplication issue one had with the ExtractTextPlugin.
833
834```js
835const path = require("path");
836const MiniCssExtractPlugin = require("mini-css-extract-plugin");
837
838module.exports = {
839 entry: {
840 foo: path.resolve(__dirname, "src/foo"),
841 bar: path.resolve(__dirname, "src/bar"),
842 },
843 optimization: {
844 splitChunks: {
845 cacheGroups: {
846 fooStyles: {
847 type: "css/mini-extract",
848 name: "styles_foo",
849 chunks: (chunk) => {
850 return chunk.name === "foo";
851 },
852 enforce: true,
853 },
854 barStyles: {
855 type: "css/mini-extract",
856 name: "styles_bar",
857 chunks: (chunk) => {
858 return chunk.name === "bar";
859 },
860 enforce: true,
861 },
862 },
863 },
864 },
865 plugins: [
866 new MiniCssExtractPlugin({
867 filename: "[name].css",
868 }),
869 ],
870 module: {
871 rules: [
872 {
873 test: /\.css$/,
874 use: [MiniCssExtractPlugin.loader, "css-loader"],
875 },
876 ],
877 },
878};
879```
880
881### Filename Option as function
882
883With the `filename` option you can use chunk data to customize the filename.
884This is particularly useful when dealing with multiple entry points and wanting to get more control out of the filename for a given entry point/chunk.
885In the example below, we'll use `filename` to output the generated css into a different directory.
886
887**webpack.config.js**
888
889```js
890const MiniCssExtractPlugin = require("mini-css-extract-plugin");
891
892module.exports = {
893 plugins: [
894 new MiniCssExtractPlugin({
895 filename: ({ chunk }) => `${chunk.name.replace("/js/", "/css/")}.css`,
896 }),
897 ],
898 module: {
899 rules: [
900 {
901 test: /\.css$/,
902 use: [MiniCssExtractPlugin.loader, "css-loader"],
903 },
904 ],
905 },
906};
907```
908
909### Long Term Caching
910
911For long term caching use `filename: "[contenthash].css"`. Optionally add `[name]`.
912
913**webpack.config.js**
914
915```js
916const MiniCssExtractPlugin = require("mini-css-extract-plugin");
917
918module.exports = {
919 plugins: [
920 new MiniCssExtractPlugin({
921 filename: "[name].[contenthash].css",
922 chunkFilename: "[id].[contenthash].css",
923 }),
924 ],
925 module: {
926 rules: [
927 {
928 test: /\.css$/,
929 use: [MiniCssExtractPlugin.loader, "css-loader"],
930 },
931 ],
932 },
933};
934```
935
936### Remove Order Warnings
937
938For projects where css ordering has been mitigated through consistent use of scoping or naming conventions, the css order warnings can be disabled by setting the ignoreOrder flag to true for the plugin.
939
940**webpack.config.js**
941
942```js
943const MiniCssExtractPlugin = require("mini-css-extract-plugin");
944
945module.exports = {
946 plugins: [
947 new MiniCssExtractPlugin({
948 ignoreOrder: true,
949 }),
950 ],
951 module: {
952 rules: [
953 {
954 test: /\.css$/i,
955 use: [MiniCssExtractPlugin.loader, "css-loader"],
956 },
957 ],
958 },
959};
960```
961
962### Multiple Themes
963
964**webpack.config.js**
965
966```js
967const MiniCssExtractPlugin = require("mini-css-extract-plugin");
968
969module.exports = {
970 entry: "./src/index.js",
971 module: {
972 rules: [
973 {
974 test: /\.s[ac]ss$/i,
975 oneOf: [
976 {
977 resourceQuery: "?dark",
978 use: [
979 Self.loader,
980 "css-loader",
981 {
982 loader: "sass-loader",
983 options: {
984 additionalData: `@use 'dark-theme/vars' as vars;`,
985 },
986 },
987 ],
988 },
989 {
990 use: [
991 Self.loader,
992 "css-loader",
993 {
994 loader: "sass-loader",
995 options: {
996 additionalData: `@use 'light-theme/vars' as vars;`,
997 },
998 },
999 ],
1000 },
1001 ],
1002 },
1003 ],
1004 },
1005 plugins: [
1006 new Self({
1007 filename: "[name].css",
1008 attributes: {
1009 id: "theme",
1010 },
1011 }),
1012 ],
1013};
1014```
1015
1016**src/index.js**
1017
1018```js
1019import "./style.scss";
1020
1021let theme = "light";
1022const themes = {};
1023
1024themes[theme] = document.querySelector("#theme");
1025
1026async function loadTheme(newTheme) {
1027 // eslint-disable-next-line no-console
1028 console.log(`CHANGE THEME - ${newTheme}`);
1029
1030 const themeElement = document.querySelector("#theme");
1031
1032 if (themeElement) {
1033 themeElement.remove();
1034 }
1035
1036 if (themes[newTheme]) {
1037 // eslint-disable-next-line no-console
1038 console.log(`THEME ALREADY LOADED - ${newTheme}`);
1039
1040 document.head.appendChild(themes[newTheme]);
1041
1042 return;
1043 }
1044
1045 if (newTheme === "dark") {
1046 // eslint-disable-next-line no-console
1047 console.log(`LOADING THEME - ${newTheme}`);
1048
1049 import(/* webpackChunkName: "dark" */ "./style.scss?dark").then(() => {
1050 themes[newTheme] = document.querySelector("#theme");
1051
1052 // eslint-disable-next-line no-console
1053 console.log(`LOADED - ${newTheme}`);
1054 });
1055 }
1056}
1057
1058document.onclick = () => {
1059 if (theme === "light") {
1060 theme = "dark";
1061 } else {
1062 theme = "light";
1063 }
1064
1065 loadTheme(theme);
1066};
1067```
1068
1069**src/dark-theme/\_vars.scss**
1070
1071```scss
1072$background: black;
1073```
1074
1075**src/light-theme/\_vars.scss**
1076
1077```scss
1078$background: white;
1079```
1080
1081**src/styles.scss**
1082
1083```scss
1084body {
1085 background-color: vars.$background;
1086}
1087```
1088
1089**public/index.html**
1090
1091```html
1092<!DOCTYPE html>
1093<html lang="en">
1094 <head>
1095 <meta charset="UTF-8" />
1096 <meta name="viewport" content="width=device-width, initial-scale=1" />
1097 <title>Document</title>
1098 <link id="theme" rel="stylesheet" type="text/css" href="./main.css" />
1099 </head>
1100 <body>
1101 <script src="./main.js"></script>
1102 </body>
1103</html>
1104```
1105
1106### Media Query Plugin
1107
1108If you'd like to extract the media queries from the extracted CSS (so mobile users don't need to load desktop or tablet specific CSS anymore) you should use one of the following plugins:
1109
1110- [Media Query Plugin](https://github.com/SassNinja/media-query-plugin)
1111- [Media Query Splitting Plugin](https://github.com/mike-diamond/media-query-splitting-plugin)
1112
1113## Contributing
1114
1115Please take a moment to read our contributing guidelines if you haven't yet done so.
1116
1117[CONTRIBUTING](./.github/CONTRIBUTING.md)
1118
1119## License
1120
1121[MIT](./LICENSE)
1122
1123[npm]: https://img.shields.io/npm/v/mini-css-extract-plugin.svg
1124[npm-url]: https://npmjs.com/package/mini-css-extract-plugin
1125[node]: https://img.shields.io/node/v/mini-css-extract-plugin.svg
1126[node-url]: https://nodejs.org
1127[deps]: https://david-dm.org/webpack-contrib/mini-css-extract-plugin.svg
1128[deps-url]: https://david-dm.org/webpack-contrib/mini-css-extract-plugin
1129[tests]: https://github.com/webpack-contrib/mini-css-extract-plugin/workflows/mini-css-extract-plugin/badge.svg
1130[tests-url]: https://github.com/webpack-contrib/mini-css-extract-plugin/actions
1131[cover]: https://codecov.io/gh/webpack-contrib/mini-css-extract-plugin/branch/master/graph/badge.svg
1132[cover-url]: https://codecov.io/gh/webpack-contrib/mini-css-extract-plugin
1133[chat]: https://badges.gitter.im/webpack/webpack.svg
1134[chat-url]: https://gitter.im/webpack/webpack
1135[size]: https://packagephobia.now.sh/badge?p=mini-css-extract-plugin
1136[size-url]: https://packagephobia.now.sh/result?p=mini-css-extract-plugin