UNPKG

29.3 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> **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
411#### `publicPath`
412
413Type:
414
415```ts
416type publicPath =
417 | string
418 | ((resourcePath: string, rootContext: string) => string);
419```
420
421Default: the `publicPath` in `webpackOptions.output`
422
423Specifies a custom public path for the external resources like images, files, etc inside `CSS`.
424Works like [`output.publicPath`](https://webpack.js.org/configuration/output/#outputpublicpath)
425
426##### `string`
427
428**webpack.config.js**
429
430```js
431const MiniCssExtractPlugin = require("mini-css-extract-plugin");
432
433module.exports = {
434 plugins: [
435 new MiniCssExtractPlugin({
436 // Options similar to the same options in webpackOptions.output
437 // both options are optional
438 filename: "[name].css",
439 chunkFilename: "[id].css",
440 }),
441 ],
442 module: {
443 rules: [
444 {
445 test: /\.css$/,
446 use: [
447 {
448 loader: MiniCssExtractPlugin.loader,
449 options: {
450 publicPath: "/public/path/to/",
451 },
452 },
453 "css-loader",
454 ],
455 },
456 ],
457 },
458};
459```
460
461##### `function`
462
463**webpack.config.js**
464
465```js
466const MiniCssExtractPlugin = require("mini-css-extract-plugin");
467
468module.exports = {
469 plugins: [
470 new MiniCssExtractPlugin({
471 // Options similar to the same options in webpackOptions.output
472 // both options are optional
473 filename: "[name].css",
474 chunkFilename: "[id].css",
475 }),
476 ],
477 module: {
478 rules: [
479 {
480 test: /\.css$/,
481 use: [
482 {
483 loader: MiniCssExtractPlugin.loader,
484 options: {
485 publicPath: (resourcePath, context) => {
486 return path.relative(path.dirname(resourcePath), context) + "/";
487 },
488 },
489 },
490 "css-loader",
491 ],
492 },
493 ],
494 },
495};
496```
497
498#### `emit`
499
500Type:
501
502```ts
503type emit = boolean;
504```
505
506Default: `true`
507
508If true, emits a file (writes a file to the filesystem). If false, the plugin will extract the CSS but **will not** emit the file.
509It is often useful to disable this option for server-side packages.
510
511#### `esModule`
512
513Type:
514
515```ts
516type esModule = boolean;
517```
518
519Default: `true`
520
521By default, `mini-css-extract-plugin` generates JS modules that use the ES modules syntax.
522There 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/).
523
524You can enable a CommonJS syntax using:
525
526**webpack.config.js**
527
528```js
529const MiniCssExtractPlugin = require("mini-css-extract-plugin");
530
531module.exports = {
532 plugins: [new MiniCssExtractPlugin()],
533 module: {
534 rules: [
535 {
536 test: /\.css$/i,
537 use: [
538 {
539 loader: MiniCssExtractPlugin.loader,
540 options: {
541 esModule: false,
542 },
543 },
544 "css-loader",
545 ],
546 },
547 ],
548 },
549};
550```
551
552## Examples
553
554### Recommended
555
556For `production` builds it's recommended to extract the CSS from your bundle being able to use parallel loading of CSS/JS resources later on.
557This can be achieved by using the `mini-css-extract-plugin`, because it creates separate css files.
558For `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.
559
560> Do not use `style-loader` and `mini-css-extract-plugin` together.
561
562**webpack.config.js**
563
564```js
565const MiniCssExtractPlugin = require("mini-css-extract-plugin");
566const devMode = process.env.NODE_ENV !== "production";
567
568module.exports = {
569 module: {
570 rules: [
571 {
572 test: /\.(sa|sc|c)ss$/,
573 use: [
574 devMode ? "style-loader" : MiniCssExtractPlugin.loader,
575 "css-loader",
576 "postcss-loader",
577 "sass-loader",
578 ],
579 },
580 ],
581 },
582 plugins: [].concat(devMode ? [] : [new MiniCssExtractPlugin()]),
583};
584```
585
586### Minimal example
587
588**webpack.config.js**
589
590```js
591const MiniCssExtractPlugin = require("mini-css-extract-plugin");
592
593module.exports = {
594 plugins: [
595 new MiniCssExtractPlugin({
596 // Options similar to the same options in webpackOptions.output
597 // all options are optional
598 filename: "[name].css",
599 chunkFilename: "[id].css",
600 ignoreOrder: false, // Enable to remove warnings about conflicting order
601 }),
602 ],
603 module: {
604 rules: [
605 {
606 test: /\.css$/,
607 use: [
608 {
609 loader: MiniCssExtractPlugin.loader,
610 options: {
611 // you can specify a publicPath here
612 // by default it uses publicPath in webpackOptions.output
613 publicPath: "../",
614 },
615 },
616 "css-loader",
617 ],
618 },
619 ],
620 },
621};
622```
623
624### Named export for CSS Modules
625
626> ⚠ Names of locals are converted to `camelCase`.
627
628> ⚠ It is not allowed to use JavaScript reserved words in css class names.
629
630> ⚠ Options `esModule` and `modules.namedExport` in `css-loader` should be enabled.
631
632**styles.css**
633
634```css
635.foo-baz {
636 color: red;
637}
638.bar {
639 color: blue;
640}
641```
642
643**index.js**
644
645```js
646import { fooBaz, bar } from "./styles.css";
647
648console.log(fooBaz, bar);
649```
650
651You can enable a ES module named export using:
652
653**webpack.config.js**
654
655```js
656const MiniCssExtractPlugin = require("mini-css-extract-plugin");
657
658module.exports = {
659 plugins: [new MiniCssExtractPlugin()],
660 module: {
661 rules: [
662 {
663 test: /\.css$/,
664 use: [
665 {
666 loader: MiniCssExtractPlugin.loader,
667 },
668 {
669 loader: "css-loader",
670 options: {
671 esModule: true,
672 modules: {
673 namedExport: true,
674 localIdentName: "foo__[name]__[local]",
675 },
676 },
677 },
678 ],
679 },
680 ],
681 },
682};
683```
684
685### The `publicPath` option as function
686
687**webpack.config.js**
688
689```js
690const MiniCssExtractPlugin = require("mini-css-extract-plugin");
691
692module.exports = {
693 plugins: [
694 new MiniCssExtractPlugin({
695 // Options similar to the same options in webpackOptions.output
696 // both options are optional
697 filename: "[name].css",
698 chunkFilename: "[id].css",
699 }),
700 ],
701 module: {
702 rules: [
703 {
704 test: /\.css$/,
705 use: [
706 {
707 loader: MiniCssExtractPlugin.loader,
708 options: {
709 publicPath: (resourcePath, context) => {
710 // publicPath is the relative path of the resource to the context
711 // e.g. for ./css/admin/main.css the publicPath will be ../../
712 // while for ./css/main.css the publicPath will be ../
713 return path.relative(path.dirname(resourcePath), context) + "/";
714 },
715 },
716 },
717 "css-loader",
718 ],
719 },
720 ],
721 },
722};
723```
724
725### Advanced configuration example
726
727This plugin should not be used with `style-loader` in the loaders chain.
728
729Here is an example to have both HMR in `development` and your styles extracted in a file for `production` builds.
730
731(Loaders options left out for clarity, adapt accordingly to your needs.)
732
733You should not use `HotModuleReplacementPlugin` plugin if you are using a `webpack-dev-server`.
734`webpack-dev-server` enables / disables HMR using `hot` option.
735
736**webpack.config.js**
737
738```js
739const webpack = require("webpack");
740const MiniCssExtractPlugin = require("mini-css-extract-plugin");
741const devMode = process.env.NODE_ENV !== "production";
742
743const plugins = [
744 new MiniCssExtractPlugin({
745 // Options similar to the same options in webpackOptions.output
746 // both options are optional
747 filename: devMode ? "[name].css" : "[name].[contenthash].css",
748 chunkFilename: devMode ? "[id].css" : "[id].[contenthash].css",
749 }),
750];
751if (devMode) {
752 // only enable hot in development
753 plugins.push(new webpack.HotModuleReplacementPlugin());
754}
755
756module.exports = {
757 plugins,
758 module: {
759 rules: [
760 {
761 test: /\.(sa|sc|c)ss$/,
762 use: [
763 MiniCssExtractPlugin.loader,
764 "css-loader",
765 "postcss-loader",
766 "sass-loader",
767 ],
768 },
769 ],
770 },
771};
772```
773
774### Hot Module Reloading (HMR)
775
776> **Note**
777>
778> HMR is automatically supported in webpack 5. No need to configure it. Skip the following:
779
780The `mini-css-extract-plugin` supports hot reloading of actual css files in development.
781Some options are provided to enable HMR of both standard stylesheets and locally scoped CSS or CSS modules.
782Below is an example configuration of mini-css for HMR use with CSS modules.
783
784You should not use `HotModuleReplacementPlugin` plugin if you are using a `webpack-dev-server`.
785`webpack-dev-server` enables / disables HMR using `hot` option.
786
787**webpack.config.js**
788
789```js
790const webpack = require("webpack");
791const MiniCssExtractPlugin = require("mini-css-extract-plugin");
792
793const plugins = [
794 new MiniCssExtractPlugin({
795 // Options similar to the same options in webpackOptions.output
796 // both options are optional
797 filename: devMode ? "[name].css" : "[name].[contenthash].css",
798 chunkFilename: devMode ? "[id].css" : "[id].[contenthash].css",
799 }),
800];
801if (devMode) {
802 // only enable hot in development
803 plugins.push(new webpack.HotModuleReplacementPlugin());
804}
805
806module.exports = {
807 plugins,
808 module: {
809 rules: [
810 {
811 test: /\.css$/,
812 use: [
813 {
814 loader: MiniCssExtractPlugin.loader,
815 options: {},
816 },
817 "css-loader",
818 ],
819 },
820 ],
821 },
822};
823```
824
825### Minimizing For Production
826
827To minify the output, use a plugin like [css-minimizer-webpack-plugin](https://github.com/webpack-contrib/css-minimizer-webpack-plugin).
828
829**webpack.config.js**
830
831```js
832const MiniCssExtractPlugin = require("mini-css-extract-plugin");
833const CssMinimizerPlugin = require("css-minimizer-webpack-plugin");
834
835module.exports = {
836 plugins: [
837 new MiniCssExtractPlugin({
838 filename: "[name].css",
839 chunkFilename: "[id].css",
840 }),
841 ],
842 module: {
843 rules: [
844 {
845 test: /\.css$/,
846 use: [MiniCssExtractPlugin.loader, "css-loader"],
847 },
848 ],
849 },
850 optimization: {
851 minimizer: [
852 // For webpack@5 you can use the `...` syntax to extend existing minimizers (i.e. `terser-webpack-plugin`), uncomment the next line
853 // `...`,
854 new CssMinimizerPlugin(),
855 ],
856 },
857};
858```
859
860This will enable CSS optimization only in production mode. If you want to run it also in development set the `optimization.minimize` option to true.
861
862### Using preloaded or inlined CSS
863
864The runtime code detects already added CSS via `<link>` or `<style>` tag.
865This can be useful when injecting CSS on server-side for Server-Side-Rendering.
866The `href` of the `<link>` tag has to match the URL that will be used for loading the CSS chunk.
867The `data-href` attribute can be used for `<link>` and `<style>` too.
868When inlining CSS `data-href` must be used.
869
870### Extracting all CSS in a single file
871
872The CSS can be extracted in one CSS file using `optimization.splitChunks.cacheGroups`.
873
874**webpack.config.js**
875
876```js
877const MiniCssExtractPlugin = require("mini-css-extract-plugin");
878
879module.exports = {
880 optimization: {
881 splitChunks: {
882 cacheGroups: {
883 styles: {
884 name: "styles",
885 type: "css/mini-extract",
886 chunks: "all",
887 enforce: true,
888 },
889 },
890 },
891 },
892 plugins: [
893 new MiniCssExtractPlugin({
894 filename: "[name].css",
895 }),
896 ],
897 module: {
898 rules: [
899 {
900 test: /\.css$/,
901 use: [MiniCssExtractPlugin.loader, "css-loader"],
902 },
903 ],
904 },
905};
906```
907
908Note 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).
909
910### Extracting CSS based on entry
911
912You may also extract the CSS based on the webpack entry name.
913This is especially useful if you import routes dynamically but want to keep your CSS bundled according to entry.
914This also prevents the CSS duplication issue one had with the ExtractTextPlugin.
915
916```js
917const path = require("path");
918const MiniCssExtractPlugin = require("mini-css-extract-plugin");
919
920module.exports = {
921 entry: {
922 foo: path.resolve(__dirname, "src/foo"),
923 bar: path.resolve(__dirname, "src/bar"),
924 },
925 optimization: {
926 splitChunks: {
927 cacheGroups: {
928 fooStyles: {
929 type: "css/mini-extract",
930 name: "styles_foo",
931 chunks: (chunk) => {
932 return chunk.name === "foo";
933 },
934 enforce: true,
935 },
936 barStyles: {
937 type: "css/mini-extract",
938 name: "styles_bar",
939 chunks: (chunk) => {
940 return chunk.name === "bar";
941 },
942 enforce: true,
943 },
944 },
945 },
946 },
947 plugins: [
948 new MiniCssExtractPlugin({
949 filename: "[name].css",
950 }),
951 ],
952 module: {
953 rules: [
954 {
955 test: /\.css$/,
956 use: [MiniCssExtractPlugin.loader, "css-loader"],
957 },
958 ],
959 },
960};
961```
962
963### Filename Option as function
964
965With the `filename` option you can use chunk data to customize the filename.
966This 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.
967In the example below, we'll use `filename` to output the generated css into a different directory.
968
969**webpack.config.js**
970
971```js
972const MiniCssExtractPlugin = require("mini-css-extract-plugin");
973
974module.exports = {
975 plugins: [
976 new MiniCssExtractPlugin({
977 filename: ({ chunk }) => `${chunk.name.replace("/js/", "/css/")}.css`,
978 }),
979 ],
980 module: {
981 rules: [
982 {
983 test: /\.css$/,
984 use: [MiniCssExtractPlugin.loader, "css-loader"],
985 },
986 ],
987 },
988};
989```
990
991### Long Term Caching
992
993For long term caching use `filename: "[contenthash].css"`. Optionally add `[name]`.
994
995**webpack.config.js**
996
997```js
998const MiniCssExtractPlugin = require("mini-css-extract-plugin");
999
1000module.exports = {
1001 plugins: [
1002 new MiniCssExtractPlugin({
1003 filename: "[name].[contenthash].css",
1004 chunkFilename: "[id].[contenthash].css",
1005 }),
1006 ],
1007 module: {
1008 rules: [
1009 {
1010 test: /\.css$/,
1011 use: [MiniCssExtractPlugin.loader, "css-loader"],
1012 },
1013 ],
1014 },
1015};
1016```
1017
1018### Remove Order Warnings
1019
1020For 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.
1021
1022**webpack.config.js**
1023
1024```js
1025const MiniCssExtractPlugin = require("mini-css-extract-plugin");
1026
1027module.exports = {
1028 plugins: [
1029 new MiniCssExtractPlugin({
1030 ignoreOrder: true,
1031 }),
1032 ],
1033 module: {
1034 rules: [
1035 {
1036 test: /\.css$/i,
1037 use: [MiniCssExtractPlugin.loader, "css-loader"],
1038 },
1039 ],
1040 },
1041};
1042```
1043
1044### Multiple Themes
1045
1046**webpack.config.js**
1047
1048```js
1049const MiniCssExtractPlugin = require("mini-css-extract-plugin");
1050
1051module.exports = {
1052 entry: "./src/index.js",
1053 module: {
1054 rules: [
1055 {
1056 test: /\.s[ac]ss$/i,
1057 oneOf: [
1058 {
1059 resourceQuery: "?dark",
1060 use: [
1061 MiniCssExtractPlugin.loader,
1062 "css-loader",
1063 {
1064 loader: "sass-loader",
1065 options: {
1066 additionalData: `@use 'dark-theme/vars' as vars;`,
1067 },
1068 },
1069 ],
1070 },
1071 {
1072 use: [
1073 MiniCssExtractPlugin.loader,
1074 "css-loader",
1075 {
1076 loader: "sass-loader",
1077 options: {
1078 additionalData: `@use 'light-theme/vars' as vars;`,
1079 },
1080 },
1081 ],
1082 },
1083 ],
1084 },
1085 ],
1086 },
1087 plugins: [
1088 new MiniCssExtractPlugin({
1089 filename: "[name].css",
1090 attributes: {
1091 id: "theme",
1092 },
1093 }),
1094 ],
1095};
1096```
1097
1098**src/index.js**
1099
1100```js
1101import "./style.scss";
1102
1103let theme = "light";
1104const themes = {};
1105
1106themes[theme] = document.querySelector("#theme");
1107
1108async function loadTheme(newTheme) {
1109 // eslint-disable-next-line no-console
1110 console.log(`CHANGE THEME - ${newTheme}`);
1111
1112 const themeElement = document.querySelector("#theme");
1113
1114 if (themeElement) {
1115 themeElement.remove();
1116 }
1117
1118 if (themes[newTheme]) {
1119 // eslint-disable-next-line no-console
1120 console.log(`THEME ALREADY LOADED - ${newTheme}`);
1121
1122 document.head.appendChild(themes[newTheme]);
1123
1124 return;
1125 }
1126
1127 if (newTheme === "dark") {
1128 // eslint-disable-next-line no-console
1129 console.log(`LOADING THEME - ${newTheme}`);
1130
1131 import(/* webpackChunkName: "dark" */ "./style.scss?dark").then(() => {
1132 themes[newTheme] = document.querySelector("#theme");
1133
1134 // eslint-disable-next-line no-console
1135 console.log(`LOADED - ${newTheme}`);
1136 });
1137 }
1138}
1139
1140document.onclick = () => {
1141 if (theme === "light") {
1142 theme = "dark";
1143 } else {
1144 theme = "light";
1145 }
1146
1147 loadTheme(theme);
1148};
1149```
1150
1151**src/dark-theme/\_vars.scss**
1152
1153```scss
1154$background: black;
1155```
1156
1157**src/light-theme/\_vars.scss**
1158
1159```scss
1160$background: white;
1161```
1162
1163**src/styles.scss**
1164
1165```scss
1166body {
1167 background-color: vars.$background;
1168}
1169```
1170
1171**public/index.html**
1172
1173```html
1174<!DOCTYPE html>
1175<html lang="en">
1176 <head>
1177 <meta charset="UTF-8" />
1178 <meta name="viewport" content="width=device-width, initial-scale=1" />
1179 <title>Document</title>
1180 <link id="theme" rel="stylesheet" type="text/css" href="./main.css" />
1181 </head>
1182 <body>
1183 <script src="./main.js"></script>
1184 </body>
1185</html>
1186```
1187
1188### Media Query Plugin
1189
1190If 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:
1191
1192- [Media Query Plugin](https://github.com/SassNinja/media-query-plugin)
1193- [Media Query Splitting Plugin](https://github.com/mike-diamond/media-query-splitting-plugin)
1194
1195## Contributing
1196
1197Please take a moment to read our contributing guidelines if you haven't yet done so.
1198
1199[CONTRIBUTING](./.github/CONTRIBUTING.md)
1200
1201## License
1202
1203[MIT](./LICENSE)
1204
1205[npm]: https://img.shields.io/npm/v/mini-css-extract-plugin.svg
1206[npm-url]: https://npmjs.com/package/mini-css-extract-plugin
1207[node]: https://img.shields.io/node/v/mini-css-extract-plugin.svg
1208[node-url]: https://nodejs.org
1209[tests]: https://github.com/webpack-contrib/mini-css-extract-plugin/workflows/mini-css-extract-plugin/badge.svg
1210[tests-url]: https://github.com/webpack-contrib/mini-css-extract-plugin/actions
1211[cover]: https://codecov.io/gh/webpack-contrib/mini-css-extract-plugin/branch/master/graph/badge.svg
1212[cover-url]: https://codecov.io/gh/webpack-contrib/mini-css-extract-plugin
1213[chat]: https://badges.gitter.im/webpack/webpack.svg
1214[chat-url]: https://gitter.im/webpack/webpack
1215[size]: https://packagephobia.now.sh/badge?p=mini-css-extract-plugin
1216[size-url]: https://packagephobia.now.sh/result?p=mini-css-extract-plugin