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

  • 4
    いいね
  • 0
    コメント

はじめに

もともと業務で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していきます。
以前に「gulpはプラグインだらけで辛いんじゃあ」と嘆きましたが、webpackも結構いっぱいインストールしなきゃいけないっすね。

scssファイルを用意

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

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

body {
  :fullscreen a {
    display: flex
  }
}

後でautoprefixerの仕事ぶりを確認したいので、autoprefixerの公式のサンプルのものを流用しています。

webpackの設定

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

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

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

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

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でしたら

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にコマンドを登録します。

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

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

スクリーンショット 2017-03-18 8.04.13.png

無事にビルドは成功

スクリーンショット 2017-03-18 8.05.41.png

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

scssもリントしたい

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

しかしinstallationを見ると

gem install scss_lint

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

というわけで一旦これは保留してもう一度調べ直したら見つかったのが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で書くのがお作法なようです。

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

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

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

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

リントルールの設定

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

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

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

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

package.jsonにコマンド登録

これもpackage.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を実行してみましょう。

スクリーンショット 2017-03-18 8.45.33.png

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

スクリーンショット 2017-03-18 8.48.12.png

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

参考

* webpack
* autoprefixer
* sass-lint
* webpack2へ移行する軽いメモ
* Webpack2でpostcssを使う