README

# PostCSS Loader

Loader for webpack to process CSS with PostCSS

## Install

npm i -D postcss-loader

## Usage

### <tt>Configuration</tt>

**`postcss.config.js`**

module.exports = {
parser: 'sugarss',
plugins: {
'postcss-import': {},
'postcss-preset-env': {},
'cssnano': {}
}
}

You can read more about common PostCSS Config here.

### <tt>Config Cascade</tt>

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`**

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)**

module.exports = {
module: {
rules: [
{
test: /\.css$/,
use: [
'style-loader',
{ loader: 'css-loader', options: { importLoaders: 1 } },
'postcss-loader'
]
}
]
}
}

## Options

Name | Type | Default | Description
--- | --- | --- | ---
`exec` | `{Boolean}` | `undefined` | Enable PostCSS Parser support in `CSS-in-JS`
`parser` | `{String\|Object}` | `undefined` | Set PostCSS Parser
`syntax` | `{String\|Object}` | `undefined` | Set PostCSS Syntax
`stringifier` | `{String\|Object}` | `undefined` | Set PostCSS Stringifier
`config` | `{Object}` | `undefined` | Set `postcss.config.js` config path && `ctx`
`plugins` | `{Array\|Function}` | `[]` | Set PostCSS Plugins
`sourceMap` | `{String\|Boolean}` | `false` | Enable Source Maps

### <tt>Exec</tt>

If you use JS styles without the `postcss-js` parser, add the `exec` option.

**`webpack.config.js`**

{
test: /\.style.js$/,
use: [
'style-loader',
{ loader: 'css-loader', options: { importLoaders: 1 } },
{ loader: 'postcss-loader', options: { parser: 'sugarss', exec: true } }
]
}

### <tt>Config</tt>

Name | Type | Default | Description
--- | --- | --- | ---
`path` | `{String}` | `undefined` | PostCSS Config Directory
`context` | `{Object}` | `undefined` | PostCSS Config Context

#### <tt>Path</tt>

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, this option only allows you to manually specify the directory where config lookup should start from

**`webpack.config.js`**

{
loader: 'postcss-loader',
options: {
config: {
path: 'path/to/.config/' ✅
path: 'path/to/.config/css.config.js' ❌
}
}
}

#### <tt>Context (ctx)</tt>

Name | Type | Default | Description
--- | --- | --- | ---

`env`

`{String}`

‘'development’`\ilinebr </td> <td class="markdownTableBodyLeft">`process.env.NODE_ENV<tt>\ilinebr </td> </tr> <tr class="markdownTableRowEven"> <td class="markdownTableBodyCenter">file`\ilinebr </td> <td class="markdownTableBodyCenter">`{Object}`\ilinebr </td> <td class="markdownTableBodyCenter">`loader.resourcePath<tt>\ilinebr </td> <td class="markdownTableBodyLeft">extname`,`dirname`,`basename`\ilinebr </td> </tr> <tr class="markdownTableRowOdd"> <td class="markdownTableBodyCenter">`options`\ilinebr </td> <td class="markdownTableBodyCenter">`{Object}`\ilinebr </td> <td class="markdownTableBodyCenter">`{}`

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`**

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`**

{
loader: 'postcss-loader',
options: {
config: {
ctx: {
'postcss-preset-env': {...options},
cssnano: {...options},
}
}
}
}

### <tt>Plugins</tt>

**`webpack.config.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’`)

### <tt>Syntaxes</tt>

Name | Type | Default | Description
--- | --- | --- | ---
`parser` | `{String\|Function}` | `undefined` | Custom PostCSS Parser
`syntax` | `{String\|Function}` | `undefined` | Custom PostCSS Syntax
`stringifier` | `{String\|Function}` | `undefined` | Custom PostCSS Stringifier

#### <tt>Parser</tt>

**`webpack.config.js`**

{
test: /\.sss$/,
use: [
...,
{ loader: 'postcss-loader', options: { parser: 'sugarss' } }
]
}

#### <tt>Syntax</tt>

**`webpack.config.js`**

{
test: /\.css$/,
use: [
...,
{ loader: 'postcss-loader', options: { syntax: 'sugarss' } }
]
}

#### <tt>Stringifier</tt>

**`webpack.config.js`**

{
test: /\.css$/,
use: [
...,
{ loader: 'postcss-loader', options: { stringifier: 'midas' } }
]
}

### <tt>SourceMap</tt>

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`**

{
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`**

{
loader: 'postcss-loader',
options: {
sourceMap: 'inline'
}
}
.class { color: red; }
/*# sourceMappingURL=data:application/json;base64, ... */

## Examples

### <tt>Stylelint</tt>

**`webpack.config.js`**

{
test: /\.css$/,
use: [
'style-loader',
'css-loader',
{
loader: 'postcss-loader',
options: {
ident: 'postcss',
plugins: [
require('postcss-import')(),
require('stylelint')(),
...,
]
}
}
]
}

### <tt>Autoprefixing</tt>

**`webpack.config.js`**

{
test: /\.css$/,
use: [
'style-loader',
'css-loader',
{
loader: 'postcss-loader',
options: {
ident: 'postcss',
plugins: [
require('autoprefixer')({...options}),
...,
]
}
}
]
}

> :warning: `postcss-preset-env` includes `autoprefixer`, so adding it separately is not necessary if you already use the preset.

### <tt>CSS Modules</tt>

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`**

{
test: /\.css$/,
use: [
'style-loader',
{ loader: 'css-loader', options: { modules: true, importLoaders: 1 } },
'postcss-loader'
]
}

or use postcss-modules instead of `css-loader`.

### <tt>CSS-in-JS</tt>

If you want to process styles written in JavaScript, use the postcss-js parser.

**`webpack.config.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

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

> 1. You need to have only one default export per style module

### <a href="https://github.com/webpack-contrib/mini-css-extract-plugin">Extract CSS</a>

**`webpack.config.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'
})
]
}

## Maintainers

Michael Ciniawsky

Alexander Krasnoyarov <tbody>