W3cubDocs

/webpack

postcss-loader

Install

npm i -D  postcss-loader

Usage

Config

postcss.config.js

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

You can read more about common PostCSS Config here.

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

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 Default Description
exec
undefined
Enable PostCSS Parser support in CSS-in-JS
parser
undefined
Set PostCSS Parser
syntax
undefined
Set PostCSS Syntax
stringifier
undefined
Set PostCSS Stringifier
config
undefined
Set postcss.config.js config path && ctx
plugins
[]
Set PostCSS Plugins
sourceMap
false
Enable Source Maps

Exec

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

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

Config

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

webpack.config.js

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

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

module.exports = ({ file, options, env }) => ({
  parser: file.extname === '.sss' ? 'sugarss' : false,
  plugins: {
    'postcss-import': { root: file.dirname },
    'postcss-cssnext': options.cssnext ? options.cssnext : false,
    'autoprefixer': env == 'production' ? options.autoprefixer : false,
    'cssnano': env === 'production' ? options.cssnano : false
  }
})

webpack.config.js

{
  loader: 'postcss-loader'
  options: {
    config: {
      ctx: {
        cssnext: {...options},
        cssnano: {...options},
        autoprefixer: {...options}
      }
    }
  }
}

Plugins

webpack.config.js

{
  loader: 'postcss-loader',
  options: {
    plugins: (loader) => [
      require('postcss-import')({ root: loader.resourcePath }),
      require('postcss-cssnext')(),
      require('autoprefixer')(),
      require('cssnano')()
    ]
  }
}

Syntaxes

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

Parser

webpack.config.js

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

Syntax

webpack.config.js

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

Stringifier

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

:warning: If a previous loader like e.g sass-loader is applied and it's sourceMap option is set, but the sourceMap option in postcss-loader is omitted, previous source maps will be discarded by postcss-loader entirely.

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

Stylelint

webpack.config.js

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

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

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

or use [postcss-modules] instead of css-loader.

CSS-in-JS

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

{
  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
  2. You need to have only one default export per style module

[Extract CSS][ExtractPlugin]

webpack.config.js

const ExtractTextPlugin = require('extract-text-webpack-plugin')

module.exports = {
  module: {
    rules: [
      {
        test: /\.css$/,
        use: ExtractTextPlugin.extract({
          fallback: 'style-loader',
          use: [
            { loader: 'css-loader', options: { importLoaders: 1 } },
            'postcss-loader'
          ]
        })
      }
    ]
  },
  plugins: [
    new ExtractTextPlugin('[name].css')
  ]
}

© JS Foundation and other contributors
Licensed under the Creative Commons Attribution License 4.0.
https://webpack.js.org/loaders/postcss-loader