👔

Stylelint(14系)をSCSSとVSCodeに導入する2022

2022/01/06に公開

stylelintをSCSSとVSCode(Stylelint拡張機能)に導入しようと思ったんだけど、14系[1]には破壊的変更[2] が含まれてるらしく、ドキュメント通りにやってもエラーが出てしまったり、ネットで検索しても出てくる記事が13系以前のものだったりして苦労した。何とか導入することができたのでどうやったかを記録したいと思う。

やりたいこと

  • SCSSにstylelintを導入する
    • yarn stylelint hogehoge.scssとかやったらSCSSファイルにstylelintを実行できる
    • プロパティのソートもやってくれる
  • VSCodeにstylelint拡張機能を導入する
    • エディタ上にリアルタイムでエラーを出してくれる
    • 保存時に自動で修正してくれる

結論

インストール

yarn add -D stylelint stylelint-config-standard-scss postcss@8 stylelint-config-recess-order 

ルートディレクトリ(stylelintをインストールした場所)に.stylelintrc.jsonというファイルを作る。

.stylelintrc.json
{
  "extends": [
    "stylelint-config-standard-scss",
    "stylelint-config-recess-order"
  ]
}

VSCode拡張

「Stylelint」というStylelint公式の拡張機能をインストールする。
https://marketplace.visualstudio.com/items?itemName=stylelint.vscode-stylelint
settnig.jsonを開いて

setting.json
{
  "stylelint.validate": ["css", "scss"],
  "scss.validate": false,
  "css.validate": false,
  "editor.codeActionsOnSave": {
    "source.fixAll.stylelint": true
  },
  // Prettier併用の場合
  "editor.formatOnSave": true,
  "editor.defaultFormatter": "esbenp.prettier-vscode"
}

を追記する。

詳細

環境

  • nuxt-creat-appで作ったNuxt.jsのプロジェクトに後からstylelintを導入する。
  • パッケージマネージャーはyarnを使用
    ※ただし、Nuxtやyarn固有のエラーや記述は特になかったから今回の話にはあまり関係ないと思う。
  • assets/などにSCSSファイルを作ることを想定。vueファイルの中にstyleタグを書くやり方には未対応

SCSSにStylelintを導入する

公式ドキュメント通りに進めていく。
https://stylelint.io/user-guide/get-started#linting-everything-else

公式はnpmだったけど、自分はyarn派なので

yarn add -D stylelint stylelint-config-standard-scss

でstylelintとstylelint-config-standard-scssをインストールする。stylelint-config-standard-scssというのはstylelintをscssで使うための基本的な設定が入ってるパッケージのこと。

次に、プロジェクトのルートディレクトリ(さっきyarn addをした場所)に.stylelintrc.jsonというファイルを作れと書いてあるのでその通りにする。

.stylelintrc.json
{
  "extends": "stylelint-config-standard-scss"
}

あるいは.stylelintrc.jsというファイルを作って

.stylelintrc.js
module.exports = {
  "extends": [
    "stylelint-config-standard-scss"
  ]
};

と書いても良い。(ちなみにちゃんとファイルが作れているとVSCode上に表示した際、ファイル名の横にこのようなアイコンがつくので、ついていない場合はtypoをしてないか確認しよう。)

公式によるとこれだけでnpx stylelint "**/*.scss"とかやればstylelintが実行できると書いていたので、適当なSCSSファイルを実行してみる。

yarn stylelint assets/hoge.scss

ここまでドキュメント通りにやってるし、これでstylelintが導入できたはず......

TypeError: Class extends value undefined is not a constructor or null
(中略)
error Command failed with exit code 1.
info Visit https://yarnpkg.com/en/docs/cli/run for documentation about this command.

できないんだが....!?!?!?!?!?

TypeError: Class extends value undefined is not a constructor or null

調べてみると、stylelint-config-standard-scssのGitHubで同じエラーで悩む人たちを見つけた。
https://github.com/stylelint-scss/stylelint-config-standard-scss/issues/5

そしてissueの下の方にこのようなコメント[3] があった。

This is related to how npm installs and flattens dependencies. postcss-scss expects postcss as peer dependancy, and since you didn’t install it yourself, and most of other dependencies use postcss@7, that version is placed at root of node_modules, but our postcss-scss needs postcss@8.

Here are possible fixes:

  • Install postcss@8 as your project dependancy so postcss-scss can pick that as top-level postcss
  • Update all other related packages which use postcss@7 to versions where postcss@8 is expected

多分こんな感じのことを言ってる。

これはnpmが依存関係をインストールし、平坦化する方法に関連しています。
postcss-scsspostcssをpeer dependencyとして期待しています。あなたはpostcssを自分自身でインストールしておらず、他の依存関係の殆どがpostcss@7を使っているので、postcss@7がnode_modulesのルートに置かれています。しかし、我々のpostcss-scsspostcss@8を必要としています。

以下は考えられる修正方法です。

  • postcss@8をプロジェクトの依存関係としてインストールし、postcss-scssがそれをトップレベルのpostcssとして選択できるようにする。
  • postcss@7を使用している他のすべての関連パッケージをpostcss@8が期待されるバージョンにアップデートする。

peer dependencyって何?という方にはこの記事の説明がわかりやすいと思う。
要するにpostcssの8系をインストールしろってことらしい。

yarn add -D postcss@8

この後、さっきと同じようにyarn stylelint assets/hoge.scssをやるとちゃんと実行できるようになっていた。ちなみに自動修正もしたいならyarn stylelint --fix assets/hoge.scssのように--fixをつけると良い。

ソートもしてくれるようにする

stylelint-config-standard-scssだけだとプロパティのソートはしてくれないので、追加でstylelint-config-recess-orderをインストールする。

yarn add -D stylelint-config-recess-order 

ドキュメント通りに進めるために分けてインストールしたけど、別にstylelintをインストールする時に一緒にやってしまっても問題ない。(結論のところでは全て同時にインストールしている)

インストールできたら.stylelintrc.jsonに追記する。

.stylelintrc.json
{
  "extends": [
    "stylelint-config-standard-scss",
    "stylelint-config-recess-order"
  ]
}

これだけでOK! 
例えばこのようなファイルがあったとして

assets/hoge.scss
.test {
  width: 10px;
  margin: 10px;
  height: 10px;
}

yarn stylelint --fix assets/hoge.scssを実行すると

assets/hoge.scss
.test {
  width: 10px;
  height: 10px;
  margin: 10px;
}

順番が入れ替わってる!
こっちは特にエラーに苦しむこともなく簡単に導入できた。

VSCodeにStylelintを導入する

コマンドラインでstylelintを実行することはできたので、今度はVSCodeの環境を整えていく。
まず、VSCodeの「Stylelint」というStylelint公式の拡張機能をインストールする。
https://marketplace.visualstudio.com/items?itemName=stylelint.vscode-stylelint

「stylelint」と検索しても普通に上位に出てくるし、あるいは検索欄に@id:stylelint.vscode-stylelintと入力したら一発で出てくる。

これで導入完了...と思いきや、CSSファイルには赤線が表示されているのに対し、SCSSファイルには何も表示されていない。

この理由は上記のドキュメントの⚠️Only CSS and PostCSS are Validated by Defaultのところに書かれている。

The 0.x versions of this extension, which used Stylelint 13.x and prior, supported validating many different languages out of the box without any additional configuration. However, this added a lot of complexity and resulted in many cases of unwanted or unexpected behaviour.

In current versions of the extension, the extension only supports validating CSS and PostCSS out of the box and requires additional configuration to validate other languages. You will need to:

多分こんな感じのことを言ってる。

この拡張機能の0.xバージョンではStylelint 13.x以前を使用しており、追加の設定なしに多くの異なる言語の検証を行うことができました。しかし、これは非常に複雑で、望ましくない、あるいは予期しない動作をするケースが多くありました。

現在のバージョンでは拡張機能は CSS と PostCSS のみをサポートしており、他の言語を検証するためには追加の設定が必要です。必要なのは:(次の文章に続く)

つまり、「デフォルトだとCSSとPostCSSしかサポートしてないから、SCSSに導入したいなら以下の設定をやってくれ」的なことを言ってるっぽい。で、この次の文章にはやるべき3つの設定が書かれてるんだけど、最初の2つは前の章でもうやったので必要なのは最後のやつのみ。

Add the language identifiers for the documents you want to validate to the extension's workspace or user settings using the stylelint.validate option.
Example VS Code config:

{
  "stylelint.validate": ["css", "scss"]
}

SCSSを使うのにはstylelint.validateオプションを設定する必要があるとのことなのでsetting.jsonを開き、上記を追加する。
setting.jsonって何?って方はこのブログが参考になると思う。

SCSSファイルにもエラーが表示されるようになった

また、ドキュメントのDisable VS Code's Built-In Linters (optional)によると、VSCodeの組み込みリンターとStylelintが同じエラーを表示してしまうことがあるそうで、それはちょっと鬱陶しいので組み込みリンターのほうを無効にする。

stylelint.validateと合わせるとsetting.jsonはこんな感じになる。

setting.json
"stylelint.validate": ["css", "scss"],
"scss.validate": false,
"css.validate": false,

保存時に自動整形する

最後にVSCode上で保存時にSCSSを自動整形してくれるようにする。
setting.json

settting.json
"editor.codeActionsOnSave": {
  "source.fixAll.stylelint": true
}

を追加する。実はPrettierも併用していて、上記の設定を加えたことで保存時にPrettierが効かなくなってしまったんだけど、以下の設定を加えたらうまくいった。

setting.json
"editor.formatOnSave": true,
"editor.defaultFormatter": "esbenp.prettier-vscode"

これでVSCodeの設定は完了!
最後に最終的なsetting.jsonを貼っておく。

setting.json
{
  "stylelint.validate": ["css", "scss"],
  "scss.validate": false,
  "css.validate": false,
  "editor.codeActionsOnSave": {
    "source.fixAll.stylelint": true
  },
  "editor.formatOnSave": true,
  "editor.defaultFormatter": "esbenp.prettier-vscode"
}

終わりに

本記事では、StylelintとSCSSとVSCodeに導入するやり方について書いた。
Stylelint14系がリリースされたのは2021年10月と比較的最近のため、ネットで検索して出てくる記事のほとんどが13系以前で思ったよりも苦労した。

ちなみに前回のブログを書いたときにstylelintを生のCSSに導入したんだけどそのときはすんなりと導入できた。14系の破壊的変更の1つにデフォルトでSCSSやSass等CSSライクな言語がサポートされなくなった的なのがあって(だから手動でstylelint-config-standard-scssとか色々入れないといけない)、それが原因でちょっと面倒くさくなってるぽかった。

エラーの解決方法は公式のGithubやドキュメントに書かれてあることが殆どだったので一次ソースを確認することの大事さを感じた。

脚注
  1. 執筆時点の最新バージョン ↩︎

  2. https://stylelint.io/migration-guide/to-14 ↩︎

  3. https://github.com/stylelint-scss/stylelint-config-standard-scss/issues/5#issuecomment-961709882 ↩︎

Discussion