1 | <div align="center">
|
2 | <img
|
3 | width="180"
|
4 | height="180"
|
5 | hspace="10"
|
6 | alt="PostCSS Logo"
|
7 | src="https://api.postcss.org/logo.svg">
|
8 | <a href="https://github.com/webpack/webpack">
|
9 | <img
|
10 | width="200"
|
11 | height="200"
|
12 | hspace="10"
|
13 | src="https://cdn.rawgit.com/webpack/media/e7485eb2/logo/icon.svg">
|
14 | </a>
|
15 | <div align="center">
|
16 | <a href="https://evilmartians.com/?utm_source=postcss">
|
17 | <img
|
18 | src="https://evilmartians.com/badges/sponsored-by-evil-martians.svg"
|
19 | alt="Sponsored by Evil Martians"
|
20 | width="236"
|
21 | height="54"
|
22 | vspace="10">
|
23 | </a>
|
24 | </div>
|
25 | </div>
|
26 |
|
27 | [![npm][npm]][npm-url]
|
28 | [![node][node]][node-url]
|
29 | [![tests][tests]][tests-url]
|
30 | [![coverage][cover]][cover-url]
|
31 | [![size][size]][size-url]
|
32 |
|
33 | Webpack discussion: [![discussion][discussion]][discussion-url]
|
34 |
|
35 | PostCSS chat: [![chat-postcss][chat-postcss]][chat-postcss-url]
|
36 |
|
37 | # postcss-loader
|
38 |
|
39 | Loader to process CSS with [`PostCSS`](https://github.com/postcss/postcss).
|
40 |
|
41 | ## Getting Started
|
42 |
|
43 | You need webpack v5 to use the latest version. For Webpack v4, you have to install postcss-loader v4.
|
44 |
|
45 | To begin, you'll need to install `postcss-loader` and `postcss`:
|
46 |
|
47 | ```console
|
48 | npm install --save-dev postcss-loader postcss
|
49 | ```
|
50 |
|
51 | or
|
52 |
|
53 | ```console
|
54 | yarn add -D postcss-loader postcss
|
55 | ```
|
56 |
|
57 | or
|
58 |
|
59 | ```console
|
60 | pnpm add -D postcss-loader postcss
|
61 | ```
|
62 |
|
63 | Then add the plugin to your `webpack` config. For example:
|
64 |
|
65 | > In the following configuration the plugin [`postcss-preset-env`](https://github.com/csstools/postcss-preset-env) is used, which is not installed by default.
|
66 |
|
67 | **file.js**
|
68 |
|
69 | ```js
|
70 | import css from "file.css";
|
71 | ```
|
72 |
|
73 | **webpack.config.js**
|
74 |
|
75 | ```js
|
76 | module.exports = {
|
77 | module: {
|
78 | rules: [
|
79 | {
|
80 | test: /\.css$/i,
|
81 | use: [
|
82 | "style-loader",
|
83 | "css-loader",
|
84 | {
|
85 | loader: "postcss-loader",
|
86 | options: {
|
87 | postcssOptions: {
|
88 | plugins: [
|
89 | [
|
90 | "postcss-preset-env",
|
91 | {
|
92 | // Options
|
93 | },
|
94 | ],
|
95 | ],
|
96 | },
|
97 | },
|
98 | },
|
99 | ],
|
100 | },
|
101 | ],
|
102 | },
|
103 | };
|
104 | ```
|
105 |
|
106 | Alternative use with [config files](#config):
|
107 |
|
108 | **postcss.config.js**
|
109 |
|
110 | ```js
|
111 | module.exports = {
|
112 | plugins: [
|
113 | [
|
114 | "postcss-preset-env",
|
115 | {
|
116 | // Options
|
117 | },
|
118 | ],
|
119 | ],
|
120 | };
|
121 | ```
|
122 |
|
123 | The loader **automatically** searches for configuration files.
|
124 |
|
125 | **webpack.config.js**
|
126 |
|
127 | ```js
|
128 | module.exports = {
|
129 | module: {
|
130 | rules: [
|
131 | {
|
132 | test: /\.css$/i,
|
133 | use: ["style-loader", "css-loader", "postcss-loader"],
|
134 | },
|
135 | ],
|
136 | },
|
137 | };
|
138 | ```
|
139 |
|
140 | And run `webpack` via your preferred method.
|
141 |
|
142 | ## Options
|
143 |
|
144 | - [`execute`](#execute)
|
145 | - [`postcssOptions`](#postcssOptions)
|
146 | - [`sourceMap`](#sourcemap)
|
147 | - [`implementation`](#implementation)
|
148 |
|
149 | ### `execute`
|
150 |
|
151 | Type:
|
152 |
|
153 | ```ts
|
154 | type execute = boolean;
|
155 | ```
|
156 |
|
157 | Default: `undefined`
|
158 |
|
159 | Enable PostCSS Parser support in `CSS-in-JS`.
|
160 | If you use JS styles the [`postcss-js`](https://github.com/postcss/postcss-js) parser, add the `execute` option.
|
161 |
|
162 | **webpack.config.js**
|
163 |
|
164 | ```js
|
165 | module.exports = {
|
166 | module: {
|
167 | rules: [
|
168 | {
|
169 | test: /\.style.js$/,
|
170 | use: [
|
171 | "style-loader",
|
172 | {
|
173 | loader: "css-loader",
|
174 | },
|
175 | {
|
176 | loader: "postcss-loader",
|
177 | options: {
|
178 | postcssOptions: {
|
179 | parser: "postcss-js",
|
180 | },
|
181 | execute: true,
|
182 | },
|
183 | },
|
184 | ],
|
185 | },
|
186 | ],
|
187 | },
|
188 | };
|
189 | ```
|
190 |
|
191 | ### `postcssOptions`
|
192 |
|
193 | See the file [`./src/config.d.ts`](./src/config.d.ts).
|
194 |
|
195 | Type:
|
196 |
|
197 | ```ts
|
198 | import type { Config as PostCSSConfig } from "postcss-load-config";
|
199 | import type { LoaderContext } from "webpack";
|
200 |
|
201 | type PostCSSLoaderContext = LoaderContext<PostCSSConfig>;
|
202 |
|
203 | interface PostCSSLoaderAPI {
|
204 | mode: PostCSSLoaderContext["mode"];
|
205 | file: PostCSSLoaderContext["resourcePath"];
|
206 | webpackLoaderContext: PostCSSLoaderContext;
|
207 | env: PostCSSLoaderContext["mode"];
|
208 | options: PostCSSConfig;
|
209 | }
|
210 |
|
211 | export type PostCSSLoaderOptions =
|
212 | | PostCSSConfig
|
213 | | ((api: PostCSSLoaderAPI) => PostCSSConfig);
|
214 | ```
|
215 |
|
216 | Default: `undefined`
|
217 |
|
218 | Allows to set [`PostCSS options`](https://postcss.org/api/#processoptions) and plugins.
|
219 |
|
220 | All `PostCSS` options are supported.
|
221 | There is the special `config` option for config files. How it works and how it can be configured is described below.
|
222 |
|
223 | We recommend do not specify `from`, `to` and `map` options, because this can lead to wrong path in source maps.
|
224 | If you need source maps please use the [`sourcemap`](#sourcemap) option.
|
225 |
|
226 | For large projects, to optimize performance of the loader, it is better to provide `postcssOptions` in loader
|
227 | config and specify `config: false`. This approach removes the need to lookup and load external config files multiple
|
228 | times during compilation.
|
229 |
|
230 | #### `object`
|
231 |
|
232 | Setup `plugins`:
|
233 |
|
234 | **webpack.config.js** (**recommended**)
|
235 |
|
236 | ```js
|
237 | const myOtherPostcssPlugin = require("postcss-my-plugin");
|
238 |
|
239 | module.exports = {
|
240 | module: {
|
241 | rules: [
|
242 | {
|
243 | test: /\.sss$/i,
|
244 | loader: "postcss-loader",
|
245 | options: {
|
246 | postcssOptions: {
|
247 | plugins: [
|
248 | "postcss-import",
|
249 | ["postcss-short", { prefix: "x" }],
|
250 | require.resolve("my-postcss-plugin"),
|
251 | myOtherPostcssPlugin({ myOption: true }),
|
252 | // Deprecated and will be removed in the next major release
|
253 | { "postcss-nested": { preserveEmpty: true } },
|
254 | ],
|
255 | },
|
256 | },
|
257 | },
|
258 | ],
|
259 | },
|
260 | };
|
261 | ```
|
262 |
|
263 | **webpack.config.js** (**deprecated**, will be removed in the next major release)
|
264 |
|
265 | ```js
|
266 | module.exports = {
|
267 | module: {
|
268 | rules: [
|
269 | {
|
270 | test: /\.sss$/i,
|
271 | loader: "postcss-loader",
|
272 | options: {
|
273 | postcssOptions: {
|
274 | plugins: {
|
275 | "postcss-import": {},
|
276 | "postcss-short": { prefix: "x" },
|
277 | },
|
278 | },
|
279 | },
|
280 | },
|
281 | ],
|
282 | },
|
283 | };
|
284 | ```
|
285 |
|
286 | Setup `syntax`:
|
287 |
|
288 | **webpack.config.js**
|
289 |
|
290 | ```js
|
291 | module.exports = {
|
292 | module: {
|
293 | rules: [
|
294 | {
|
295 | test: /\.sss$/i,
|
296 | loader: "postcss-loader",
|
297 | options: {
|
298 | postcssOptions: {
|
299 | // Can be `string`
|
300 | syntax: "sugarss",
|
301 | // Can be `object`
|
302 | syntax: require("sugarss"),
|
303 | },
|
304 | },
|
305 | },
|
306 | ],
|
307 | },
|
308 | };
|
309 | ```
|
310 |
|
311 | Setup `parser`:
|
312 |
|
313 | **webpack.config.js**
|
314 |
|
315 | ```js
|
316 | module.exports = {
|
317 | module: {
|
318 | rules: [
|
319 | {
|
320 | test: /\.sss$/i,
|
321 | loader: "postcss-loader",
|
322 | options: {
|
323 | postcssOptions: {
|
324 | // Can be `string`
|
325 | parser: "sugarss",
|
326 | // Can be `object`
|
327 | parser: require("sugarss"),
|
328 | // Can be `function`
|
329 | parser: require("sugarss").parse,
|
330 | },
|
331 | },
|
332 | },
|
333 | ],
|
334 | },
|
335 | };
|
336 | ```
|
337 |
|
338 | Setup `stringifier`:
|
339 |
|
340 | **webpack.config.js**
|
341 |
|
342 | ```js
|
343 | const Midas = require("midas");
|
344 | const midas = new Midas();
|
345 |
|
346 | module.exports = {
|
347 | module: {
|
348 | rules: [
|
349 | {
|
350 | test: /\.sss$/i,
|
351 | loader: "postcss-loader",
|
352 | options: {
|
353 | postcssOptions: {
|
354 | // Can be `string`
|
355 | stringifier: "sugarss",
|
356 | // Can be `object`
|
357 | stringifier: require("sugarss"),
|
358 | // Can be `function`
|
359 | stringifier: midas.stringifier,
|
360 | },
|
361 | },
|
362 | },
|
363 | ],
|
364 | },
|
365 | };
|
366 | ```
|
367 |
|
368 | #### `function`
|
369 |
|
370 | **webpack.config.js**
|
371 |
|
372 | ```js
|
373 | module.exports = {
|
374 | module: {
|
375 | rules: [
|
376 | {
|
377 | test: /\.(css|sss)$/i,
|
378 | loader: "postcss-loader",
|
379 | options: {
|
380 | postcssOptions: (loaderContext) => {
|
381 | if (/\.sss$/.test(loaderContext.resourcePath)) {
|
382 | return {
|
383 | parser: "sugarss",
|
384 | plugins: [
|
385 | ["postcss-short", { prefix: "x" }],
|
386 | "postcss-preset-env",
|
387 | ],
|
388 | };
|
389 | }
|
390 |
|
391 | return {
|
392 | plugins: [
|
393 | ["postcss-short", { prefix: "x" }],
|
394 | "postcss-preset-env",
|
395 | ],
|
396 | };
|
397 | },
|
398 | },
|
399 | },
|
400 | ],
|
401 | },
|
402 | };
|
403 | ```
|
404 |
|
405 | #### `config`
|
406 |
|
407 | Type:
|
408 |
|
409 | ```ts
|
410 | type config = boolean | string;
|
411 | ```
|
412 |
|
413 | Default: `true`
|
414 |
|
415 | Allows to set options using config files.
|
416 | Options specified in the config file are combined with options passed to the loader, the loader options overwrite options from config.
|
417 |
|
418 | ##### Config Files
|
419 |
|
420 | The loader will search up the directory tree for configuration in the following places:
|
421 |
|
422 | - a `postcss` property in `package.json`
|
423 | - a `.postcssrc` file in JSON or YAML format
|
424 | - a `.postcssrc.json`, `.postcssrc.yaml`, `.postcssrc.yml`, `.postcssrc.js`, or `.postcssrc.cjs` file
|
425 | - a `postcss.config.js` or `postcss.config.cjs` CommonJS module exporting an object (**recommended**)
|
426 |
|
427 | ##### Examples of Config Files
|
428 |
|
429 | Using `object` notation:
|
430 |
|
431 | **postcss.config.js** (**recommend**)
|
432 |
|
433 | ```js
|
434 | module.exports = {
|
435 | // You can specify any options from https://postcss.org/api/#processoptions here
|
436 | // parser: 'sugarss',
|
437 | plugins: [
|
438 | // Plugins for PostCSS
|
439 | ["postcss-short", { prefix: "x" }],
|
440 | "postcss-preset-env",
|
441 | ],
|
442 | };
|
443 | ```
|
444 |
|
445 | Using `function` notation:
|
446 |
|
447 | **postcss.config.js** (**recommend**)
|
448 |
|
449 | ```js
|
450 | module.exports = (api) => {
|
451 | // `api.file` - path to the file
|
452 | // `api.mode` - `mode` value of webpack, please read https://webpack.js.org/configuration/mode/
|
453 | // `api.webpackLoaderContext` - loader context for complex use cases
|
454 | // `api.env` - alias `api.mode` for compatibility with `postcss-cli`
|
455 | // `api.options` - the `postcssOptions` options
|
456 |
|
457 | if (/\.sss$/.test(api.file)) {
|
458 | return {
|
459 | // You can specify any options from https://postcss.org/api/#processoptions here
|
460 | parser: "sugarss",
|
461 | plugins: [
|
462 | // Plugins for PostCSS
|
463 | ["postcss-short", { prefix: "x" }],
|
464 | "postcss-preset-env",
|
465 | ],
|
466 | };
|
467 | }
|
468 |
|
469 | return {
|
470 | // You can specify any options from https://postcss.org/api/#processoptions here
|
471 | plugins: [
|
472 | // Plugins for PostCSS
|
473 | ["postcss-short", { prefix: "x" }],
|
474 | "postcss-preset-env",
|
475 | ],
|
476 | };
|
477 | };
|
478 | ```
|
479 |
|
480 | **postcss.config.js** (**deprecated**, will be removed in the next major release)
|
481 |
|
482 | ```js
|
483 | module.exports = {
|
484 | // You can specify any options from https://postcss.org/api/#processoptions here
|
485 | // parser: 'sugarss',
|
486 | plugins: {
|
487 | // Plugins for PostCSS
|
488 | "postcss-short": { prefix: "x" },
|
489 | "postcss-preset-env": {},
|
490 | },
|
491 | };
|
492 | ```
|
493 |
|
494 | ##### Config Cascade
|
495 |
|
496 | You can use different `postcss.config.js` files in different directories.
|
497 | Config lookup starts from `path.dirname(file)` and walks the file tree upwards until a config file is found.
|
498 |
|
499 | ```
|
500 | |– components
|
501 | | |– component
|
502 | | | |– index.js
|
503 | | | |– index.png
|
504 | | | |– style.css (1)
|
505 | | | |– postcss.config.js (1)
|
506 | | |– component
|
507 | | | |– index.js
|
508 | | | |– image.png
|
509 | | | |– style.css (2)
|
510 | |
|
511 | |– postcss.config.js (1 && 2 (recommended))
|
512 | |– webpack.config.js
|
513 | |
|
514 | |– package.json
|
515 | ```
|
516 |
|
517 | After setting up your `postcss.config.js`, add `postcss-loader` to your `webpack.config.js`.
|
518 | You can use it standalone or in conjunction with `css-loader` (recommended).
|
519 |
|
520 | Use it **before** `css-loader` and `style-loader`, but **after** other preprocessor loaders like e.g `sass|less|stylus-loader`, if you use any (since [webpack loaders evaluate right to left/bottom to top](https://webpack.js.org/concepts/loaders/#configuration)).
|
521 |
|
522 | **webpack.config.js** (**recommended**)
|
523 |
|
524 | ```js
|
525 | module.exports = {
|
526 | module: {
|
527 | rules: [
|
528 | {
|
529 | test: /\.css$/,
|
530 | use: [
|
531 | "style-loader",
|
532 | {
|
533 | loader: "css-loader",
|
534 | options: {
|
535 | importLoaders: 1,
|
536 | },
|
537 | },
|
538 | "postcss-loader",
|
539 | ],
|
540 | },
|
541 | ],
|
542 | },
|
543 | };
|
544 | ```
|
545 |
|
546 | #### `boolean`
|
547 |
|
548 | Enables/Disables autoloading config.
|
549 |
|
550 | **webpack.config.js**
|
551 |
|
552 | ```js
|
553 | module.exports = {
|
554 | module: {
|
555 | rules: [
|
556 | {
|
557 | test: /\.css$/i,
|
558 | loader: "postcss-loader",
|
559 | options: {
|
560 | postcssOptions: {
|
561 | config: false,
|
562 | },
|
563 | },
|
564 | },
|
565 | ],
|
566 | },
|
567 | };
|
568 | ```
|
569 |
|
570 | #### String
|
571 |
|
572 | Allows to specify the path to the config file.
|
573 |
|
574 | **webpack.config.js**
|
575 |
|
576 | ```js
|
577 | const path = require("path");
|
578 |
|
579 | module.exports = {
|
580 | module: {
|
581 | rules: [
|
582 | {
|
583 | test: /\.css$/i,
|
584 | loader: "postcss-loader",
|
585 | options: {
|
586 | postcssOptions: {
|
587 | config: path.resolve(__dirname, "custom.config.js"),
|
588 | },
|
589 | },
|
590 | },
|
591 | ],
|
592 | },
|
593 | };
|
594 | ```
|
595 |
|
596 | ### `sourceMap`
|
597 |
|
598 | Type:
|
599 |
|
600 | ```ts
|
601 | type sourceMap = boolean;
|
602 | ```
|
603 |
|
604 | Default: depends on the `compiler.devtool` value
|
605 |
|
606 | By default generation of source maps depends on the [`devtool`](https://webpack.js.org/configuration/devtool/) option.
|
607 | All values enable source map generation except `eval` and `false` value.
|
608 |
|
609 | **webpack.config.js**
|
610 |
|
611 | ```js
|
612 | module.exports = {
|
613 | module: {
|
614 | rules: [
|
615 | {
|
616 | test: /\.css$/i,
|
617 | use: [
|
618 | { loader: "style-loader" },
|
619 | { loader: "css-loader", options: { sourceMap: true } },
|
620 | { loader: "postcss-loader", options: { sourceMap: true } },
|
621 | { loader: "sass-loader", options: { sourceMap: true } },
|
622 | ],
|
623 | },
|
624 | ],
|
625 | },
|
626 | };
|
627 | ```
|
628 |
|
629 | Alternative setup:
|
630 |
|
631 | **webpack.config.js**
|
632 |
|
633 | ```js
|
634 | module.exports = {
|
635 | devtool: "source-map",
|
636 | module: {
|
637 | rules: [
|
638 | {
|
639 | test: /\.css$/i,
|
640 | use: [
|
641 | { loader: "style-loader" },
|
642 | { loader: "css-loader" },
|
643 | { loader: "postcss-loader" },
|
644 | { loader: "sass-loader" },
|
645 | ],
|
646 | },
|
647 | ],
|
648 | },
|
649 | };
|
650 | ```
|
651 |
|
652 | ### `implementation`
|
653 |
|
654 | Type:
|
655 |
|
656 | ```ts
|
657 | type implementation = object;
|
658 | ```
|
659 |
|
660 | type of `implementation` should be the same as [postcss.d.ts](https://github.com/postcss/postcss/blob/main/lib/postcss.d.ts)
|
661 |
|
662 | Default: `postcss`
|
663 |
|
664 | The special `implementation` option determines which implementation of PostCSS to use. Overrides the locally installed `peerDependency` version of `postcss`.
|
665 |
|
666 | **This option is only really useful for downstream tooling authors to ease the PostCSS 7-to-8 transition.**
|
667 |
|
668 | #### `function`
|
669 |
|
670 | **webpack.config.js**
|
671 |
|
672 | ```js
|
673 | module.exports = {
|
674 | module: {
|
675 | rules: [
|
676 | {
|
677 | test: /\.css$/i,
|
678 | use: [
|
679 | { loader: "style-loader" },
|
680 | { loader: "css-loader" },
|
681 | {
|
682 | loader: "postcss-loader",
|
683 | options: { implementation: require("postcss") },
|
684 | },
|
685 | { loader: "sass-loader" },
|
686 | ],
|
687 | },
|
688 | ],
|
689 | },
|
690 | };
|
691 | ```
|
692 |
|
693 | #### String
|
694 |
|
695 | **webpack.config.js**
|
696 |
|
697 | ```js
|
698 | module.exports = {
|
699 | module: {
|
700 | rules: [
|
701 | {
|
702 | test: /\.css$/i,
|
703 | use: [
|
704 | { loader: "style-loader" },
|
705 | { loader: "css-loader" },
|
706 | {
|
707 | loader: "postcss-loader",
|
708 | options: { implementation: require.resolve("postcss") },
|
709 | },
|
710 | { loader: "sass-loader" },
|
711 | ],
|
712 | },
|
713 | ],
|
714 | },
|
715 | };
|
716 | ```
|
717 |
|
718 | ## Examples
|
719 |
|
720 | ### SugarSS
|
721 |
|
722 | You'll need to install `sugarss`:
|
723 |
|
724 | ```console
|
725 | npm install --save-dev sugarss
|
726 | ```
|
727 |
|
728 | Using [`SugarSS`](https://github.com/postcss/sugarss) syntax.
|
729 |
|
730 | **webpack.config.js**
|
731 |
|
732 | ```js
|
733 | module.exports = {
|
734 | module: {
|
735 | rules: [
|
736 | {
|
737 | test: /\.sss$/i,
|
738 | use: [
|
739 | "style-loader",
|
740 | {
|
741 | loader: "css-loader",
|
742 | options: { importLoaders: 1 },
|
743 | },
|
744 | {
|
745 | loader: "postcss-loader",
|
746 | options: {
|
747 | postcssOptions: {
|
748 | parser: "sugarss",
|
749 | },
|
750 | },
|
751 | },
|
752 | ],
|
753 | },
|
754 | ],
|
755 | },
|
756 | };
|
757 | ```
|
758 |
|
759 | ### Autoprefixer
|
760 |
|
761 | You'll need to install `autoprefixer`:
|
762 |
|
763 | ```console
|
764 | npm install --save-dev autoprefixer
|
765 | ```
|
766 |
|
767 | Add vendor prefixes to CSS rules using [`autoprefixer`](https://github.com/postcss/autoprefixer).
|
768 |
|
769 | **webpack.config.js**
|
770 |
|
771 | ```js
|
772 | module.exports = {
|
773 | module: {
|
774 | rules: [
|
775 | {
|
776 | test: /\.css$/i,
|
777 | use: [
|
778 | "style-loader",
|
779 | {
|
780 | loader: "css-loader",
|
781 | options: { importLoaders: 1 },
|
782 | },
|
783 | {
|
784 | loader: "postcss-loader",
|
785 | options: {
|
786 | postcssOptions: {
|
787 | plugins: [
|
788 | [
|
789 | "autoprefixer",
|
790 | {
|
791 | // Options
|
792 | },
|
793 | ],
|
794 | ],
|
795 | },
|
796 | },
|
797 | },
|
798 | ],
|
799 | },
|
800 | ],
|
801 | },
|
802 | };
|
803 | ```
|
804 |
|
805 | > **Warning**
|
806 | >
|
807 | > [`postcss-preset-env`](https://github.com/csstools/postcss-preset-env) includes [`autoprefixer`](https://github.com/postcss/autoprefixer), so adding it separately is not necessary if you already use the preset. More [information](https://github.com/csstools/postcss-preset-env#autoprefixer)
|
808 |
|
809 | ### PostCSS Preset Env
|
810 |
|
811 | You'll need to install `postcss-preset-env`:
|
812 |
|
813 | ```console
|
814 | npm install --save-dev postcss-preset-env
|
815 | ```
|
816 |
|
817 | **webpack.config.js**
|
818 |
|
819 | ```js
|
820 | module.exports = {
|
821 | module: {
|
822 | rules: [
|
823 | {
|
824 | test: /\.css$/i,
|
825 | use: [
|
826 | "style-loader",
|
827 | {
|
828 | loader: "css-loader",
|
829 | options: { importLoaders: 1 },
|
830 | },
|
831 | {
|
832 | loader: "postcss-loader",
|
833 | options: {
|
834 | postcssOptions: {
|
835 | plugins: [
|
836 | [
|
837 | "postcss-preset-env",
|
838 | {
|
839 | // Options
|
840 | },
|
841 | ],
|
842 | ],
|
843 | },
|
844 | },
|
845 | },
|
846 | ],
|
847 | },
|
848 | ],
|
849 | },
|
850 | };
|
851 | ```
|
852 |
|
853 | ### CSS Modules
|
854 |
|
855 | What is `CSS Modules`? Please [read](https://github.com/webpack-contrib/css-loader#modules).
|
856 |
|
857 | No additional options required on the `postcss-loader` side.
|
858 | To make them work properly, either add the `css-loader`’s `importLoaders` option.
|
859 |
|
860 | **webpack.config.js**
|
861 |
|
862 | ```js
|
863 | module.exports = {
|
864 | module: {
|
865 | rules: [
|
866 | {
|
867 | test: /\.css$/i,
|
868 | use: [
|
869 | "style-loader",
|
870 | {
|
871 | loader: "css-loader",
|
872 | options: {
|
873 | modules: true,
|
874 | importLoaders: 1,
|
875 | },
|
876 | },
|
877 | "postcss-loader",
|
878 | ],
|
879 | },
|
880 | ],
|
881 | },
|
882 | };
|
883 | ```
|
884 |
|
885 | ### CSS-in-JS and [`postcss-js`](https://github.com/postcss/postcss-js)
|
886 |
|
887 | You'll need to install `postcss-js`:
|
888 |
|
889 | ```console
|
890 | npm install --save-dev postcss-js
|
891 | ```
|
892 |
|
893 | If you want to process styles written in JavaScript, use the [`postcss-js`](https://github.com/postcss/postcss-js) parser.
|
894 |
|
895 | **webpack.config.js**
|
896 |
|
897 | ```js
|
898 | module.exports = {
|
899 | module: {
|
900 | rules: [
|
901 | {
|
902 | test: /\.style.js$/,
|
903 | use: [
|
904 | "style-loader",
|
905 | {
|
906 | loader: "css-loader",
|
907 | options: {
|
908 | importLoaders: 2,
|
909 | },
|
910 | },
|
911 | {
|
912 | loader: "postcss-loader",
|
913 | options: {
|
914 | postcssOptions: {
|
915 | parser: "postcss-js",
|
916 | },
|
917 | execute: true,
|
918 | },
|
919 | },
|
920 | "babel-loader",
|
921 | ],
|
922 | },
|
923 | ],
|
924 | },
|
925 | };
|
926 | ```
|
927 |
|
928 | As result you will be able to write styles in the following way
|
929 |
|
930 | ```js
|
931 | import colors from "./styles/colors";
|
932 |
|
933 | export default {
|
934 | ".menu": {
|
935 | color: colors.main,
|
936 | height: 25,
|
937 | "&_link": {
|
938 | color: "white",
|
939 | },
|
940 | },
|
941 | };
|
942 | ```
|
943 |
|
944 | > **Warning**
|
945 | >
|
946 | > If you are using Babel you need to do the following in order for the setup to work
|
947 |
|
948 | > 1. Add [`babel-plugin-add-module-exports`](https://github.com/59naga/babel-plugin-add-module-exports) to your configuration.
|
949 | > 2. You need to have only one **default** export per style module.
|
950 |
|
951 | ### Extract CSS
|
952 |
|
953 | Using [`mini-css-extract-plugin`](https://github.com/webpack-contrib/mini-css-extract-plugin).
|
954 |
|
955 | **webpack.config.js**
|
956 |
|
957 | ```js
|
958 | const isProductionMode = process.env.NODE_ENV === "production";
|
959 |
|
960 | const MiniCssExtractPlugin = require("mini-css-extract-plugin");
|
961 |
|
962 | module.exports = {
|
963 | mode: isProductionMode ? "production" : "development",
|
964 | module: {
|
965 | rules: [
|
966 | {
|
967 | test: /\.css$/,
|
968 | use: [
|
969 | isProductionMode ? MiniCssExtractPlugin.loader : "style-loader",
|
970 | "css-loader",
|
971 | "postcss-loader",
|
972 | ],
|
973 | },
|
974 | ],
|
975 | },
|
976 | plugins: [
|
977 | new MiniCssExtractPlugin({
|
978 | filename: isProductionMode ? "[name].[contenthash].css" : "[name].css",
|
979 | }),
|
980 | ],
|
981 | };
|
982 | ```
|
983 |
|
984 | ### Emit assets
|
985 |
|
986 | To write a asset from PostCSS plugin to the webpack, need to add a message in `result.messages`.
|
987 |
|
988 | The message should contain the following fields:
|
989 |
|
990 | - `type` = `asset` - Message type (require, should be equal `asset`)
|
991 | - `file` - file name (require)
|
992 | - `content` - file content (require)
|
993 | - `sourceMap` - sourceMap
|
994 | - `info` - asset info
|
995 |
|
996 | **webpack.config.js**
|
997 |
|
998 | ```js
|
999 | const postcssCustomPlugin = (opts = {}) => {
|
1000 | return {
|
1001 | postcssPlugin: "postcss-custom-plugin",
|
1002 | Once: (root, { result }) => {
|
1003 | result.messages.push({
|
1004 | type: "asset",
|
1005 | file: "sprite.svg",
|
1006 | content: "<svg>...</svg>",
|
1007 | });
|
1008 | },
|
1009 | };
|
1010 | };
|
1011 |
|
1012 | module.exports = {
|
1013 | module: {
|
1014 | rules: [
|
1015 | {
|
1016 | test: /\.css$/i,
|
1017 | use: [
|
1018 | "style-loader",
|
1019 | "css-loader",
|
1020 | {
|
1021 | loader: "postcss-loader",
|
1022 | options: {
|
1023 | postcssOptions: {
|
1024 | plugins: [postcssCustomPlugin()],
|
1025 | },
|
1026 | },
|
1027 | },
|
1028 | ],
|
1029 | },
|
1030 | ],
|
1031 | },
|
1032 | };
|
1033 | ```
|
1034 |
|
1035 | ### Add dependencies, contextDependencies, buildDependencies, missingDependencies
|
1036 |
|
1037 | The dependencies are necessary for webpack to understand when it needs to run recompilation on the changed files.
|
1038 |
|
1039 | There are two way to add dependencies:
|
1040 |
|
1041 | 1. (Recommended). The plugin may emit messages in `result.messages`.
|
1042 |
|
1043 | The message should contain the following fields:
|
1044 |
|
1045 | - `type` = `dependency` - Message type (require, should be equal `dependency`, `context-dependency`, `build-dependency` or `missing-dependency`)
|
1046 | - `file` - absolute file path (require)
|
1047 |
|
1048 | **webpack.config.js**
|
1049 |
|
1050 | ```js
|
1051 | const path = require("path");
|
1052 |
|
1053 | const postcssCustomPlugin = (opts = {}) => {
|
1054 | return {
|
1055 | postcssPlugin: "postcss-custom-plugin",
|
1056 | Once: (root, { result }) => {
|
1057 | result.messages.push({
|
1058 | type: "dependency",
|
1059 | file: path.resolve(__dirname, "path", "to", "file"),
|
1060 | });
|
1061 | },
|
1062 | };
|
1063 | };
|
1064 |
|
1065 | module.exports = {
|
1066 | module: {
|
1067 | rules: [
|
1068 | {
|
1069 | test: /\.css$/i,
|
1070 | use: [
|
1071 | "style-loader",
|
1072 | "css-loader",
|
1073 | {
|
1074 | loader: "postcss-loader",
|
1075 | options: {
|
1076 | postcssOptions: {
|
1077 | plugins: [postcssCustomPlugin()],
|
1078 | },
|
1079 | },
|
1080 | },
|
1081 | ],
|
1082 | },
|
1083 | ],
|
1084 | },
|
1085 | };
|
1086 | ```
|
1087 |
|
1088 | Or you can use ready-made plugin [postcss-add-dependencies](https://www.npmjs.com/package/postcss-add-dependencies).
|
1089 |
|
1090 | 2. Pass `loaderContext` in plugin.
|
1091 |
|
1092 | **webpack.config.js**
|
1093 |
|
1094 | ```js
|
1095 | const path = require("path");
|
1096 |
|
1097 | module.exports = {
|
1098 | module: {
|
1099 | rules: [
|
1100 | {
|
1101 | test: /\.css$/i,
|
1102 | use: [
|
1103 | "style-loader",
|
1104 | "css-loader",
|
1105 | {
|
1106 | loader: "postcss-loader",
|
1107 | options: {
|
1108 | postcssOptions: {
|
1109 | config: path.resolve(__dirname, "path/to/postcss.config.js"),
|
1110 | },
|
1111 | },
|
1112 | },
|
1113 | ],
|
1114 | },
|
1115 | ],
|
1116 | },
|
1117 | };
|
1118 | ```
|
1119 |
|
1120 | **postcss.config.js**
|
1121 |
|
1122 | ```js
|
1123 | module.exports = (api) => ({
|
1124 | plugins: [
|
1125 | require("path/to/postcssCustomPlugin.js")({
|
1126 | loaderContext: api.webpackLoaderContext,
|
1127 | }),
|
1128 | ],
|
1129 | });
|
1130 | ```
|
1131 |
|
1132 | **postcssCustomPlugin.js**
|
1133 |
|
1134 | ```js
|
1135 | const path = require("path");
|
1136 |
|
1137 | const postcssCustomPlugin = (opts = {}) => {
|
1138 | return {
|
1139 | postcssPlugin: "postcss-custom-plugin",
|
1140 | Once: (root, { result }) => {
|
1141 | opts.loaderContext.addDependency(
|
1142 | path.resolve(__dirname, "path", "to", "file"),
|
1143 | );
|
1144 | },
|
1145 | };
|
1146 | };
|
1147 |
|
1148 | postcssCustomPlugin.postcss = true;
|
1149 | module.exports = postcssCustomPlugin;
|
1150 | ```
|
1151 |
|
1152 | ## Contributing
|
1153 |
|
1154 | Please take a moment to read our contributing guidelines if you haven't yet done so.
|
1155 |
|
1156 | [CONTRIBUTING](./.github/CONTRIBUTING.md)
|
1157 |
|
1158 | ## License
|
1159 |
|
1160 | [MIT](./LICENSE)
|
1161 |
|
1162 | [npm]: https://img.shields.io/npm/v/postcss-loader.svg
|
1163 | [npm-url]: https://npmjs.com/package/postcss-loader
|
1164 | [node]: https://img.shields.io/node/v/postcss-loader.svg
|
1165 | [node-url]: https://nodejs.org
|
1166 | [tests]: https://github.com/webpack-contrib/postcss-loader/workflows/postcss-loader/badge.svg
|
1167 | [tests-url]: https://github.com/webpack-contrib/postcss-loader/actions
|
1168 | [cover]: https://codecov.io/gh/webpack-contrib/postcss-loader/branch/master/graph/badge.svg
|
1169 | [cover-url]: https://codecov.io/gh/webpack-contrib/postcss-loader
|
1170 | [discussion]: https://img.shields.io/github/discussions/webpack/webpack
|
1171 | [discussion-url]: https://github.com/webpack/webpack/discussions
|
1172 | [chat-postcss]: https://badges.gitter.im/postcss/postcss.svg
|
1173 | [chat-postcss-url]: https://gitter.im/postcss/postcss
|
1174 | [size]: https://packagephobia.now.sh/badge?p=postcss-loader
|
1175 | [size-url]: https://packagephobia.now.sh/result?p=postcss-loader
|