はじめに
こんにちは!Incremental Stream Team の @53able です!
今回はダッシュボードに ESLint を導入した話を書いていこうと思います!
ESLint について
ESLint は JavaScript の構文チェックツールです。
導入の背景
GameWith のサービス側には2年前に ESLint が導入されています。
GameWith のダッシュボード側には導入されていなかったです。
ダッシュボードの開発が複数人で活発に行い、振り返りをしたところ構文チェックツールがないせいで、人によって微妙な書き方の差異が発生しており、開発速度が遅くなっているので、今回導入することにしました
コードレビューで、レビュワーが構文チェックをしてコメントするのはかなりコストが高く、この課題も解決したかったです 例:var 使っているので let, const 使って欲しいなど
やりたいのは「構文チェック」と「自動整形」だったため、ESLint を導入しました
ESLint の設定
ESLint の設定を最初に紹介したいと思います!
{ "extends": [ "eslint:recommended", "plugin:prettier/recommended" ], "env": { "browser": true, "jquery": true, "es2021": true }, "parserOptions": { "sourceType": "module" }, "rules": { "prettier/prettier": ["error", { // prettierのルールをカスタマイズ }] } }
Prettier
Prettier 関連のプラグインについていくつか紹介します。
eslint-plugin-prettier
Prettier のルールを ESLint のルールとして実行できるようにするプラグインです。
eslint-config-prettier
ESLint にもコードの整形についてのルールがいくつかあります(例えば、インデントは半角スペース2つにするか4つにするか)
こういった Prettier とコンフリクトするルールについて、Prettier の設定で ESLint を上書きするようにするプラグインです。
導入作業
1. 現在のエラーの調査
まずはじめに、GameWith のサービス側に既に ESLint が導入されているので、まず最初にダッシュボードの JavaScript に ESLint を実行し、どんなエラーがどれくらい出るのか確認しました。
確認する際はダッシュボードの JS のディレクトリにはライブラリの JS を直接ダウンロードして配置してあったので、上記 ESLint 実行時には無視するように設定をしました。
また、今回のダッシュボードへの導入のタイミングで、ESLint の env
で es6
から es2021
に引き上げました(es2021
は Chrome 85 から対応しており、問題ないと判断をしました)
ESLint を実行すると、ファイルごとにエラーが表示されます。
今回知りたかったのは、ファイルごとのエラーではなく、全体を通してどんな種類のエラーが出ているかを知りたかったので eslint-report-by-rule
というモジュールを利用しました。
eslint-report-by-rule
は下記のように実行します。
eslint-report-by-rule 'eslint dashboard -f json'
実行すると下記のように ESLint のルール別のエラー数が表示されます(下記は実際に図った数値で合計 4000 over のエラーが出ています!)
※ダッシュボードの JavaScript は量が多く、このコマンドは15分ほどかかりました笑
{ "no-unused-vars": 141, "prettier/prettier": 3646, "no-undef": 545, "no-redeclare": 5, "no-useless-escape": 53, "no-const-assign": 1, "no-empty": 11, "no-prototype-builtins": 5, }
2. エラーの修正(自動修正)
修正作業としてはまず ESLint の fix オプションを利用し修正をしました。
eslint --fix dashboard
この fix オプションよって、4000 件以上あったエラーが約 800 件になりました!
3500 件以上あった prettier/prettier
のエラーは全てなくなりました(すごく助かります💦)
{ "no-unused-vars": 141, "no-undef": 545, "no-redeclare": 5, "no-useless-escape": 41, "no-const-assign": 1, "no-empty": 11, "no-prototype-builtins": 5, }
3. エラーの修正(手動修正)
fix オプションでも修正できなかったエラーに関しては手動で修正しました。
no-unused-vars
- 使われていない変数は、削除したりコメントアウトしたりして修正をしました
no-undef
var
,let
,const
が書かれてない変数に関しては、手動でlet
,const
を付与しました
no-redeclare
- 無駄な再代入は修正しました
no-useless-escape
- 正規表現内の不要なエスケープは削除しました
no-const-assign
const
宣言している変数に代入をしていたのでlet
宣言に修正しました
no-empty
catch
文の中が空だったので修正しました
no-prototype-builtins
hasOwnProperty
の実行方法について修正しました
苦労した点
関数から受け取った変数が利用されていなかったのでその変数と関数の実行を削除したのですが、テスト時にバグが発生し、調査すると消した関数が原因でした。
理由としては、削除した関数が副作用のある関数だったためです(具体的には関数内で DOM の操作を行っていました)
サンプルコード
if (hoge) { const piyo = fuga(elementId); }
また、宣言子なしで定義されている変数はグローバルスコープになりどんな箇所からも参照することができるので、let
, const
の付与でスコープが変わってしまい参照できなくなる可能性もあったので、注意深く作業しました。
ダッシュボードには webpack や gulp といったバンドラーを利用していないため、ライブラリなど依存関係は <script>
の読み込み順で解決していました。
そのため、ライブラリなどの別ファイル定義の関数やクラスなどを利用している箇所で no-undef
エラーが発生していました。
今回はバンドラーなどは使わず import/export
を利用し no-undef
エラーを修正しました。
現代の主要なブラウザは import/export
に対応しているので、バンドラーの導入など不要で修正できるため採用しました 👍
サンプルコード
import hoge from 'hoge.js'; const piyo = new hoge(elementId);
import
が書かれている JavaScript は type=module
で読み込む必要があるため、ダッシュボードに記述されている <script>
を修正しました。
import/export
を書く場合、ESLint で下記オプションを設定する必要があります。
"parserOptions": { "sourceType": "module" },
import
を使ってるので、jQuery の getScript
の処理は全て import
に書き換えました。
4. 完了
手動で修正したことによって、エラーは 0 になりました🎉
終わりに
今回はダッシュボードへの導入だったため、import/export
はバンドラーを通さずに採用しています。
ダッシュボードは Chrome で開かれることが多いため、採用もしやすかったです!
導入は完了したのですが、実は PHP Template の <script>
に直書きされた JavaScript が存在しているため ESLint による構文チェックができていません。
ちなみに直接書かれた JavaScript の先頭には下記コメントアウトを書き残してあります笑(約100箇所)
<?php //TODO このスクリプトに関連する作業を行う場合は、JSファイルにして ESLint を通すようにしてください。 ?>
現在はテストツールを導入しているので、次回はテストツールの導入について紹介できればと思います!
Twitter にて GameWith のエンジニア向け情報発信をしています!