UNPKG

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