UNPKG

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