PostCSS x Webpack

PostCSSを試してみました。JSで言うところのBabelのようなモノという理解です。

PostCSSについてはPostCSSの概要と書き方の記事が分かりやすかったです。


Loaderとプラグインをインストールする

postcss-loaderと、今回は以下のプラグインをインストールしておきます。

  • precss ... Sassライクなシンタクスで書くためのプラグイン
  • autoprefixer ... ベンダープレフィックスを自動で付加してくれるプラグイン
% npm i -D postcss-loader precss autoprefixer

webpack.config.jsに以下を追加します。

const precss = require('precss');              // <-- 追加  
const autoprefixer = require('autoprefixer');  // <-- 追加

module.exports = {  
  ...

  resolve: {
    extensions: ['', '.js', '.jsx', '.css']
  },

  module: {
    loaders: [
      ...

      {
        test: /\.css$/,
        loaders: ['style', 'css', 'postcss'],  // <-- 'postcss'を追加
        include: APP
      }
    ]
  },

  postcss: function() {
    return [precss, autoprefixer];
  }
};

Production用にExtractTextPluginを使用する場合には、loadersの部分は以下のようになります。

loader: ExtractTextPlugin.extract('style', 'css!postcss'),  

loader[s]ではなくで、loaderです。

とりあえず、アプリケーションのルートディレクトリにstyle.cssを作り、適当なスタイルを定義し動くか試しておきます。

/* app/style.css */
body { background-color: #ccc; }  

stylesディレクトリを作って、この中にCSSのモジュールを作ることにします。まずは#cccを背景色として変数化してみます。

/* app/styles/variables.css */
$gray: #css;
/* app/styles/base.css */
body { background-color: $gray; }  

元のstyle.cssはこれらのモジュールを読みこむだけに変更。

/* app/style.css */
@import 'styles/variables';
@import 'styles/base';

ここで、style.cssを更新すると"Hot Module Replacement"が効くのですが、styles以下のファイルでは効かないようです。この場合はpostcss-importプラグインを利用します。

% npm i -D postcss-import
// webpack.config.js

...
const PostcssImport = require('postcss-import');

module.exports = {  
  ...

  postcss: function(webpack) {
    return [
      PostcssImport({
        addDependencyTo: webpack
      }), // <-- 先頭に追加する
      precss,
      autoprefixer
    ];
  },
  ...
};

これで、variables.cssの変数の値を変更すると、HMRが効くはずです。

同様に、ネストと@extendも試してみます。

// index.jsx
import React from 'react';  
import {render} from 'react-dom';

function Hello(props) {  
  return (
    <div>
      <h1>
          <span className="greeting">Hell<span class="o">o</span><span>
          <span className="name">{props.name}</span>.
      </h1>
    </div>
  );
}

render(<Hello name="PostCSS" />, document.getElementById('app'));  
.heading {
  font-weight: bold;
  font-size: 60px;
}

h1 {

  @extend .heading;

  .greeting {
    .o {
      color: blue;
    }
  }

  .name {
    color: red;
  }
}

Sassのように@extendやネストも使えました。