Skip to content

How to include PostCSS

Sam Vloeberghs edited this page Feb 25, 2016 · 9 revisions

Overview

We want to be able to use any and all PostCSS plugins to process our styles and then apply those styles to components using view encapsulation.

It's been mentioned in the including SCSS wiki article that you need to use the raw-loader. The reason for that is, when Webpack requires styles the css-loader or sass-loader will return a Javascript object that is meant to be parsed by something like the style-loader. However, this is not ideal when using Angular2 as it's become a very popular pattern to scope your styles with view encapsulation using syntax like this:

@Component({
  selector: 'test-component',
  template: require('./template.html'),
  styles: [
    require('./styles.css') //<-- Including the style
  ]
})
export class TestComponent {
  
}

The raw-loader solves this by interpreting the styles required as a string. We can now safely pass styles from the css-loader or scss-loader into the raw loader, and it will spit out a string that we can give to the component's styles array.

So what about PostCSS?

The postCSS-loader is quite a bit different. When passing results from it to the raw-loader you end up with a string like this:

exports = module.exports = require("./../../node_modules/css-loader/lib/css-base.js")();
// imports


// module
exports.push([module.id, ":root {\n  background-color: blue;\n}\n", ""]);

// exports

Obviously not ideal, it seems like the PostCSS loader is doing some magic importing that the raw-loader is interpreting as a string. Luckily there's a webpack plugin called to-string-loader designed to take the Webpack styles object and cast it to a string. Let's take a look at how to configure that.

Step by Step OR TL:DR

  • Install postcss-loader, css-loader, to-string-loader and desired postCSS plugins (in this example cssnext)
npm install --save-dev postcss-loader css-loader to-string-loader postcss-cssnext
  • Create loader configuration for PostCSS. As part of your loaders array in webpack.config.js and webpack.prod.config.js add:
[
    //...
    { test: /\.css$/,   loader: 'to-string!css-loader!postcss-loader'},
    //...
]
  • Add in any postCSS plugin. As part of your module.exports object in webpack.config.js and webpack.prod.config.js add:
module.exports = {
    //...
    postcss: [
        require('postcss-cssnext')({
            browsers: ['ie >= 9', 'last 2 versions']
        })
    ],
    //...
}

(optional) Use with SASS / SCSS

Using this together with SASS and sass-loader is simple. Just put the sass-loader before the execution of the postcss-loader:

[
    //...
    {
      test: /\.scss$/,
      exclude: /node_modules/,
      loader: 'to-string!css-loader!postcss-loader!sass-loader'
    },
    //...
]

Success

We can now include postCSS into our project and still keep the great scoping that Angular 2 provides.

as a breif aside, make sure you're using the :host selector in your css files. Otherwise the scoping could break.

:host { //<-- Targets component.
  color: red;
}

Clone this wiki locally