はじめに
もともと業務で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ファイルを用意
今回晒すのはあくまでサンプルなのでかなり適当なファイルを用意します。
@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をよしなに変更しましょう。
"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にコマンドを登録します。
{
// 省略
"scripts": {
"scss-build": "webpack --config webpack.config.js"
}
// 省略
}
これでnpm run scss-build
でコンパイルが走ります。
これならオプションとかを自分で打つ必要がないので間違いも減りますし、「scss-buildってことはscssをビルドするんやな」とわかりますね。
無事にビルドは成功
ベンダープレフィックスもちゃんと付与されてますね。
これでもう-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で書くのがお作法なようです。
files:
# Lint対象のファイル
include:
- "src/scss/**/*.scss"
とりあえずリントチェックの対象のファイルだけ設定します。他のディレクトリからも読み込みたい時はincludeの下につけ足していきましょう。
逆に「こいつはリントしなくてええんやで」って時は
files:
# Lint対象のファイル
include:
- "src/scss/**/*.scss"
# 無視するファイル
ignore:
- "src/scss/**/*.scss"
- "src/scss/**/*.scss"
て感じでignoreに項目を追加していきます。
リントルールの設定
さて、リントツール導入の最大の山場であるリントルールの設定です。
sass-lintでは.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にコマンドを登録しておきましょう
{
// 省略
"scripts": {
"scss-build": "webpack --config webpack.config.js",
"scss-lint": "sass-lint -c .sass-lint.yml -v"
},
// 省略
}
こっちは-c オプションで設定ファイルを指定できるんですよね、ややこしいことに。
あと-vは結果を詳細に見るためのオプションです。
それではnpm run scss-lint
を実行してみましょう。
デフォルトのルール設定で何個か引っかかってるみたいですね。
ちなみに全く同じscssに対して-vオプションを外した時はこうなります
おい、警告出せよ(怒)!
というわけで-vオプションはつけて置くことを推奨します。
参考
* webpack