ぼちぼちPostCSSの勉強をやっちゃいますか

## はじめに

こんにちは、Sassに胸キュンしてる系エンジニアのゆーひです。
自分は今までGulpとSassを使った環境こそが至高だと思っていたのですが、最近はwebpackとPostCSSを用いた環境がイケイケらしいですね。
流行りに乗るってわけじゃないですが、最新技術を追いかけ続けないと**老害**になるんで「PostCSS？ああ、触れますよ？」とドヤ顔で言えるくらいにはなろうかなと思ったんでやってみました。

※今回はGulpでやります。老害ですごめんなさい。Gulpバンザイ。

## PostCSSとは？

PostCSSはNode.js製のモジュールで**CSSをコンパイルできる**ツールです。
そうなんです。LessやSassとは異なり、CSS拡張子をソースとして新しいCSSを生成してくれるんです。
PostCSSには様々なプラグインが豊富に用意されているので、自身の好きな様にカスタマイズすることも可能。
例としては、自動的にベンダープレフィクスを付与してくれたり、CSSの中で変数が使えたりCSSの圧縮をしてくれたりなどなど。

あれ、それって歴代CSSプリプロセッサーと変わんなくない？？
って自分は思ったんですが、そこに関しては次の項目で綴ります！

## PostCSSとSassの比較

### コンパイル速度

| PostCSS | Ruby Sass | Less |
|:--------|:----------|:-----|
| 36ms（0.036秒） | 1084ms（1.084秒） | 160ms（0.16秒） |

どうやら非常に速いらしいですね。

引用元: https://speakerdeck.com/jmblog/postcss-tohahe-ka?slide=55

### 学習コスト

記法的には歴代CSSプリプロセッサーと大差ないようです。
ただ、プラグイン次第ではCSSのモダンな書き方を求められるみたいですね。
それは後述します。

### 環境設定

- [gulp](https://github.com/gulpjs/gulp)
- [gulp-postcss](https://github.com/postcss/gulp-postcss)

Gulp上でPostCSSを動かすにあたって最低限必須となるモジュール上記2点です。
そしてgulpfileは以下の様にします。

```js:gulpfile.js
const gulp = require('gulp');
const postCss = require('gulp-postcss');

gulp.task('css', () => {
  return gulp.src('./src/*.css')
    .pipe(postCss())
    .pipe(gulp.dest('./dist'));
});

gulp.task('default', ['css'], () => gulp.watch('./src/*.css', ['sass']));
```

あとは適当にsrcディレクトリなんか作ってその中にstyle.cssとか用意すれば準備完了ですね。
プラグインの読み込ませ方としてはGulpのパイプラインの中で実行している`postCss()`の引数の中に配列で渡してあげることによって利用することができます。

```js:gulpfile.js
// 例

//...以上略

const customProperties = require('postcss-custom-properties');

gulp.task('css', () => {
  return gulp.src('./src/*.css')
    .pipe(postCss([
      customProperties
    ]))
    .pipe(gulp.dest('./dist'));
});

//...以下略

```

## 実行

ともあれ動かさない事には何も始まりませんし、分かりません。
実際に動かしてみましょう。

`$ gulp`

※事前にテキストエディタにPostCSS専用シンタックスハイライトをインストールしておく事をオススメします。
[Syntax Highlighting for PostCSS](https://github.com/hudochenkov/Syntax-highlighting-for-PostCSS)

## プラグイン

### 変数

歴代CSSプリプロセッサー同様、変数定義が可能です。

- [postcss-simple-vars](https://github.com/postcss/postcss-simple-vars)
- [postcss-custom-properties](https://github.com/postcss/postcss-custom-properties)

最近は上記の2種類がよく使われている様ですね。
CSS上で変数が使えるというのは変わらないんですが、記法が変わります。

```css:postcss-simple-vars.css
$blue: #20aee5;

.hoge {
  color: $blue;
}
```

```css:postcss-custom-properties.css
:root {
  --color: #20aee5;
}

.hoge {
  color: var(--color);
}
```

上記の方はSassでもお馴染みな書き方ですが、下記の方はいかがでしょう。
Sassしか触ったことのない自分からしてみたら全く見慣れない記法です。

調べてみたところ、これは[Future CSS Syntax](http://basscss.com/v7/docs/guides/future-css/)と呼ばれる次世代型CSSの記法だそうです。つまりいずれはどのブラウザでも使えるようになるであろう書き方という事ですね。
JSでいうところのES2015みたいな位置付けだと勝手に解釈しています。

### 別ファイルの読み込み

- [postcss-import](https://github.com/postcss/postcss-import)

importは非常に便利ですよね。いつもお世話になっております。
記法も特に変わりはありません。

```css:postcss-import.css
@import "layout/header";
```

### ネスト

- [postcss-nested](https://github.com/postcss/postcss-nested)

この入れ子記法、ちゃんと管理されてる感があって個人的にすごい好きです。
記述も従来の通りですね。

```css:postcss-nested.css
.hoge {
  color: $blue;

  & > li {
    width: 20%;
  }
}
```

### Mixin

- [postcss-mixins](https://github.com/postcss/postcss-mixins)

これもお馴染みの機能ですね。
ただ、若干Sassとは記法が違うみたいです。
`define`って意味が分からなかったんでググってみたら『定義』するという意味で、`define-mixin`っていうのはMixinを定義するという意味みたいです。

```css:postcss-mixins.css
@define-mixin btn $width, $color {
  width: $width;
  padding: 10px 20px;
  color: $color;
}
.hoge-btn {
  @mixin btn 200px, $blue;
}
```

余談ですが、個人的にCSSにおける継承はコードの複雑化、膨大化を招く恐れがあると考えているので、あまり好んで使っていませんね。
ただ、CSSにプログラミング的な考えを持って来るって発想はいいなと思ってます。

### Placeholder

- [postcss-extend](https://github.com/travco/postcss-extend)

Mixinと同じ意見。

```css:postcss-extend.css
.default-link {
  width: 100px;
  font-size: 20px;
}

.hoge-link {
  @extend .default-link;
  font-size: 30px;
}
```

## まとめ

### 学習コスト
何かしらのCSSプリプロセッサーを触った事がある人ならば、問題なく使えるんじゃないかと思います。

### 歴代CSSプリプロセッサーからPostCSSへの乗り換え

新規プロジェクトでPostCSSを使うのは全然いいと思います。
ただ、既にSassなどでがっつり書かれているプロジェクトが、工数をかけてまでPostCSSに移行するメリットはほぼ無いと思われるのでやらない方がいいかもしれない。
※工数かけてでもデプロイの時間を短縮したいとかいうパターンはあるかも。

とまぁ所感としてはこんなかんじですかね。
あとwebpackも触れるようになります。がんばります。

## 余談

PostCSSのロゴなんですけれど、

<img width="980" alt="postcss_1.png" src="https://qiita-image-store.s3.amazonaws.com/0/88810/e59d066c-fea2-2a81-6e24-3a09c09d879a.png">

**某錬金術師漫画**に出てくる**あの人のアレ**にそっくりだなぁと思いました。
ではでは。

![hagane_31g.jpg](https://qiita-image-store.s3.amazonaws.com/0/88810/cdb12d90-5d1a-860c-4571-4678baeecbf1.jpeg)