{Boolean}
npm i -D postcss-loader postcss
Configuration
postcss.config.js
module.exports = {
parser: 'sugarss',
plugins: {
'postcss-import': {},
'postcss-preset-env': {},
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 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).
webpack.config.js
module.exports = {
module: {
rules: [
{
test: /\.css$/,
use: ['style-loader', 'postcss-loader'],
},
],
},
};
⚠️ When
postcss-loader
is used standalone (withoutcss-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',
],
},
],
},
};
Name | Type | Default | Description |
---|---|---|---|
Name Type Default Description
|
{Boolean} |
undefined |
Enable PostCSS Parser support in
CSS-in-JS |
Name Type Default Description
|
{String\|Object\|Boolean} |
undefined |
Set
postcss.config.js
config path &&
ctx |
Name Type Default Description
|
{Object} |
defaults values for Postcss.process |
Set Postcss.process options and postcss plugins |
Name Type Default Description
|
{Boolean} |
compiler.devtool |
Enables/Disables generation of source maps |
Exec
Type: Boolean
Default: undefined
If you use JS styles without the postcss-js
parser, add the exec
option.
webpack.config.js
module.exports = {
module: {
rules: [
{
test: /\.style.js$/,
use: [
'style-loader',
{ loader: 'css-loader', options: { importLoaders: 1 } },
{
loader: 'postcss-loader',
options: {
postcssOptions: {
parser: 'sugarss',
},
exec: true,
},
},
],
},
],
},
};
Config
Type: Boolean|String|Object
Default: undefined
Options specified in the config file are combined with options passed to the loader. Loader options overwrite options from config.
Enables/Disables autoloading config.
webpack.config.js
module.exports = {
module: {
rules: [
{
test: /\.css$/i,
loader: 'postcss-loader',
options: {
config: false,
},
},
],
},
};
Allows to specify the absolute path to the config file.
webpack.config.js
module.exports = {
module: {
rules: [
{
test: /\.css$/i,
loader: 'postcss-loader',
options: {
config: path.resolve(__dirname, 'custom.config.js'),
},
},
],
},
};
Name | Type | Default | Description |
---|---|---|---|
Name Type Default Description
|
{String} |
undefined |
PostCSS Config Directory |
Name Type Default Description
|
{Object} |
undefined |
PostCSS Config Context |
Path
Type: String
Default: undefined
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
module.exports = {
module: {
rules: [
{
test: /\.css$/i,
loader: 'postcss-loader',
options: {
config: {
path: 'path/to/.config/', // ✅
path: 'path/to/.config/css.config.js', // ❌
},
},
},
],
},
};
Context (ctx)
Type: Object
Default: undefined
Name | Type | Default | Description |
---|---|---|---|
Name Type Default Description
|
{String} |
'development' |
process.env.NODE_ENV |
Name Type Default Description
|
{Object} |
loader.resourcePath |
extname
,
dirname
,
basename |
Name Type Default Description
|
{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: [
// Plugins with options and without
['postcss-import', { root: file.dirname }],
'postcss-preset-env',
],
});
webpack.config.js
module.exports = {
module: {
rules: [
{
test: /\.css$/i,
loader: 'postcss-loader',
options: {
config: {
ctx: {
'postcss-preset-env': { ...options },
cssnano: { ...options },
},
},
},
},
],
},
};
postcssOptions
Name | Type | Default | Description |
---|---|---|---|
Name Type Default Description
|
{Function\|Object\|Array<Function\|Object>} |
[] |
Set PostCSS Plugins |
Name Type Default Description
|
{String\|Object\|Function} |
undefined |
Set custom PostCSS Parser |
Name Type Default Description
|
{String\|Object} |
undefined |
Set custom PostCSS Syntax |
Name Type Default Description
|
{String\|Object\|Function} |
undefined |
Set custom PostCSS Stringifier |
Plugins
Type: Function|Object|Array<String|Function\|Object|Array>
Default: []
It is recommended to specify plugins in the format Array<String\|Array>
or Function
that returns the same array as shown below.
Object
format ({pluginName: pluginOptions}
) is deprecated and will be removed in the next major release.
webpack.config.js
module.exports = {
module: {
rules: [
{
test: /\.css$/i,
loader: 'postcss-loader',
options: {
plugins: [
'postcss-import',
'postcss-nested',
['postcss-short', { prefix: 'x' }],
],
},
},
],
},
};
webpack.config.js
module.exports = {
module: {
rules: [
{
test: /\.css$/i,
loader: 'postcss-loader',
options: {
plugins: (loader) => [
['postcss-import', { root: loader.resourcePath }],
'postcss-nested',
'cssnano',
],
},
},
],
},
};
webpack.config.js
module.exports = {
module: {
rules: [
{
test: /\.css$/i,
loader: 'postcss-loader',
options: {
postcssOptions: {
plugins: (loader) => [
require('postcss-import')({ root: loader.resourcePath }),
require('postcss-preset-env')(),
require('cssnano')(),
],
},
},
},
],
},
};
⚠️ The method below for specifying plugins is deprecated.
webpack.config.js
module.exports = {
module: {
rules: [
{
test: /\.css$/i,
loader: 'postcss-loader',
options: {
plugins: {
'postcss-import': {},
'postcss-nested': {},
'postcss-short': { prefix: 'x' },
},
},
},
],
},
};
It is possible to disable the plugin specified in the config.
postcss.config.js
module.exports = {
plugins: {
'postcss-short': { prefix: 'x' },
'postcss-import': {},
'postcss-nested': {},
},
};
webpack.config.js
module.exports = {
module: {
rules: [
{
test: /\.css$/i,
loader: 'postcss-loader',
options: {
postcssOptions: {
plugins: {
'postcss-import': {},
'postcss-nested': {},
// Turn off the plugin
'postcss-short': false,
},
},
},
},
],
},
};
Parser
Type: String|Object|Function
Default: undefined
String
The passed string
is converted to the form require('string')
.
webpack.config.js
module.exports = {
module: {
rules: [
{
test: /\.sss$/i,
loader: 'postcss-loader',
options: {
postcssOptions: {
// Will be converted to `require('sugarss')`
parser: 'sugarss',
},
},
},
],
},
};
Object
webpack.config.js
module.exports = {
module: {
rules: [
{
test: /\.sss$/i,
loader: 'postcss-loader',
options: {
postcssOptions: {
parser: require('sugarss'),
},
},
},
],
},
};
Function
webpack.config.js
module.exports = {
module: {
rules: [
{
test: /\.sss$/i,
loader: 'postcss-loader',
options: {
postcssOptions: {
parser: require('sugarss').parse,
},
},
},
],
},
};
Syntax
Type: String|Object
Default: undefined
String
The passed string
is converted to the form require('string')
.
webpack.config.js
module.exports = {
module: {
rules: [
{
test: /\.css$/i,
loader: 'postcss-loader',
options: {
postcssOptions: {
// Will be converted to `require('sugarss')`
syntax: 'sugarss',
},
},
},
],
},
};
Object
webpack.config.js
module.exports = {
module: {
rules: [
{
test: /\.css$/i,
loader: 'postcss-loader',
options: {
postcssOptions: {
stringifier: require('sugarss'),
},
},
},
],
},
};
Stringifier
Type: String|Object|Function
Default: undefined
String
The passed string
is converted to the form require('string')
.
webpack.config.js
module.exports = {
module: {
rules: [
{
test: /\.css$/i,
loader: 'postcss-loader',
options: {
postcssOptions: {
// Will be converted to `require('sugarss')`
stringifier: 'sugarss',
},
},
},
],
},
};
Object
webpack.config.js
module.exports = {
module: {
rules: [
{
test: /\.css$/i,
loader: 'postcss-loader',
options: {
postcssOptions: {
stringifier: require('sugarss'),
},
},
},
],
},
};
Function
webpack.config.js
const Midas = require('midas');
const midas = new Midas();
module.exports = {
module: {
rules: [
{
test: /\.css$/i,
loader: 'postcss-loader',
options: {
postcssOptions: {
stringifier: midas.stringifier,
},
},
},
],
},
};
SourceMap
Type: Boolean
Default: depends on the compiler.devtool
value
By default generation of source maps depends on the devtool
option. All values enable source map generation except eval
and false
value.
webpack.config.js
module.exports = {
module: {
rules: [
{
test: /\.css$/i,
use: [
{ loader: 'style-loader' },
{ loader: 'css-loader', options: { sourceMap: true } },
{ loader: 'postcss-loader', options: { sourceMap: true } },
{ loader: 'sass-loader', options: { sourceMap: true } },
],
},
],
},
};
Stylelint
webpack.config.js
module.exports = {
module: {
rules: [
{
test: /\.css$/i,
use: [
'style-loader',
'css-loader',
{
loader: 'postcss-loader',
options: {
postcssOptions: {
plugins: ['postcss-import', 'stylelint'],
},
},
},
],
},
],
},
};
Autoprefixing
webpack.config.js
module.exports = {
module: {
rules: [
{
test: /\.css$/i,
use: [
'style-loader',
'css-loader',
{
loader: 'postcss-loader',
options: {
postcssOptions: {
plugins: [['autoprefixer', { ...options }]],
},
},
},
],
},
],
},
};
:warning:
postcss-preset-env
includesautoprefixer
, 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
module.exports = {
module: {
rules: [
{
test: /\.css$/i,
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.
webpack.config.js
module.exports = {
module: {
rules: [
{
test: /\.style.js$/,
use: [
'style-loader',
{ loader: 'css-loader', options: { importLoaders: 2 } },
{
loader: 'postcss-loader',
options: {
postcssOptions: {
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
- Add babel-plugin-add-module-exports to your configuration
- You need to have only one default export per style module
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',
}),
],
};
Emit assets
To write a asset from the postcss plugin to the webpack's output file system, need to add a message in result.messages
.
The message should contain the following fields:
type
= asset
- Message type (require, should be equal asset
)file
- file name (require)content
- file content (require)sourceMap
- sourceMapinfo
- asset infowebpack.config.js
const customPlugin = () => (css, result) => {
result.messages.push({
type: 'asset',
file: 'sprite.svg',
content: '<svg>...</svg>',
});
};
const postcssPlugin = postcss.plugin('postcss-assets', customPlugin);
module.exports = {
module: {
rules: [
{
test: /\.css$/i,
use: [
'style-loader',
'css-loader',
{
loader: 'postcss-loader',
options: {
postcssOptions: {
plugins: [postcssPlugin()],
},
},
},
],
},
],
},
};
Add dependencies
There are two way to add dependencies:
result.messages
.The message should contain the following fields:
type
= dependency
- Message type (require, should be equal dependency
)file
- absolute file path (require)webpack.config.js
const path = require('path');
const customPlugin = () => (css, result) => {
result.messages.push({
type: 'dependency',
file: path.resolve(__dirname, 'path', 'to', 'file'),
});
};
const postcssPlugin = postcss.plugin('postcss-assets', customPlugin);
module.exports = {
module: {
rules: [
{
test: /\.css$/i,
use: [
'style-loader',
'css-loader',
{
loader: 'postcss-loader',
options: {
postcssOptions: {
plugins: [postcssPlugin()],
},
},
},
],
},
],
},
};
loaderContext
in plugin.webpack.config.js
module.exports = {
module: {
rules: [
{
test: /\.css$/i,
use: [
'style-loader',
'css-loader',
{
loader: 'postcss-loader',
options: {
config: 'path/to/postcss.config.js',
},
},
],
},
],
},
};
postcss.config.js
module.exports = (loaderContext) => ({
postcssOptions: {
plugins: [require('path/to/customPlugin')(loaderContext)],
},
});
customPlugin.js
const path = require('path');
const customPlugin = (loaderContext) => (css, result) => {
loaderContext.webpack.addDependency(
path.resolve(__dirname, 'path', 'to', 'file')
);
};
module.exports = postcss.plugin('postcss-assets', customPlugin);
Michael Ciniawsky | Alexander Krasnoyarov |