こんにちは!のせっち@nosecchi01です。
Stylelintをv13からv14へのメジャーアップデートがありました。
かなり大幅な変更がありましたので、アップデートは慎重に行う必要があります。
特に既存プロジェクトでは、既に書いているコードがあり、調整が大変だったので、注意すべき点をご紹介します。
Stylelint v14での変更点
主な変更点はStylelint公式のMigration Guideを読むのが一番確実です。
公式で説明されている変更点は下記(意訳)となっています。
- 標準ではcssのLintに対応しなくなり、postcssパッケージを個別にインストールする必要がある。
- 例えばscssならpostcss-scssとstyleint-config-standard-scssが必要など
- node.js 10は切り捨て
- v13.7.0で非推奨となったルールが廃止
configOverrides
が廃止function-calc-no-invalid
が廃止
その他にも僕が実際にアップグレードをしていく中で詰まった点がたくさんありましたので個別に紹介します。
僕はscssを使用しているので、scssに関する記述になります。
個別事象が出た場合は、主にgitthub issueを参考に対応していきます!
参考にしたissueへのリンクを合わせて載せていきます。
まずはStylelintをv14にアップグレードする
Stylelintをv14にアップグレードしていきます。
npm i -D stylelint@14
最新版が欲しい場合はstylelint@latest
としてください。
stylelint-config-recmmended-scssはstylelint-config-standard-scssに統合された
stylelint-config-recmmended-scssはstylelint-config-standard-scssに統合されました。recommended-scssを使っていた人はstandardに置き換えましょう!
## recommended-scssを削除してstandard-scssをインストール
npm rm -D stylelint-config-recmmended-scss && npm i -D stylelint-config-standard-scss
.stylelintrc.json
(またはstylelint.cofig.js
)も編集しておきます
{
"extends": [
"stylelint-config-standard-scss"
],
}
postcssを@8以上に
このままStylelintチェックを行うと、僕の環境では下記のエラーが出ました。
TypeError: Class extends value undefined is not a constructor or null
そこで、postcssを@8以上にします。
npm i -D postcss@8
これで一応Stylelintは動きます。その代わりいっぱいエラーが出ます。(僕は出ました)
scssのlintのためにpostcss-scssも必要
scssをlintするためには、stylelint-config-standard-scss
の他にpostcss-scss
も必要なので入れていきます。
npm i -D postcss-scss
設定にも追記します。
{
"overrides": [
{
"files": ["**/*.scss"],
"customSyntax": "postcss-scss"
}
]
}
Unknown rule系のエラー
Unknown rule function-calc-no-invalid
とエラー分が出る場合、冒頭でも説明しましたが、function-calc-no-invalid
はv14で廃止されたので、rulesから削除する必要があります。
{
"rules": {
"function-calc-no-invalid" : true // 削除
}
}
function-calc-no-invalidは130kもあって重たいので削除されたようです。
function-calc-no-unspaced-operator
というルールがあるので、そちらを使えばいいでしょう。
(デフォルトでtrueなのでわざわざ書く必要はありません。)
エラーだらけになったら(対応方法)
Stylelint v14にすると、めちゃくちゃエラーが出ます。
v14はデフォルトのルールが厳しい印象です。
新規プロジェクトならルールに合わせて書いていくこともできるかもしれませんが、既に書いたものを全部ルール適合させていくのは大変なので、ルールを緩和します。
一気に紹介します。
rules部分の特に重要そうなところを抜粋しました。
{
"rules": {
"selector-id-pattern": null, // idでkebab-case以外も許容
"selector-class-pattern": null, // classでkebab-case以外も許容
"keyframes-name-pattern": null, // keyframesでkebab-case以外も許容
"scss/at-mixin-pattern": null, // mixinでkebab-case以外も許容
"scss/dollar-variable-pattern": null, // $変数でkebab-case以外も許容
"scss/percent-placeholder-pattern": null, // %placeholderでkebab-case以外も許容
"scss/at-extend-no-missing-placeholder": null, // @extendで%placeholder以外も許容
"function-url-quotes": ["always", { "severity": "warning" }], // url()内が""で囲まれていなくてもwarningで止める
"number-max-precision": [3, { "severity": "warning" }], // 小数点以下3桁以上でもwarningで止める
"alpha-value-notation": ["number", { "severity": "warning" }], // 0.3が30%となっていてもwarningで止める
"font-family-name-quotes": [
"always-where-recommended",
{ "severity": "warning" }
], // font-family名のルールが適合していなくてもwarningで止める
"property-no-vendor-prefix": [
true,
{
"ignoreProperties": ["appearance", "text-size-adjust"]
} // autoprefixerで補えるprefixを書いていた場合、エラーとなるが、ignorePropertiesは無視する
]
}
}
JSONでコメントアウトはNGですが、解説用に書いています。
更に抜粋して個別に解説します。
"selector-id-pattern": null, // idでkebab-case以外も許容
"selector-class-pattern": null, // classでkebab-case以外も許容
"keyframes-name-pattern": null, // keyframesでkebab-case以外も許容
"scss/at-mixin-pattern": null, // mixinでkebab-case以外も許容
"scss/dollar-variable-pattern": null, // $変数でkebab-case以外も許容
"scss/percent-placeholder-pattern": null, // %placeholderでkebab-case以外も許容
デフォルトではなんとkebab-case以外全部エラーになるようになってしまいました。これは厳しすぎますね…!
kebab-caseというのはapply-form
のように、単語をハイフンで繋げる命名規則です。
lowerCamel(applyForm
)や、BEM(apply__form
)はエラーとなり、これだと厳しいのでnull
として全部許容します。
他の命名規則で統一したい場合は、正規表現で書くことでルールを厳格に指定できます。
たとえば、lowercaseとkebab-caseのみ許容する場合、
{
"rules": {
"selector-class-pattern": "^[a-z][a-z0-9-]+$",
"selector-id-pattern": "^[a-z][a-z0-9-]+$"
}
}
BEMを許容する場合、
{
"rules": {
"selector-class-pattern": "^[A-Z][a-zA-Z0-9_-]+$",
"selector-id-pattern": "^[A-Z][a-zA-Z0-9_-]+$"
}
}
ただ、エラー文も正規表現で出るようになって初見の人にはわかりにくいので、僕は一律null
としています。
次です。
"scss/at-extend-no-missing-placeholder": null, // @extendで%placeholder以外も許容
@extendでは必ず%placeholderで書かないといけなくなりました。
// 正しい
%card {
// 共通のスタイルを指定
}
.card {
@extend %card;
}
.card--reverse {
@extend %card;
flex-direction: row-reverse;
}
下記のように書くとNGとなります。
// NG
.card {
// 共通のスタイルを指定
}
.card--reverse {
@extend .card; // %placeholderで書かないとNG
flex-direction: row-reverse;
}
共通のスタイルを書きつつ、差分スタイルを@extend
以下で書くとエラーとなります。
上記の例でいうと、.card
も利用しているのでわざわざ%placeholder
で同じことを書く必要はないと思うのですが…。
ということでこのルールはnull
としました。
"function-url-quotes": ["always", { "severity": "warning" }], // url()内が""で囲まれていなくてもwarningで止める
background-image: url("image.jpg");
のようなurl()内では””(クォート)で囲まれていないとエラーになります。
僕はなぜか””を書かない癖がついてしまっていて、既存プロジェクトを全部直すのは大変なのでwarningで止めることにしました。{ "severity": "warning" }
を使うと、エラーをwarningにしてくれます。
"number-max-precision": [3, { "severity": "warning" }], // 小数点以下3桁以上でもwarningで止める
デフォルトだと小数点2桁以上書いたらエラーです。
"alpha-value-notation": ["number", { "severity": "warning" }], // 0.3が30%となっていてもwarningで止める
alpha-value-notationというのはa { color: rgb(0 0 0 / 0.3) }
の0.3の部分です。
モダンな書き方だと、0.3ではなく、30%と書く(percentage)そうですが、0.3(number)に慣れているのでnumberとして、たとえpercentageで書いたとしてもwarningで止めるようにしました。
"font-family-name-quotes": [
"always-where-recommended",
{ "severity": "warning" }
], // font-family名のルールが適合していなくてもwarningで止める
これは複雑なのでまずは公式を見てください!
要はsans-serif
やserif
のような汎用フォントはクォートで囲んではいけない、ということが守れていればいいので、選択肢の中から好みのルールを選べばいいです。
僕はalways-where-recommended
がしっくり来たのでこれにしました。
"property-no-vendor-prefix": [
true,
{
"ignoreProperties": ["appearance", "text-size-adjust"]
} // autoprefixerで補えるprefixを書いていた場合、エラーとなるが、ignorePropertiesは無視する
]
“property-no-vendor-prefix”はautoprefixerで補完されるprefixは書いてはいけない、というルールです。
–fixを付けてsytlelintを実行すれば自動修正されます。
ただ、自動修正すると今度は、declaration-block-no-duplicate-properties
になってしまうのでやっかいです。
// 修正前
.hoge {
transform: translateY(90deg);
-webkit-transform: translateY(90deg); // property-no-vendor-prefixでエラー
}
// 修正後
.hoge {
transform: translateY(90deg);
transform: translateY(90deg); // declaration-block-no-duplicate-propertiesでエラー
}
ignorePropertiesを書いておくと、指定したプロパティは無視してくれます。
どっちしろ修正が大変なケースではignorePropertiesをうまく活用した方がいいときもあるでしょう。
既存プロジェクトは{ “severity”: “warning” }を活用する
既存プロジェクトでは、各scssファイルを修正してエラーを取っていく作業は非常に骨が折れます。
修正間違えをして、表示が崩れてしまっては元も子もないので、{ "severity": "warning" }
をうまく活用して、まずはエラーゼロの状態を目指しましょう。
最終的にはルールを緩和するのか、ルールに合わせてscssファイルを修正するのかゆっくり検討すればいいです。
おまけ:Vueファイルの対応
.vue
ファイル内のscssをLintする場合も一工夫必要になりました。
まずはパッケージをインストール。
npm i -D postcss-html stylelint-config-html
configファイルも編集します。
module.exports = {
extends: [
"stylelint-config-standard-scss",
"stylelint-config-html/vue" // 追加
],
}
これで.vue
ファイルのscssもLintしてくれるようになります!
お疲れ様でした!