GameWith Developer Blog

GameWith のエンジニア、デザイナーが技術について日々発信していきます。

ダッシュボードに ESLint を導入した話 #GameWith #TechWith

はじめに

こんにちは!Incremental Stream Team の @53able です!

今回はダッシュボードに ESLint を導入した話を書いていこうと思います!

ESLint について

ESLint は JavaScript の構文チェックツールです。

eslint.org

導入の背景

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 のルールとして実行できるようにするプラグインです。

www.npmjs.com

eslint-config-prettier

ESLint にもコードの整形についてのルールがいくつかあります(例えば、インデントは半角スペース2つにするか4つにするか)

こういった Prettier とコンフリクトするルールについて、Prettier の設定で ESLint を上書きするようにするプラグインです。

www.npmjs.com

導入作業

1. 現在のエラーの調査

まずはじめに、GameWith のサービス側に既に ESLint が導入されているので、まず最初にダッシュボードの JavaScript に ESLint を実行し、どんなエラーがどれくらい出るのか確認しました。

確認する際はダッシュボードの JS のディレクトリにはライブラリの JS を直接ダウンロードして配置してあったので、上記 ESLint 実行時には無視するように設定をしました。

また、今回のダッシュボードへの導入のタイミングで、ESLint の enves6 から es2021 に引き上げました(es2021 は Chrome 85 から対応しており、問題ないと判断をしました)

ESLint を実行すると、ファイルごとにエラーが表示されます。

今回知りたかったのは、ファイルごとのエラーではなく、全体を通してどんな種類のエラーが出ているかを知りたかったので eslint-report-by-rule というモジュールを利用しました。

www.npmjs.com

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

Twitter にて GameWith のエンジニア向け情報発信をしています!

twitter.com