PostCSSとstylelintの環境構築

最近はSassからPostCSSへ移行する流れがあり、乗っかってみました。
ついでにstylelintでCSSの構文チェックできる設定もしたのでまとめて紹介します。

## PostCSSとは

PostCSS自体を説明するには難しいですが目的としては

```
CSSの開発効率・品質の向上のために使うもの
```

と捉えてもらえば良いかと思います。
具体的に何ができるかというと

* 仕様策定中の次世代CSSの先取り
* ベンダープレフィックスの自動付与
* 独自拡張機能の追加
* ファイルの結合・圧縮

などが挙げられます。

### Sassとの比較

なぜSassからPostCSSへ移行する流れがあるかというと

* トランスパイル時間が短い
* 仕様策定中の次世代CSSを先取りできる
* 独自機能を追加できる

などが挙げられます。
上記がメリットとならない場合は無理に導入する必要はないと思います。
例えば、すでにSassを導入していてスムーズに運用できているのであれば移行する必要はあまりなさそうです。
新規プロジェクトの時に導入するか検討すると良いかと思います。

## PostCSSを導入する

PostCSSはいろんなことができますが、今回は以下を導入する手順をまとめます。

* 仕様策定中の次世代CSSの先取り
* ベンダープレフィックスの自動付与
* 独自拡張機能（mixin、ユーティリティライブラリ）の追加
* ファイルの結合・圧縮

### 使用するパッケージ

* autoprefixer
* cssnano
* postcss
* postcss-apply
* postcss-cli
* postcss-custom-media
* postcss-custom-properties
* postcss-import
* postcss-mixins
* postcss-nesting
* postcss-reporter
* postcss-utilities
* stylelint

まとめてインストールします。
※次世代CSSはcssnextで一括提供していますが、使用するものだけに絞っています。

```
$ yarn add -D autoprefixer cssnano postcss postcss-apply postcss-cli postcss-custom-media postcss-custom-properties postcss-import postcss-mixins postcss-nesting postcss-reporter postcss-utilities stylelint
```

※yarnを使用していない人は上記の「yarn add」を「npm i」にして実行してください。


### 設定ファイルの作成

PostCSSを使用するには設定ファイルが必要です。
今回は以下のjsファイルを作成しましょう。

```js:postcss.config.js
module.exports = (ctx) => ({
  map: ctx.options.map,
  plugins: [
    require('postcss-import')({
      plugins: [
        require('stylelint')
      ]
    }),
    require('postcss-mixins'),
    require('postcss-utilities'),
    require('postcss-custom-properties'),
    require('postcss-custom-media'),
    require('postcss-nesting'),
    require('postcss-apply'),
    require('autoprefixer'),
    require('cssnano')
  ]
});
```

stylelintを使用しない場合は`postcss-import`のstylelintの記述を削除しましょう。

```js:postcss.config.js
module.exports = (ctx) => ({
// ...省略...
  plugins: [
    // ...省略...
    require('postcss-import'),
// ...省略...
});
```

#### 注意事項

パッケージによっては読み込みの順番が違うとエラーになってしまうものがあるようです。
今回の場合だとpostcss-importとpostcss-mixinsは先に読み込ませないとエラーになってしまいました。


### npm-scriptsの登録

postcss-cliを使って監視、ビルドそれぞれのタスクを用意します。

```js:package.json
{
  // ...省略...
  "scripts": {
    // ...省略...
    "watch:css": "postcss src/css/style.css -d dist/css -m -w",
    "build:css": "postcss src/css/style.css -d dist/css",
  },
  // ...省略...
}
```

### 運用フロー

開発時には監視、ソースマップの書き出しをおこないます。

```
$ yarn watch:css
```

納品時にはトランスパイルのみおこないます。

```
$ yarn build:css
```

※yarnを導入していない人は「yarn」を「npm run」にして実行してください。


## stylelintを導入する

stylelintはCSSの構文チェックツールです。
PostCSSのpluginsとして動作するようにしましたが、PostCSSと同じく設定ファイルが必要です。

### 設定ファイルの作成

設定ファイルは以下のように設定します。

```js:stylelint.config.js
module.exports = {
  extends: "stylelint-config-primer",
  rules: {
    "indentation": 2,
    // ...省略...
  }
}
```

extendsで設定ファイル集を読み込めます。
rulesで一つずつ設定でき、extendsを上書きすることができます。
ルールを細かく設定したい場合は[公式サイト](https://stylelint.io/)を確認しながら設定すると良いです。

個人的な話ですが、導入する際に以下の設定ファイル集を使ってサッと設定してしまおうと思いました。

* stylelint-config-standard: 最も一般的なCSSのコーディング規約集
* stylelint-config-primer: GitHubのCSSのコーディング規約

ですが、どうも自分好みに設定できないので結局公式サイトを読みながら一から設定しました。
細かく設定できるのですが、一日かかってしまいました。
公式サイトの英語を読むのがつらい人は日本語コメントをつけたので参考にどうぞ。
※すべてを網羅しているわけではないので悪しからず。

[stylelintの設定ファイル](https://gist.github.com/buchiya4th/f4ca1be2ab98ee5a8098fa68a93e752c)
※GitHubGistへ移行しました。


基本的に`always`や`never`で設定していくようです。複数行の場合は`always-multi-line`や`never-multi-line`で指定できるようです。
extendsが合わない人は上記をとりあえず突っ込んで、開発しながら不要なエラーの調整をおこなっていっても良いかもしれません。（慣例的な記述形式にしているつもりです。）
stylelint.config.jsを記述して格納しておけば、PostCSSを監視中はCLIでエラーを表示してくれます。

### エディタで監視

エディタにパッケージを追加することで、エディタ上でエラーの監視がリアルタイムでおこなえるので便利です。

* Atom
    * linter-stylelint
* Sublime Text
    * SublimeLinter-contrib-stylelint

※Sublime Text側のパッケージは検証していないので自己責任でお願いします。



### 無視する設定

normalize.cssなどの外部ライブラリは読み込むだけで修正したくない場合があります。
そんな時は`.stylelintignore`ファイルを作成して`.gitignore`の記述方式に従って記述すると無視できます。
例えば、以下のような階層の場合

```
/root/
  .stylelintignore
  /src/
    /css/
      /foundation/
        /vendor/
          無視したいCSSファイル
```

`.stylelintignore`には以下のように記述します。

```.gitignore:.stylelintignore
/src/css/foundation/vendor/**/*.css
```

すると`/src/css/foundation/vendor/`に入っているCSSファイルすべてを無視してくれます。
これで外部ライブラリは上記ディレクトリに格納するだけで一々手を加える必要がなくなります。
※上書きしたいものは別ファイルで改めて記述すると良いでしょう。


## さいごに

PostCSSやstylelintをうまく導入することで、開発効率や品質が上がると思います。
しかし、設定がうまくいかないと逆に設定に多くの時間を取られてしまいます。
フレームワークを使うとwebpackも検討する必要があります。
すぐにプロジェクトに導入するのではなく、ある程度把握してスムーズに設定できるようになってからプロジェクトに導入することをオススメします。
しっかり準備して次のプロジェクトに活かして効率化を図って早く帰りましょう。

### 参考

* PostCSS
    * [PostCSS とは何か](https://speakerdeck.com/jmblog/postcss-tohahe-ka)
    * [postcss - npm](https://www.npmjs.com/package/postcss)
    * [postcss-cli - npm](https://www.npmjs.com/package/postcss-cli)
    * [postcss-utilities](https://ismamz.github.io/postcss-utilities/)
    * [cssnextでみる次世代CSSとPostCSS](http://blog.yucchiy.com/2015/04/22/cssnext-postcss-for-nextgeneration-of-css/)
    * [cssnextから学ぶ次世代CSS](http://qiita.com/howdy39/items/92a7de771bbea99dbc7c)
    * [PostCSS まとめ](http://qiita.com/morishitter/items/4a04eb144abf49f41d7d)
    * [ぼちぼちPostCSSの勉強をやっちゃいますか](http://qiita.com/yuyake0084/items/301b716214e0352360c5)
    * [Sassを捨ててPostCSSに移行したのでそのときの工程メモ](http://qiita.com/nabeliwo/items/0aeea21e95f3fbab3955)
* stylelint
    * [stylelint](https://stylelint.io/)
    * [stylelintの設定ファイルの作り方](http://qiita.com/morishitter/items/fefa1de3137036c7d9c6)
    * [CSSのLintをstylelintにする](http://qiita.com/makotot/items/c266ed11ada1423cb96e)