webpackでPostCSSのポの字からはじめてみる

いまいちCSS界の波に乗れておらず今更感あるかもしれませんが、webpackでPostCSSを始めるときに最小限で手頃な情報がなかったので備忘録ということでまとめておきます:construction_worker:

※間違っているところ、無駄なところがあったら教えてください:bow_tone1:

# webpack & PostCSSの最小限の環境を構築する

## インストール

- webpack(v3.8.1)
- postcss(v6.0.14)
- css-loader(v0.28.7)
- postcss-loader(v2.0.8)
- style-loader(0.19.0)

※2017/11/20時点

### コマンド

```
npm i -D webpack postcss css-loader postcss-loader style-loader
```

## webpack.config.jsの作成

### ファイル構成

![スクリーンショット 2017-11-21 13.17.02.png](https://qiita-image-store.s3.amazonaws.com/0/55103/a41296cf-b7fa-5406-0e4a-519334066772.png)

### webpack.config.js

```js:webpack.config.js
const path = require('path')

const outputDirPath = path.resolve(__dirname, 'build/js');

module.exports = {
  entry: {
    entry: ['./src/index.js'],
  },

  output: {
    path: outputDirPath,
    filename: 'index.js'
  },

  module: {
    loaders: [
      {
        test: /\.css$/,
        use: [
          'style-loader',
          'css-loader',
          'postcss-loader'
        ]
      }
    ]
  }
};
```

## CSSをimportするjsファイルを作成

```js:index.js
import './index.css'
```

スタイルを記述する`src/index.css`をimportします。

### 実行

```
npm run webpack
```

実行すると`src/index.css`のスタイルが`src/index.js`にimportされ、`build/js/index.js`として書き出されます。

これでwebpackとPostCSSでCSSファイルをビルドする環境が整いました。ここから実用に向けて少しずつ機能を足していきます:thumbsup:

# ローカルにサーバーを立ててライブリロード

作業フォルダー内のCSSが更新されたら自動でブラウザが更新されるように設定します。`webpack-dev-server`を使います。

## インストール

- webpack-dev-server(v2.9.4)

※先に「webpack & PostCSSの最小限の環境を構築する」を実行してください。
※2017/11/20時点

### コマンド

```
npm i -D webpack-dev-server
```

## package.jsonの編集

`scripts`に実行するタスクを追加

- `build`  
ビルドタスク
- `start`
ローカルサーバーを立て、ファイルが更新されたかどうかを監視するタスク。

```json:package.json
{
  "name": "postcss-test",
  "version": "1.0.0",
  "license": "MIT",
  "scripts": {
    "build": "webpack",
    "start": "webpack-dev-server"
  },
  "devDependencies": {
    "css-loader": "^0.28.7",
    "postcss": "^6.0.14",
    "postcss-loader": "^2.0.8",
    "style-loader": "^0.19.0",
    "webpack": "^3.8.1",
    "webpack-dev-server": "^2.9.4"
  }
}

```

## webpack.config.jsの編集

```js:webpack.config.js
const path = require('path')

const outputDirPath = path.resolve(__dirname, 'build/', 'js');

module.exports = {
  entry: {
    entry: ['./src/index.js'],
  },

  output: {
    path: outputDirPath,
    filename: 'index.js'
  },

  module: {
    loaders: [
      {
        test: /\.css$/,
        use: [
          'style-loader',
          'css-loader',
          'postcss-loader'
          }
        ]
      }
    ]
  },

  // 追加
  devServer: {
    // サーバーで表示するディレクトリ
    contentBase: path.join(__dirname, "build"),
    // ビルドしたbundle.jsをhttp://localhost:8080/js/bundle.jsで参照できるように
    // ライブリロードが可能になる
    publicPath: '/js/',
    // contentBase以下のwebpackで管理していないファイルの更新でもリロードするように
    watchContentBase: true
  }
};
```

### 実行

`start`の前に`build`を実行してビルド後のファイルを用意しておく。

```
npm run build
npm run start
```

# Autoprefixerを導入

[Autoprefixer](https://github.com/postcss/autoprefixer)とは、

```css:適応前
a {
    display: flex;
}
```

が

```css:適応後
a {
    display: -webkit-box;
    display: -webkit-flex;
    display: -ms-flexbox;
    display: flex
}
```

のようにベンダープレフィックスを自動で流し込んでくれる。便利:metal:

## インストール

- autoprefixer(v7.1.6)

※先に「webpack & PostCSSの最小限の環境を構築する」を実行してください。
※2017/11/20時点

### コマンド

```
npm i -D autoprefixer
```

## webpack.config.jsの編集

```js:webpack.config.js
const path = require('path')
const autoprefixer = require('autoprefixer');

const outputDirPath = path.resolve(__dirname, 'build/', 'js');

module.exports = {
  entry: {
    entry: ['./src/index.js'],
  },

  output: {
    path: outputDirPath,
    filename: 'index.js'
  },

  module: {
    loaders: [
      {
        test: /\.css$/,
        use: [
          'style-loader',
          'css-loader',
          // 変更
          {
            loader: 'postcss-loader',
            options: {
              plugins: ()=>[
                autoprefixer
              ]
            }
          }
        ]
      }
    ]
  },

  devServer: {
    // サーバーで表示するディレクトリ
    contentBase: path.join(__dirname, "build"),
    // ビルドしたbundle.jsをhttp://localhost:8080/js/bundle.jsで参照できるように
    // ライブリロードが可能になる
    publicPath: '/js/',
    // contentBase以下のwebpackで管理していないファイルの更新でもリロードするように
    watchContentBase: true
  }
};
```

### 実行

ローカルサーバーが立ち上がり、CSSを更新したら自動でベンダープレフィックスを流し込んでくれる。

```
npm run start
```

# cssnextにある新しいCSS仕様を導入

[nextcss](http://cssnext.io/)では、新しいCSS仕様を使えるようにするPostCSSのプラグインが紹介されています。その中で気になったものを自分の環境に導入してみます。ここでは、`custom media queries`を導入してみます。他の仕様も同様の方法で追加できるので、試してみてください。

プラグイン名は[custom media queries](http://cssnext.io/features/#media-queries-ranges)にある[Plugin documentation](https://github.com/postcss/postcss-custom-media)で調べられます。

## インストール

- postcss-custom-media(v6.0.14)

※先に「webpack & PostCSSの最小限の環境を構築する」を実行してください。
※2017/11/20時点

### コマンド

```
npm i -D postcss-custom-media
```

## webpack.config.jsの編集

```js:webpack.config.js
const path = require('path')
const autoprefixer = require('autoprefixer');
const customMedia = require("postcss-custom-media");

const outputDirPath = path.resolve(__dirname, 'build/', 'js');

module.exports = {
  entry: {
    entry: ['./src/index.js'],
  },

  output: {
    path: outputDirPath,
    filename: 'index.js'
  },

  module: {
    loaders: [
      {
        test: /\.css$/,
        use: [
          'style-loader',
          'css-loader',
          {
            loader: 'postcss-loader',
            options: {
              plugins: ()=>[
                autoprefixer,
                // 追加
                customMedia
              ]
            }
          }
        ]
      }
    ]
  },

  devServer: {
    // サーバーで表示するディレクトリ
    contentBase: path.join(__dirname, "build"),
    // ビルドしたbundle.jsをhttp://localhost:8080/js/bundle.jsで参照できるように
    // ライブリロードが可能になる
    publicPath: '/js/',
    // contentBase以下のwebpackで管理していないファイルの更新でもリロードするように
    watchContentBase: true
  }
};
```

## 実行

```
npm run start
```

# まとめ

昔に比べてCSSって便利になってるんですね。あまりCSS情報を追えてなかったのでこれからちょこちょこアンテナ尖らせたいと思いました:thinking:

僕だけかもしれないのですが、プロジェクトの中盤以降は`webpack.config.js`を触らなくなって書き方をよく忘れるので、数カ月後の自分に役立てばいいな:relaxed:

バージョンが上がると動かなくなるのかな...