UNPKG

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