You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

497 lines
12 KiB

4 years ago
  1. [![npm][npm]][npm-url]
  2. [![node][node]][node-url]
  3. [![deps][deps]][deps-url]
  4. [![tests][tests]][tests-url]
  5. [![coverage][cover]][cover-url]
  6. [![chat][chat]][chat-url]
  7. <div align="center">
  8. <img width="180" height="180" hspace="10"
  9. alt="PostCSS Logo"
  10. src="https://api.postcss.org/logo.svg">
  11. <a href="https://github.com/webpack/webpack">
  12. <img width="200" height="200" 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 src="https://evilmartians.com/badges/sponsored-by-evil-martians.svg"
  18. alt="Sponsored by Evil Martians" width="236" height="54" vspace="10">
  19. </a>
  20. </div>
  21. <h1>PostCSS Loader</h1>
  22. <p>Loader for <a href="https://webpack.js.org/">webpack</a> to process CSS with <a href="https://postcss.org/">PostCSS</a></p>
  23. </div>
  24. <h2 align="center">Install</h2>
  25. ```bash
  26. npm i -D postcss-loader
  27. ```
  28. <h2 align="center">Usage</h2>
  29. ### `Configuration`
  30. **`postcss.config.js`**
  31. ```js
  32. module.exports = {
  33. parser: 'sugarss',
  34. plugins: {
  35. 'postcss-import': {},
  36. 'postcss-preset-env': {},
  37. 'cssnano': {}
  38. }
  39. }
  40. ```
  41. You can read more about common PostCSS Config [here](https://github.com/michael-ciniawsky/postcss-load-config).
  42. ### `Config Cascade`
  43. You can use different `postcss.config.js` files in different directories.
  44. Config lookup starts from `path.dirname(file)` and walks the file tree upwards until a config file is found.
  45. ```
  46. |– components
  47. | |– component
  48. | | |– index.js
  49. | | |– index.png
  50. | | |– style.css (1)
  51. | | |– postcss.config.js (1)
  52. | |– component
  53. | | |– index.js
  54. | | |– image.png
  55. | | |– style.css (2)
  56. |
  57. |– postcss.config.js (1 && 2 (recommended))
  58. |– webpack.config.js
  59. |
  60. |– package.json
  61. ```
  62. After setting up your `postcss.config.js`, add `postcss-loader` to your `webpack.config.js`. You can use it standalone or in conjunction with `css-loader` (recommended). Use it **after** `css-loader` and `style-loader`, but **before** other preprocessor loaders like e.g `sass|less|stylus-loader`, if you use any.
  63. **`webpack.config.js`**
  64. ```js
  65. module.exports = {
  66. module: {
  67. rules: [
  68. {
  69. test: /\.css$/,
  70. use: [ 'style-loader', 'postcss-loader' ]
  71. }
  72. ]
  73. }
  74. }
  75. ```
  76. > ⚠️ When `postcss-loader` is used standalone (without `css-loader`) don't use `@import` in your CSS, since this can lead to quite bloated bundles
  77. **`webpack.config.js` (recommended)**
  78. ```js
  79. module.exports = {
  80. module: {
  81. rules: [
  82. {
  83. test: /\.css$/,
  84. use: [
  85. 'style-loader',
  86. { loader: 'css-loader', options: { importLoaders: 1 } },
  87. 'postcss-loader'
  88. ]
  89. }
  90. ]
  91. }
  92. }
  93. ```
  94. <h2 align="center">Options</h2>
  95. |Name|Type|Default|Description|
  96. |:--:|:--:|:-----:|:----------|
  97. |[`exec`](#exec)|`{Boolean}`|`undefined`|Enable PostCSS Parser support in `CSS-in-JS`|
  98. |[`parser`](#syntaxes)|`{String\|Object}`|`undefined`|Set PostCSS Parser|
  99. |[`syntax`](#syntaxes)|`{String\|Object}`|`undefined`|Set PostCSS Syntax|
  100. |[`stringifier`](#syntaxes)|`{String\|Object}`|`undefined`|Set PostCSS Stringifier|
  101. |[`config`](#config)|`{Object}`|`undefined`|Set `postcss.config.js` config path && `ctx`|
  102. |[`plugins`](#plugins)|`{Array\|Function}`|`[]`|Set PostCSS Plugins|
  103. |[`sourceMap`](#sourcemap)|`{String\|Boolean}`|`false`|Enable Source Maps|
  104. ### `Exec`
  105. If you use JS styles without the [`postcss-js`][postcss-js] parser, add the `exec` option.
  106. **`webpack.config.js`**
  107. ```js
  108. {
  109. test: /\.style.js$/,
  110. use: [
  111. 'style-loader',
  112. { loader: 'css-loader', options: { importLoaders: 1 } },
  113. { loader: 'postcss-loader', options: { parser: 'sugarss', exec: true } }
  114. ]
  115. }
  116. ```
  117. ### `Config`
  118. |Name|Type|Default|Description|
  119. |:--:|:--:|:-----:|:----------|
  120. |[`path`](#path)|`{String}`|`undefined`|PostCSS Config Directory|
  121. |[`context`](#context)|`{Object}`|`undefined`|PostCSS Config Context|
  122. #### `Path`
  123. You can manually specify the path to search for your config (`postcss.config.js`) with the `config.path` option. This is needed if you store your config in a separate e.g `./config || ./.config` folder.
  124. > ⚠️ Otherwise it is **unnecessary** to set this option and is **not** recommended
  125. > ⚠️ Note that you **can't** use a **filename** other than the [supported config formats] (e.g `.postcssrc.js`, `postcss.config.js`), this option only allows you to manually specify the **directory** where config lookup should **start** from
  126. **`webpack.config.js`**
  127. ```js
  128. {
  129. loader: 'postcss-loader',
  130. options: {
  131. config: {
  132. path: 'path/to/.config/' ✅
  133. path: 'path/to/.config/css.config.js' ❌
  134. }
  135. }
  136. }
  137. ```
  138. [supported config formats]: https://github.com/michael-ciniawsky/postcss-load-config#usage
  139. #### `Context (ctx)`
  140. |Name|Type|Default|Description|
  141. |:--:|:--:|:-----:|:----------|
  142. |`env`|`{String}`|`'development'`|`process.env.NODE_ENV`|
  143. |`file`|`{Object}`|`loader.resourcePath`|`extname`, `dirname`, `basename`|
  144. |`options`|`{Object}`|`{}`|Options|
  145. `postcss-loader` exposes context `ctx` to the config file, making your `postcss.config.js` dynamic, so can use it to do some real magic ✨
  146. **`postcss.config.js`**
  147. ```js
  148. module.exports = ({ file, options, env }) => ({
  149. parser: file.extname === '.sss' ? 'sugarss' : false,
  150. plugins: {
  151. 'postcss-import': { root: file.dirname },
  152. 'postcss-preset-env': options['postcss-preset-env'] ? options['postcss-preset-env'] : false,
  153. 'cssnano': env === 'production' ? options.cssnano : false
  154. }
  155. })
  156. ```
  157. **`webpack.config.js`**
  158. ```js
  159. {
  160. loader: 'postcss-loader',
  161. options: {
  162. config: {
  163. ctx: {
  164. 'postcss-preset-env': {...options},
  165. cssnano: {...options},
  166. }
  167. }
  168. }
  169. }
  170. ```
  171. ### `Plugins`
  172. **`webpack.config.js`**
  173. ```js
  174. {
  175. loader: 'postcss-loader',
  176. options: {
  177. ident: 'postcss',
  178. plugins: (loader) => [
  179. require('postcss-import')({ root: loader.resourcePath }),
  180. require('postcss-preset-env')(),
  181. require('cssnano')()
  182. ]
  183. }
  184. }
  185. ```
  186. > ⚠️ webpack requires an identifier (`ident`) in `options` when `{Function}/require` is used (Complex Options). The `ident` can be freely named as long as it is unique. It's recommended to name it (`ident: 'postcss'`)
  187. ### `Syntaxes`
  188. |Name|Type|Default|Description|
  189. |:--:|:--:|:-----:|:----------|
  190. |[`parser`](#parser)|`{String\|Function}`|`undefined`|Custom PostCSS Parser|
  191. |[`syntax`](#syntax)|`{String\|Function}`|`undefined`|Custom PostCSS Syntax|
  192. |[`stringifier`](#stringifier)|`{String\|Function}`|`undefined`|Custom PostCSS Stringifier|
  193. #### `Parser`
  194. **`webpack.config.js`**
  195. ```js
  196. {
  197. test: /\.sss$/,
  198. use: [
  199. ...,
  200. { loader: 'postcss-loader', options: { parser: 'sugarss' } }
  201. ]
  202. }
  203. ```
  204. #### `Syntax`
  205. **`webpack.config.js`**
  206. ```js
  207. {
  208. test: /\.css$/,
  209. use: [
  210. ...,
  211. { loader: 'postcss-loader', options: { syntax: 'sugarss' } }
  212. ]
  213. }
  214. ```
  215. #### `Stringifier`
  216. **`webpack.config.js`**
  217. ```js
  218. {
  219. test: /\.css$/,
  220. use: [
  221. ...,
  222. { loader: 'postcss-loader', options: { stringifier: 'midas' } }
  223. ]
  224. }
  225. ```
  226. ### `SourceMap`
  227. Enables source map support, `postcss-loader` will use the previous source map given by other loaders and update it accordingly, if no previous loader is applied before `postcss-loader`, the loader will generate a source map for you.
  228. **`webpack.config.js`**
  229. ```js
  230. {
  231. test: /\.css/,
  232. use: [
  233. { loader: 'style-loader', options: { sourceMap: true } },
  234. { loader: 'css-loader', options: { sourceMap: true } },
  235. { loader: 'postcss-loader', options: { sourceMap: true } },
  236. { loader: 'sass-loader', options: { sourceMap: true } }
  237. ]
  238. }
  239. ```
  240. #### `'inline'`
  241. You can set the `sourceMap: 'inline'` option to inline the source map
  242. within the CSS directly as an annotation comment.
  243. **`webpack.config.js`**
  244. ```js
  245. {
  246. loader: 'postcss-loader',
  247. options: {
  248. sourceMap: 'inline'
  249. }
  250. }
  251. ```
  252. ```css
  253. .class { color: red; }
  254. /*# sourceMappingURL=data:application/json;base64, ... */
  255. ```
  256. <h2 align="center">Examples</h2>
  257. ### `Stylelint`
  258. **`webpack.config.js`**
  259. ```js
  260. {
  261. test: /\.css$/,
  262. use: [
  263. 'style-loader',
  264. 'css-loader',
  265. {
  266. loader: 'postcss-loader',
  267. options: {
  268. ident: 'postcss',
  269. plugins: [
  270. require('postcss-import')(),
  271. require('stylelint')(),
  272. ...,
  273. ]
  274. }
  275. }
  276. ]
  277. }
  278. ```
  279. ### `Autoprefixing`
  280. **`webpack.config.js`**
  281. ```js
  282. {
  283. test: /\.css$/,
  284. use: [
  285. 'style-loader',
  286. 'css-loader',
  287. {
  288. loader: 'postcss-loader',
  289. options: {
  290. ident: 'postcss',
  291. plugins: [
  292. require('autoprefixer')({...options}),
  293. ...,
  294. ]
  295. }
  296. }
  297. ]
  298. }
  299. ```
  300. > :warning: [`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.
  301. ### `CSS Modules`
  302. This loader [cannot be used] with [CSS Modules] out of the box due
  303. to the way `css-loader` processes file imports. To make them work properly,
  304. either add the css-loader’s [`importLoaders`] option.
  305. **`webpack.config.js`**
  306. ```js
  307. {
  308. test: /\.css$/,
  309. use: [
  310. 'style-loader',
  311. { loader: 'css-loader', options: { modules: true, importLoaders: 1 } },
  312. 'postcss-loader'
  313. ]
  314. }
  315. ```
  316. or use [postcss-modules] instead of `css-loader`.
  317. [`importLoaders`]: https://github.com/webpack-contrib/css-loader#importloaders
  318. [cannot be used]: https://github.com/webpack/css-loader/issues/137
  319. [CSS Modules]: https://github.com/webpack/css-loader#css-modules
  320. [postcss-modules]: https://github.com/css-modules/postcss-modules
  321. ### `CSS-in-JS`
  322. If you want to process styles written in JavaScript, use the [postcss-js] parser.
  323. [postcss-js]: https://github.com/postcss/postcss-js
  324. **`webpack.config.js`**
  325. ```js
  326. {
  327. test: /\.style.js$/,
  328. use: [
  329. 'style-loader',
  330. { loader: 'css-loader', options: { importLoaders: 2 } },
  331. { loader: 'postcss-loader', options: { parser: 'postcss-js' } },
  332. 'babel-loader'
  333. ]
  334. }
  335. ```
  336. As result you will be able to write styles in the following way
  337. ```js
  338. import colors from './styles/colors'
  339. export default {
  340. '.menu': {
  341. color: colors.main,
  342. height: 25,
  343. '&_link': {
  344. color: 'white'
  345. }
  346. }
  347. }
  348. ```
  349. > :warning: If you are using Babel you need to do the following in order for the setup to work
  350. > 1. Add [babel-plugin-add-module-exports] to your configuration
  351. > 2. You need to have only one **default** export per style module
  352. [babel-plugin-add-module-exports]: https://github.com/59naga/babel-plugin-add-module-exports
  353. ### [Extract CSS][ExtractPlugin]
  354. [ExtractPlugin]: https://github.com/webpack-contrib/mini-css-extract-plugin
  355. **`webpack.config.js`**
  356. ```js
  357. const devMode = process.env.NODE_ENV !== 'production'
  358. const MiniCssExtractPlugin = require('mini-css-extract-plugin')
  359. module.exports = {
  360. module: {
  361. rules: [
  362. {
  363. test: /\.css$/,
  364. use: [
  365. devMode ? 'style-loader' : MiniCssExtractPlugin.loader,
  366. 'css-loader',
  367. 'postcss-loader'
  368. ]
  369. }
  370. ]
  371. },
  372. plugins: [
  373. new MiniCssExtractPlugin({
  374. filename: devMode ? '[name].css' : '[name].[hash].css'
  375. })
  376. ]
  377. }
  378. ```
  379. <h2 align="center">Maintainers</h2>
  380. <table>
  381. <tbody>
  382. <tr>
  383. <td align="center">
  384. <a href="https://github.com/michael-ciniawsky">
  385. <img width="150" height="150" src="https://github.com/michael-ciniawsky.png?v=3&s=150">
  386. </br>
  387. Michael Ciniawsky
  388. </a>
  389. </td>
  390. <td align="center">
  391. <a href="https://github.com/evilebottnawi">
  392. <img width="150" height="150" src="https://github.com/evilebottnawi.png?v=3&s=150">
  393. </br>
  394. Alexander Krasnoyarov
  395. </a>
  396. </td>
  397. </tr>
  398. <tbody>
  399. </table>
  400. [npm]: https://img.shields.io/npm/v/postcss-loader.svg
  401. [npm-url]: https://npmjs.com/package/postcss-loader
  402. [node]: https://img.shields.io/node/v/postcss-loader.svg
  403. [node-url]: https://nodejs.org
  404. [deps]: https://david-dm.org/postcss/postcss-loader.svg
  405. [deps-url]: https://david-dm.org/postcss/postcss-loader
  406. [tests]: https://img.shields.io/travis/postcss/postcss-loader.svg
  407. [tests-url]: https://travis-ci.org/postcss/postcss-loader
  408. [cover]: https://coveralls.io/repos/github/postcss/postcss-loader/badge.svg
  409. [cover-url]: https://coveralls.io/github/postcss/postcss-loader
  410. [chat]: https://badges.gitter.im/postcss/postcss.svg
  411. [chat-url]: https://gitter.im/postcss/postcss