Stylelintを導入してSCSSを綺麗に保つ(Prettier併用)

# はじめに

CSS設計をドキュメントにまとめても、ルールの浸透が不十分であれば開発者によって設計を無視したCSSの書き方をしてしまうことがあります。
コードレビューで毎回指摘するのは大変なので、CSS設計に沿ったStylelintの設定ファイルを作成します。

# CSS設計と必要なパッケージ

CSS設計にはRSCSSを採用しており、規格に沿ったルールをピックアップしたパッケージが合ったので、それを使用させていただきます。また、コードのフォーマットは全てPrettierにお任せをし、Stylelintに含まれるフォーマットのルールは**stylelint-config-prettier**で全てオフにします。

## パッケージ一覧

- [stylelint-config-recommended-scss](https://github.com/kristerkari/stylelint-config-recommended-scss)
    - 推奨されるSCSS構文のルール
- [stylelint-config-recess-order](https://github.com/stormwarning/stylelint-config-recess-order)
    - CSSプロパティを自動ソート
    - [ソートの考え方](https://markdotto.com/2011/11/29/css-property-order/)
    - [ソート順](https://github.com/twitter/recess/blob/29bccc870b7b4ccaa0a138e504caf608a6606b59/lib/lint/strict-property-order.js)
- [stylelint-rscss](https://github.com/rstacruz/stylelint-rscss)
    - RSCSS規則に沿ったルール
- [stylelint-config-prettier](https://github.com/prettier/stylelint-config-prettier)
    - Prettierと競合する可能性のあるルールをオフにする
- [stylelint](https://github.com/stylelint/stylelint)
- [prettier](https://github.com/prettier/prettier)

# Stylelint設定

## インストール

```bash
yarn add -D stylelint stylelint-config-recommended-scss stylelint-config-recess-order stylelint-rscss stylelint-config-prettier
```

## 設定ファイル

### **stylelint.config.js**

```jsx
{
   "extends": [
     "stylelint-config-recommended-scss",
     "stylelint-config-recess-order",
     "stylelint-rscss/config",
     "stylelint-config-prettier"
   ],
   /* RSCSSのルール上書き(説明は後で) */
   "rules": {
     "max-nesting-depth": [
       2,
       {
        "ignore": ["pseudo-classes"],
        "ignoreAtRules": ["include"]
       }
     ]
   }

 }
```

## コマンド

### **package.json**

```jsx
"scripts": {
	"lint:scss": "stylelint **/*.scss",
	"lint:scss:fix": "stylelint --fix **/*.scss"
}
```

# Prettier設定

## インストール

```bash
yarn add -D prettier
```

## 設定ファイル

### **.prettierrc**

```jsx
{
  "trailingComma": "none",
  "singleQuote": true
}
```

## コマンド

### **package.json**

```jsx
"scripts": {
	"format": "prettier -c **/*.scss",
	"format:fix": "prettier -w **/*.scss",
}
```

# 中身を詳しく見ていく

ここから設定ファイルの中身を詳しく見ていこうと思います。まずは、**stylelint.config.js**のextendsの中身についてです。
extendsの配列は左からルールが適用されていくので、記述の順番には注意する必要があります。

今回は、

推奨されるSCSS構文のルール適用
→CSSプロパティの自動ソート
→RSCSS構文のルール適用
→Prettierと競合する可能性のあるルールをオフ

となるように並べていきました。

```jsx
"extends": [
  "stylelint-config-recommended-scss",
  "stylelint-config-recess-order",
 　　"stylelint-rscss/config",
  "stylelint-config-prettier"
]
```

最後に**stylelint-config-prettier**を記述することで、これまで適用したルールの中でPrettierと競合する可能性のあるルールをオフにすることが出来ます。

次に、使用したパッケージについて見ていきます。

## stylelint-config-recommended-scss

このパッケージは、SCSSを記述する上で推奨される構文ルールを適用してくれます。やっていることは大きく分けて2つ。

1. [stylelint-config-recommended](https://github.com/stylelint/stylelint-config-recommended) をSCSS用に設定
2. [stylelint-scss](https://github.com/stylelint-scss/stylelint-scss)の設定

### 1. stylelint-config-recommendedをSCSS用に設定

stylelint-config-recommendedは、Stylelintの[possible errors](https://stylelint.io/user-guide/rules/list/#possible-errors)のルールをSCSS用に設定し直し、適用する役割があります。

### 2. stylelint-scssの設定

stylelint-scssは、SCSS構文の固有のルール、例えばネストや@importなどの@構文のルールを適用する役割があります。

これで、SCSSの構文ルールの設定が終わりました。

## stylelint-config-recess-order

このパッケージは、CSSプロパティーを一定の順序に並び替えてくれます。

大まかな順序の内訳としては、

1. position
2. displayとボックスモデル(width, height, padding, margin)
3. fontとcolor
4. backgroundとborder
5. border-radiusやbox-shadowなどのCSSプロパティ

のように、ある程度上から順番に読むことで、何を扱っているのか判別できるにしています。

つまり、どの位置に、どんな大きさで、何色を指定しているのか、どんな形なのか、などが追えるようになっています。開発者によってCSSプロパティの書く順番は異なるので、このパッケージを用いることでSCSSに一貫性を持たせることができます。

## stylelint-rscss

このパッケージはRSCSS特有のルールを適用してくれます。CSS設計でRSCSSを採用していない場合は、このパッケージを削除してもらえれば大丈夫です。

具体的にチェックしていることは、

- コンポーネントの命名方法は正しいか
- エレメントのクラス名は1語で記述されているか
- バリアントは**-〇〇**となっているか

などがあります。それに加えて、今回はネストの深さを2つ以内にしたかったので、

```jsx
 "rules": {
   "max-nesting-depth": [
     2,
     {
      "ignore": ["pseudo-classes"],
      "ignoreAtRules": ["include"]
     }
   ]
 }
```

とすることで、デフォルトのルールを上書くことができます。例外として、擬似クラスと@includeはネストの回数に含めないようにしたかったので、ignoreを記述しています。

## コマンド

Stylelintのコマンドは2つ用意しています。
**lint:scss**はルールに違反している記述がないかを確認する用なので、CIに加えてデプロイ前に実行するように設定すると良いかもしれません。

**lint:scss:fix**はルールに違反している記述の中で、自動で修正可能なものを書き換えるコマンドです。もちろん、全ての違反した記述を書き換えてくれるわけではないので、最後は手動で修正する必要がでてきます。

ただ、**stylelint-config-recess-order**のようにCSSプロパティの並び順を強制するエラーを1つ1つ手動で解消するのは大変なので、コミット前に**fix**コマンドで一括で書き換えてあげると楽です。

```jsx
"scripts": {
	"lint:scss": "stylelint **/*.scss",
	"lint:scss:fix": "stylelint --fix **/*.scss"
}
```

以上がStylelintの設定ファイルの中身の説明でした。

開発者が増えるとSCSSを綺麗に保つのが難しくなるので、ある程度Stylelintでルールを強制することで、レビュアーの手間も減るのではないでしょうか。

# おまけ

コードフォーマッターのPrettierについて少し補足しておきます。

Prettierはデフォルトでいくつかルールが設定されているので、設定ファイルを作成しなくても一定のフォーマットルールを適用することができます。

今回は2つのルールを上書きしたかったので、.**prettierrc**ファイルを作成しています。

```jsx
{
  "trailingComma": "none",
  "singleQuote": true
}
```

## trailingComma

末尾にコンマを追加するか

- "es5" - ES5に準拠する形で追加(デフォルト)
- "none" - 追加しない
- "all" - 全ての末尾に追加

## singleQuote

ダブルクォートの代わりにシングルクォートを使用するか

- false - シングルクォート
- true - ダブルクォート

以上がPrettierの補足説明でした。少しでも参考になれば嬉しいです。