| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497 |
- [![npm][npm]][npm-url]
- [![node][node]][node-url]
- [![deps][deps]][deps-url]
- [![tests][tests]][tests-url]
- [![coverage][cover]][cover-url]
- [![chat][chat]][chat-url]
- <div align="center">
- <img width="180" height="180" hspace="10"
- alt="PostCSS Logo"
- src="https://api.postcss.org/logo.svg">
- <a href="https://github.com/webpack/webpack">
- <img width="200" height="200" hspace="10"
- src="https://cdn.rawgit.com/webpack/media/e7485eb2/logo/icon.svg">
- </a>
- <div align="center">
- <a href="https://evilmartians.com/?utm_source=postcss">
- <img src="https://evilmartians.com/badges/sponsored-by-evil-martians.svg"
- alt="Sponsored by Evil Martians" width="236" height="54" vspace="10">
- </a>
- </div>
- <h1>PostCSS Loader</h1>
- <p>Loader for <a href="https://webpack.js.org/">webpack</a> to process CSS with <a href="https://postcss.org/">PostCSS</a></p>
- </div>
- <h2 align="center">Install</h2>
- ```bash
- npm i -D postcss-loader
- ```
- <h2 align="center">Usage</h2>
- ### `Configuration`
- **`postcss.config.js`**
- ```js
- module.exports = {
- parser: 'sugarss',
- plugins: {
- 'postcss-import': {},
- 'postcss-preset-env': {},
- 'cssnano': {}
- }
- }
- ```
- You can read more about common PostCSS Config [here](https://github.com/michael-ciniawsky/postcss-load-config).
- ### `Config Cascade`
- You can use different `postcss.config.js` files in different directories.
- Config lookup starts from `path.dirname(file)` and walks the file tree upwards until a config file is found.
- ```
- |– components
- | |– component
- | | |– index.js
- | | |– index.png
- | | |– style.css (1)
- | | |– postcss.config.js (1)
- | |– component
- | | |– index.js
- | | |– image.png
- | | |– style.css (2)
- |
- |– postcss.config.js (1 && 2 (recommended))
- |– webpack.config.js
- |
- |– package.json
- ```
- 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.
- **`webpack.config.js`**
- ```js
- module.exports = {
- module: {
- rules: [
- {
- test: /\.css$/,
- use: [ 'style-loader', 'postcss-loader' ]
- }
- ]
- }
- }
- ```
- > ⚠️ When `postcss-loader` is used standalone (without `css-loader`) don't use `@import` in your CSS, since this can lead to quite bloated bundles
- **`webpack.config.js` (recommended)**
- ```js
- module.exports = {
- module: {
- rules: [
- {
- test: /\.css$/,
- use: [
- 'style-loader',
- { loader: 'css-loader', options: { importLoaders: 1 } },
- 'postcss-loader'
- ]
- }
- ]
- }
- }
- ```
- <h2 align="center">Options</h2>
- |Name|Type|Default|Description|
- |:--:|:--:|:-----:|:----------|
- |[`exec`](#exec)|`{Boolean}`|`undefined`|Enable PostCSS Parser support in `CSS-in-JS`|
- |[`parser`](#syntaxes)|`{String\|Object}`|`undefined`|Set PostCSS Parser|
- |[`syntax`](#syntaxes)|`{String\|Object}`|`undefined`|Set PostCSS Syntax|
- |[`stringifier`](#syntaxes)|`{String\|Object}`|`undefined`|Set PostCSS Stringifier|
- |[`config`](#config)|`{Object}`|`undefined`|Set `postcss.config.js` config path && `ctx`|
- |[`plugins`](#plugins)|`{Array\|Function}`|`[]`|Set PostCSS Plugins|
- |[`sourceMap`](#sourcemap)|`{String\|Boolean}`|`false`|Enable Source Maps|
- ### `Exec`
- If you use JS styles without the [`postcss-js`][postcss-js] parser, add the `exec` option.
- **`webpack.config.js`**
- ```js
- {
- test: /\.style.js$/,
- use: [
- 'style-loader',
- { loader: 'css-loader', options: { importLoaders: 1 } },
- { loader: 'postcss-loader', options: { parser: 'sugarss', exec: true } }
- ]
- }
- ```
- ### `Config`
- |Name|Type|Default|Description|
- |:--:|:--:|:-----:|:----------|
- |[`path`](#path)|`{String}`|`undefined`|PostCSS Config Directory|
- |[`context`](#context)|`{Object}`|`undefined`|PostCSS Config Context|
- #### `Path`
- 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.
- > ⚠️ Otherwise it is **unnecessary** to set this option and is **not** recommended
- > ⚠️ 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
- **`webpack.config.js`**
- ```js
- {
- loader: 'postcss-loader',
- options: {
- config: {
- path: 'path/to/.config/' ✅
- path: 'path/to/.config/css.config.js' ❌
- }
- }
- }
- ```
- [supported config formats]: https://github.com/michael-ciniawsky/postcss-load-config#usage
- #### `Context (ctx)`
- |Name|Type|Default|Description|
- |:--:|:--:|:-----:|:----------|
- |`env`|`{String}`|`'development'`|`process.env.NODE_ENV`|
- |`file`|`{Object}`|`loader.resourcePath`|`extname`, `dirname`, `basename`|
- |`options`|`{Object}`|`{}`|Options|
- `postcss-loader` exposes context `ctx` to the config file, making your `postcss.config.js` dynamic, so can use it to do some real magic ✨
- **`postcss.config.js`**
- ```js
- module.exports = ({ file, options, env }) => ({
- parser: file.extname === '.sss' ? 'sugarss' : false,
- plugins: {
- 'postcss-import': { root: file.dirname },
- 'postcss-preset-env': options['postcss-preset-env'] ? options['postcss-preset-env'] : false,
- 'cssnano': env === 'production' ? options.cssnano : false
- }
- })
- ```
- **`webpack.config.js`**
- ```js
- {
- loader: 'postcss-loader',
- options: {
- config: {
- ctx: {
- 'postcss-preset-env': {...options},
- cssnano: {...options},
- }
- }
- }
- }
- ```
- ### `Plugins`
- **`webpack.config.js`**
- ```js
- {
- loader: 'postcss-loader',
- options: {
- ident: 'postcss',
- plugins: (loader) => [
- require('postcss-import')({ root: loader.resourcePath }),
- require('postcss-preset-env')(),
- require('cssnano')()
- ]
- }
- }
- ```
- > ⚠️ 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'`)
- ### `Syntaxes`
- |Name|Type|Default|Description|
- |:--:|:--:|:-----:|:----------|
- |[`parser`](#parser)|`{String\|Function}`|`undefined`|Custom PostCSS Parser|
- |[`syntax`](#syntax)|`{String\|Function}`|`undefined`|Custom PostCSS Syntax|
- |[`stringifier`](#stringifier)|`{String\|Function}`|`undefined`|Custom PostCSS Stringifier|
- #### `Parser`
- **`webpack.config.js`**
- ```js
- {
- test: /\.sss$/,
- use: [
- ...,
- { loader: 'postcss-loader', options: { parser: 'sugarss' } }
- ]
- }
- ```
- #### `Syntax`
- **`webpack.config.js`**
- ```js
- {
- test: /\.css$/,
- use: [
- ...,
- { loader: 'postcss-loader', options: { syntax: 'sugarss' } }
- ]
- }
- ```
- #### `Stringifier`
- **`webpack.config.js`**
- ```js
- {
- test: /\.css$/,
- use: [
- ...,
- { loader: 'postcss-loader', options: { stringifier: 'midas' } }
- ]
- }
- ```
- ### `SourceMap`
- 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.
- **`webpack.config.js`**
- ```js
- {
- test: /\.css/,
- use: [
- { loader: 'style-loader', options: { sourceMap: true } },
- { loader: 'css-loader', options: { sourceMap: true } },
- { loader: 'postcss-loader', options: { sourceMap: true } },
- { loader: 'sass-loader', options: { sourceMap: true } }
- ]
- }
- ```
- #### `'inline'`
- You can set the `sourceMap: 'inline'` option to inline the source map
- within the CSS directly as an annotation comment.
- **`webpack.config.js`**
- ```js
- {
- loader: 'postcss-loader',
- options: {
- sourceMap: 'inline'
- }
- }
- ```
- ```css
- .class { color: red; }
- /*# sourceMappingURL=data:application/json;base64, ... */
- ```
- <h2 align="center">Examples</h2>
- ### `Stylelint`
- **`webpack.config.js`**
- ```js
- {
- test: /\.css$/,
- use: [
- 'style-loader',
- 'css-loader',
- {
- loader: 'postcss-loader',
- options: {
- ident: 'postcss',
- plugins: [
- require('postcss-import')(),
- require('stylelint')(),
- ...,
- ]
- }
- }
- ]
- }
- ```
- ### `Autoprefixing`
- **`webpack.config.js`**
- ```js
- {
- test: /\.css$/,
- use: [
- 'style-loader',
- 'css-loader',
- {
- loader: 'postcss-loader',
- options: {
- ident: 'postcss',
- plugins: [
- require('autoprefixer')({...options}),
- ...,
- ]
- }
- }
- ]
- }
- ```
- > :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.
- ### `CSS Modules`
- This loader [cannot be used] with [CSS Modules] out of the box due
- to the way `css-loader` processes file imports. To make them work properly,
- either add the css-loader’s [`importLoaders`] option.
- **`webpack.config.js`**
- ```js
- {
- test: /\.css$/,
- use: [
- 'style-loader',
- { loader: 'css-loader', options: { modules: true, importLoaders: 1 } },
- 'postcss-loader'
- ]
- }
- ```
- or use [postcss-modules] instead of `css-loader`.
- [`importLoaders`]: https://github.com/webpack-contrib/css-loader#importloaders
- [cannot be used]: https://github.com/webpack/css-loader/issues/137
- [CSS Modules]: https://github.com/webpack/css-loader#css-modules
- [postcss-modules]: https://github.com/css-modules/postcss-modules
- ### `CSS-in-JS`
- If you want to process styles written in JavaScript, use the [postcss-js] parser.
- [postcss-js]: https://github.com/postcss/postcss-js
- **`webpack.config.js`**
- ```js
- {
- test: /\.style.js$/,
- use: [
- 'style-loader',
- { loader: 'css-loader', options: { importLoaders: 2 } },
- { loader: 'postcss-loader', options: { parser: 'postcss-js' } },
- 'babel-loader'
- ]
- }
- ```
- As result you will be able to write styles in the following way
- ```js
- import colors from './styles/colors'
- export default {
- '.menu': {
- color: colors.main,
- height: 25,
- '&_link': {
- color: 'white'
- }
- }
- }
- ```
- > :warning: If you are using Babel you need to do the following in order for the setup to work
- > 1. Add [babel-plugin-add-module-exports] to your configuration
- > 2. You need to have only one **default** export per style module
- [babel-plugin-add-module-exports]: https://github.com/59naga/babel-plugin-add-module-exports
- ### [Extract CSS][ExtractPlugin]
- [ExtractPlugin]: https://github.com/webpack-contrib/mini-css-extract-plugin
- **`webpack.config.js`**
- ```js
- const devMode = process.env.NODE_ENV !== 'production'
- const MiniCssExtractPlugin = require('mini-css-extract-plugin')
- module.exports = {
- module: {
- rules: [
- {
- test: /\.css$/,
- use: [
- devMode ? 'style-loader' : MiniCssExtractPlugin.loader,
- 'css-loader',
- 'postcss-loader'
- ]
- }
- ]
- },
- plugins: [
- new MiniCssExtractPlugin({
- filename: devMode ? '[name].css' : '[name].[hash].css'
- })
- ]
- }
- ```
- <h2 align="center">Maintainers</h2>
- <table>
- <tbody>
- <tr>
- <td align="center">
- <a href="https://github.com/michael-ciniawsky">
- <img width="150" height="150" src="https://github.com/michael-ciniawsky.png?v=3&s=150">
- </br>
- Michael Ciniawsky
- </a>
- </td>
- <td align="center">
- <a href="https://github.com/evilebottnawi">
- <img width="150" height="150" src="https://github.com/evilebottnawi.png?v=3&s=150">
- </br>
- Alexander Krasnoyarov
- </a>
- </td>
- </tr>
- <tbody>
- </table>
- [npm]: https://img.shields.io/npm/v/postcss-loader.svg
- [npm-url]: https://npmjs.com/package/postcss-loader
- [node]: https://img.shields.io/node/v/postcss-loader.svg
- [node-url]: https://nodejs.org
- [deps]: https://david-dm.org/postcss/postcss-loader.svg
- [deps-url]: https://david-dm.org/postcss/postcss-loader
- [tests]: https://img.shields.io/travis/postcss/postcss-loader.svg
- [tests-url]: https://travis-ci.org/postcss/postcss-loader
- [cover]: https://coveralls.io/repos/github/postcss/postcss-loader/badge.svg
- [cover-url]: https://coveralls.io/github/postcss/postcss-loader
- [chat]: https://badges.gitter.im/postcss/postcss.svg
- [chat-url]: https://gitter.im/postcss/postcss
|