【webpack2対応】俺が作り上げたSCSSのビルド環境を晒す【リントもあるよ】

# はじめに

もともと業務でscssを使うための環境を作ってたのですが、ちょっと~~後輩に丸投げしてた~~目を離した隙にwebpack周りも色々と状況が変わっていたので、これを機に色々調べ直して設定し直したりしました。

## やりたかったこと

* webpackでscssをビルドする
* jsで出力されるのは困るのでcssで出力する
* ベンダープレフィックスは自動でつけてほしい ~~-mozとか書きたくない~~
* リントチェック欲しいなぁ...
 * まぁ、これはwebpackじゃなくていいか

# webpack2でのscssのビルド

## パッケージインストール

まずは必要なパッケージを入れましょう。
今回scssのビルドに使ったパッケージは

* autoprefixer
* css-loader
* extract-text-webpack-plugin
* node-sass
* postcss-loader
* precss
* sass-loader
* style-loader
* webpack

これらを片っ端から`npm install --save-dev`していきます。
[以前](http://qiita.com/Mic-U/items/2c00fd911adca86e670d)に「gulpはプラグインだらけで辛いんじゃあ」と嘆きましたが、webpackも結構いっぱいインストールしなきゃいけないっすね。

## scssファイルを用意

今回晒すのはあくまでサンプルなのでかなり適当なファイルを用意します。

```scss:src/main.scss
@charset "UTF-8";

body {
  :fullscreen a {
    display: flex
  }
}
```

後でautoprefixerの仕事ぶりを確認したいので、autoprefixerの[公式のサンプル](https://github.com/postcss/autoprefixer)のものを流用しています。

## webpackの設定

上述の通り、webpack2になって設定の書き方が結構変わりました。
大まかな点としては

* module.loaders -> module.rulesに変更
* loaderの書き方がloader:"style-loader!css-loader"みたいな呪文からuse:["style-loader","css-loader"]みたいに配列でかけるようになった

詳しくは↓のリンクを参照してください

* [webpack2へ移行する軽いメモ](http://abouthiroppy.hatenablog.jp/entry/2017/02/03/212817)
* [Migrating from v1 to v2](https://webpack.js.org/guides/migrating/)

てなわけで色々と参考にして出来上がったのがこちら
前提として、src/scss/main.scssをエントリーポイントとして、最終的にdist/style.cssに出力します。
cssで出力するため、extract-text-webpack-pluginも使います。
「いや、アセット置くのはpublicディレクトリでしょ」という方はoutput.pathをよしなに変更しましょう。

```js:webpack.config.js
"use strict";
const path = require("path");
const webpack = require("webpack");
const ExtractTextPlugin = require("extract-text-webpack-plugin");
const autoprefixer = require("autoprefixer");
const precss = require("precss");

module.exports = {
  entry: {
    style: path.join(__dirname, "src/scss/main.scss")
  },
  output: {
    path: path.join(__dirname, 'dist'),
    filename: '[name].css'
  },
  module: {
    rules: [
      {
        test: /\.css$/,
        use: ExtractTextPlugin.extract({
          fallback: "style-loader",
          use: ["css-loader", "postcss-loader"]
        })
      },
      {
        test: /\.scss$/,
        use: ExtractTextPlugin.extract({
          fallback: "style-loader",
          use: ["css-loader", "postcss-loader", "sass-loader"]
        })
      }
    ]
  },
  plugins: [
    new ExtractTextPlugin('style.css'),
    new webpack.LoaderOptionsPlugin({
      options: {
        postcss: [
          autoprefixer({ browsers: ['last 2 versions'] }),
          precss
        ]
      }
    })
  ]
};

```

postcssの設定がv1でしたら

```js
module.exports = {
  // 省略
  postcss: [
    autoprefixer({ browsers: ['last 2 versions'] }),
    precss
  ]
};
```

みたいにトップレベルでかけたのですが、v2は許してくれません。
ちゃんとwebpack.LoaderOptionsPluginを使いましょう。

## package.jsonにコマンド登録

ここまでできたら`./node_modules/.bin/webpack --config webpack.config.js`で実行できますけど、毎回こんなの入力したくないですよね。
私はこれを自分で入力すると毎回`--config`を`-c`って書いちゃって怒られます。なんかいけそうな感じするじゃないですか。
まあ、あとこのコマンドだけ見ても「webpackでなんかしてるんやろなぁ」しかわからないのも後々災いを招きそうですね。

というわけでpackage.jsonにコマンドを登録します。

```json:package.json
{
  // 省略
  "scripts": {
    "scss-build": "webpack --config webpack.config.js"
  }
  // 省略
}
```

これで`npm run scss-build`でコンパイルが走ります。
これならオプションとかを自分で打つ必要がないので間違いも減りますし、「scss-buildってことはscssをビルドするんやな」とわかりますね。

<img width="871" alt="スクリーンショット 2017-03-18 8.04.13.png" src="https://qiita-image-store.s3.amazonaws.com/0/116434/98dbb0d5-f47e-88f5-3271-2f6ce71d5559.png">

無事にビルドは成功

<img width="1256" alt="スクリーンショット 2017-03-18 8.05.41.png" src="https://qiita-image-store.s3.amazonaws.com/0/116434/6062d59f-5a0c-d281-6995-e7eaffb55da9.png">

ベンダープレフィックスもちゃんと付与されてますね。
これでもう-webkitとか-mozとか書かんでええんや!
ありがとう、autoprefixer!

# scssもリントしたい

ESLintとかTSLintとかはすでに導入してその恩恵に預かりまくってたのですが、ある日ふと「scssのリントツールって聞いた覚えがないけどあるのだろうか。いや、きっとどこかの誰かが作ってるはずだ」と思い調べて見つけたのが[scss-lint](https://github.com/brigade/scss-lint)。

しかしinstallationを見ると

`gem install scss_lint`

**Rubyかよ!!**(Ruby環境を構築してない者の嘆き)

というわけで一旦これは保留してもう一度調べ直したら見つかったのが[sass-lint](https://github.com/sasstools/sass-lint)

README.mdの冒頭には

> A Node-only Sass linter for both sass and scss syntax!
> (筆者訳)Node.jsだけで動くリンターやで! sass記法もscss記法もカバーしてるで!

の一文。これにはJS民もニッコリですね。

というわけでこいつを使ってみます。

`npm install --save-dev sass-lint`

## 設定ファイル作成

さて、次にsass-lint用の設定ファイルを作りますが、README.mdによると.sass-lint.ymlというファイルでYAMLで書くのがお作法なようです。

```yaml:.sass-lint.yml
files:
#  Lint対象のファイル
  include:
    - "src/scss/**/*.scss"
```

とりあえずリントチェックの対象のファイルだけ設定します。他のディレクトリからも読み込みたい時はincludeの下につけ足していきましょう。
逆に「こいつはリントしなくてええんやで」って時は

```yaml:.sass-lint.yml
files:
#  Lint対象のファイル
  include:
    - "src/scss/**/*.scss"
# 無視するファイル
  ignore:
    - "src/scss/**/*.scss"
    - "src/scss/**/*.scss"
```

て感じでignoreに項目を追加していきます。

## リントルールの設定

さて、リントツール導入の最大の山場であるリントルールの設定です。
sass-lintでは.sass-lint.ymlにルールを書いていきます。

```yaml:.sass-lint.yml
files:
#  Lint対象のファイル
  include:
    - "src/scss/**/*.scss"

rules:
  indentation: # インデントの設定
    - 2        # 深刻度 0 -> 無視, 1 -> 警告, 3 -> エラー
    -
      size: 2  # ルールごとのオプション
```

ちょっと書き方に癖があるのですが基本的にはrulesの下にルール名を置く(↑ではindentation)
ルール名の深刻度とルールごとに定められてるオプションを設定するという流れです。
あとは[公式のドキュメント](https://github.com/sasstools/sass-lint/tree/master/docs/rules)を見ながら一つずつ設定していきます。
途中読み飛ばしたくなりますが**ルールによってはデフォルト設定のせいで想定外の結果を吐き出すこと(ダブルコーテーション使いまくってたのにデフォルト設定がダブルコーテーション禁止だったり)があるので必ず全て目を通しましょう**。
大事なのは挫けない心です。数えて見たらsass-lintのルールは73個あり、ドキュメントは英語しかありません。~~「英語読めません」が許されるのは小学生までだよね~~

## package.jsonにコマンド登録

これもpackage.jsonにコマンドを登録しておきましょう

```json:package.json
{
  // 省略
  "scripts": {
    "scss-build": "webpack --config webpack.config.js",
    "scss-lint": "sass-lint -c .sass-lint.yml -v"
  },
  // 省略
}
```

こっちは-c オプションで設定ファイルを指定できるんですよね、ややこしいことに。
あと-vは結果を詳細に見るためのオプションです。

それでは`npm run scss-lint`を実行してみましょう。

<img width="773" alt="スクリーンショット 2017-03-18 8.45.33.png" src="https://qiita-image-store.s3.amazonaws.com/0/116434/5f93d6b8-2e7d-1a79-08d4-ac453523a317.png">

デフォルトのルール設定で何個か引っかかってるみたいですね。
ちなみに全く同じscssに対して-vオプションを外した時はこうなります

<img width="867" alt="スクリーンショット 2017-03-18 8.48.12.png" src="https://qiita-image-store.s3.amazonaws.com/0/116434/ead47ca4-683e-2eb7-543d-02b433d0d4fc.png">

**おい、警告出せよ(怒)!**
というわけで-vオプションはつけて置くことを推奨します。

# 参考

* [webpack](https://webpack.js.org)
* [autoprefixer](https://github.com/postcss/autoprefixer)
* [sass-lint](https://github.com/sasstools/sass-lint)
* [webpack2へ移行する軽いメモ](http://abouthiroppy.hatenablog.jp/entry/2017/02/03/212817)
* [Webpack2でpostcssを使う](http://qiita.com/namazu510/items/beb930472a4b76c2fd64)