掲題の通り、所属しているチームの開発効率・生産性・品質向上のためにVSCodeにlinterとformatterを入れる、という取り組みを行いました。
実際に導入する際の具体的な進め方をまとめてみました。

導入にあたり

案件で特に使う頻度が多い、
・python
・node.js
・shell
・json
にlinterとformatterを導入することにしました。

使用している環境

mac OS Big sur バージョン11.4
VSCodeバージョン: 1.79.0 (Universal)
yarn 1.22.19

formatterとlinterの違い

当初、linterはただ修正案を提示するもの、それに対してformatterは自動で修正してくれるのでformatterはlinterの上位互換だと思っていました。
しかし、実際は両者は機能的に異なるもので、併用するのが良いことがわかりました。

formatter・・・形式を自動的に修正する
linter・・・対象の特徴に合わせて修正案を提示する

その結果、formatterとlinterを併用する前提で、以下のツールを使うことにしました。

対象 linter formatter
python pylint black
shell shellcheck shell-format
json - VSCodeのデフォルトツール
node.js eslint(競合した場合prettierを優先) prettier

※今回のケースでは導入コストの関係でjsonはフォーマッターがあれば十分と考え、linterは入れていません。

方針

linterやformatterをインストールしてから、コマンドを叩いて修正箇所を出したり整形したりすることもできます。
ですが、生産性向上の観点から「VS Code上で修正案を示して、保存しただけで勝手に整形してくれる機能」の実現を目指すことにしました。

事前準備

linter・formatterを適用したいプロジェクトフォルダのルートディレクトリの配下に.vs_codeフォルダを作成します。
次に.vs_codeフォルダ内に、extensions.jsonファイルとsettings.jsonファイルを作ります。
extensions.jsonには導入したいツールの情報を記載します。

{
    "recommendations": [
        "ms-python.pylint",
        "ms-python.black-formatter",
        "dbaeumer.vscode-eslint",
        "esbenp.prettier-vscode",
        "timonwong.shellcheck",
        "foxundermoon.shell-format",
    ]
}

extensions.json作成後、cmd+shift+pで「recommended extensions」と入力すると左側に設定したプラグインが表示されます。
このプラグインを全てインストール後、再起動します。

次にsettings.jsonに以下の内容を設定します。(詳しい説明は後述します)
※jsonファイルにコメントを記載するとエラーになりますが、設定の意図をわかりやすくするためにこちらではコメントを記載しています。

{
    //-------------------------------------------------------------------
    // pythonの設定
    //-------------------------------------------------------------------
    // pylintを有効化する
    "python.linting.pylintEnabled": true,
    // black formatterの設定をする
    "python.formatting.provider": "black",
    // エディタでblack formatterを指定、保存時にformatterを自動で呼び出す
    "[python]": {
        "editor.defaultFormatter": "ms-python.black-formatter",
        "editor.formatOnSave": true,
    },
    //-------------------------------------------------------------------
    // javascriptの設定
    //-------------------------------------------------------------------
    // eslintを有効化する
    "eslint.enable": true,
    // prettierの設定をする
    "[javascript]": {
        "editor.defaultFormatter": "esbenp.prettier-vscode",
        "editor.formatOnSave": true
    },
    //-------------------------------------------------------------------
    // shellの設定をする
    //-------------------------------------------------------------------
    // 保存時にshelformatを自動適用する
    "[shellscript]": {
        "editor.defaultFormatter": "foxundermoon.shell-format",
        "editor.formatOnSave": true
    },
    // shellcheckは設定不要のため記述なし
    //-------------------------------------------------------------------
    // jsonの設定をする
    //-------------------------------------------------------------------
    // json保存時にvs codeのフォーマッターを自動適用する
    "[jsonc]": {
        "editor.defaultFormatter": "vscode.json-language-features",
        "editor.formatOnSave": true
    }
}

導入の手順

1.json

上記の手順のみで、formatterとしてVSCodeデフォルトのフォーマッターが入った状態になります。
jsonファイルを編集すると勝手にフォーマットされるようになります。

2.shell

上記の手順のみで、formatterとしてshell-format、linterとしてshellcheckが入った状態になります。
settings.jsonで、以下の設定をしています。

  • shellscriptを保存した場合に、shell-formatでフォーマットを行うようにしています。
  • shellcheckはvs_codeにインストールしただけで適用されるので設定は不要です。

shellcheckでチェックが走ります

保存するとshell-formatにより自動で整形されます

今回のケースですと、6-11行目のインデントのずれが自動で整形されています。

3.python

上記の手順のみで、formatterとしてshell-format、linterとしてshellcheckが入った状態になります。
settings.jsonで、以下の設定をしています。

  • python編集時はpylintをlinterとして使うようにしています。
  • blackをformatterとして使うようにしています。
  • pythonを保存した場合に、blackでフォーマットを行うようにしています。

Pylintが「関数に説明がない」と警告を出しています。

説明を追加すると警告が消えます。

4.node.js

eslintとprettierを使用します、

eslintはlinterとformatter両方の機能を備えています。
prettierの方がformatterとして優れているので、prettierのみが機能するように設定します。


補足 eslintよりprettierが優れている点について

実際にフォーマッターとして両者を使った時の結果を比較してみます。
インデントやスペースなどを意図的にずらしてみたサンプルコードを使って検証してみます。

/**
 * User class
 * @param {int} id
 * @param {Object} friends
 * @return {User}
 */
class User {
  // eslint-disable-next-line require-jsdoc
    constructor(id, friends) {  this.id = id;   this.friends = friends;   }
}

    const users = [
  new User(0, [1, 2]), new User(1, [0]),
                new User(2, [0, 3, 123, 999]),
          new User(3, [2, 4]),
  new User(4, [3]),         new User(5, [111, 222]),
  new User(6, []),
];

/**
 * checkRelation function
 * @param {int} origin
 * @param {int} target
 * @return {bool} origin has relations
 */
function checkRelation(origin, target) {
  if (origin == target) {
        return "同じ人です";
            }

  // 最初にpush
const visited = []; const queue = [];
  // visited.push(origin);
queue.push(origin);

  // ループ内でshift,pushを繰り返す
  while (queue.length != 0) {
    const person = queue.shift();

    // DBにない場合skip
    if(!users[person]){continue;}

    // 訪問していないユーザーのみを調べる
    const friend = users[person].friends.filter((   f    ) =>     { return !visited.includes( f ); } ) ;

    console.log(person,
        friend,
        visited);

    if (    friend.includes(target) ) { return true;            }

    visited.push(person);   queue.push(...friend);
  }return false;
}

console.log(checkRelation(2, 0)); console.log(checkRelation(2, 1)); console.log(checkRelation(2, 2));
console.log(checkRelation(2, 3));
console.log(checkRelation(2, 4)); console.log(checkRelation(2, 5)); console.log(checkRelation(2, 6));
前提条件
  • eslintとprettierともにテストコードを貼り付けた後、保存ボタンを押しただけで整形するように設定しています。
  • prettierの設定ファイル.prettierrc.json(後述)には何も設定をしていません。
    {
    }
  • eslintの設定ファイル.eslintrc.json(後述)にはeslint:recommendedとは別に、以下の通りフォーマットルールを設定しています。(一部抜粋)
    "rules": {
        "no-console": "off",
        "indent": [
            "error",
            2
        ]
    }

eslintでフォーマットした場合

prettierでフォーマットした場合

両者を比較してみると、prettierの方が綺麗に整形できていることがわかると思います。
別途設定を入れた状態で整形をしているeslintで整形できていない、文字数が多い行の改行や、インデントに意図的に入れたタブの削除もprettierでは行ってくれています。
しかも、prettierは何も設定していない状態でもデフォルトの整形モードに基づいて綺麗に整形してくれます。
以上より、prettierの方がformatterとして優れていることがわかるかと思います。


また、linterとして使用する際にeslintとprettierのルールが競合しないように併用できる環境を作る必要があります。
そのためコマンドにてインストール作業を行います。

4-1.eslintをコマンドよりインストール

プロジェクトのルートディレクトリに移動し、コマンドを実行します。

yarn add --dev eslint
yarn run eslint --init

※他のパッケージマネージャーでも可能ですが、今回はyarn version 1.22.19を使って説明します。
yarnのインストール手順は公式サイトの説明を参照ください。
https://chore-update--yarnpkg.netlify.app/ja/docs/install

その後、以下の質問に解答しながらeslintをインストールします。

・ How would you like to use ESLint?
    ・ 3番目の「To check syntax, find problems, and enforce code style」を選択
    ・ コードスタイルを整えることが目的のため
・ What type of modules does your project use? (Use arrow keys)
    ・ 1番目の「JavaScript modules (import/export)」を選択
・ Which framework does your project use?
    ・ 3番目の「None of these」を選択
    ・ 今回はnode.jsのため、他選択肢のReactやVueは選ばない
・ Does your project use TypeScript?
    ・ Noを選択(今回はTSは使用しないため)
・ Where does your code run?
    ・ Nodeを選択
・ How would you like to define a style for your project?
    ・ 1番目の「Use a popular style guide」を選択
・ Which style guide do you want to follow? 
    ・ 今回はGoogleを選択
    ・ どれが絶対に正しい、というのはないので好みに応じてスタイルガイドを選択してOK
・ What format do you want your config file to be in?
    ・ JSONを選択
・ Would you like to install them now?
    ・ YESを選択
・ Which package manager do you want to use?
    ・ 任意のパッケージマネージャーを選択

4-2.eslint-config-prettierをコマンドよりインストール

同じディレクトリにて以下のコマンドを実行します。

yarn add --dev eslint-config-prettier
  • eslint-config-prettierとは、eslintのformatterとしての機能を無効にするプラグインです。

4-3.eslintrc.jsonを修正

実行が完了すると、プロジェクトのルートディレクトリに.eslintrc.jsonファイルが作成されるので、以下の通りに修正します。
変更前・変更後の記載がない箇所はインストール時にデフォルトで設定されている内容になります。

{
    "env": {
        "browser": true,
        "es2021": true
    },
    // ----------------------------------------------
    // 変更前(デフォルト)
    // "extends": "google",
    // 変更後
    "extends": [
        "eslint:recommended",
        "google",
        "prettier"
    ],
    // ----------------------------------------------
    "parserOptions": {
        "ecmaVersion": "latest",
        "sourceType": "module"
    },
    // ----------------------------------------------
    // 変更前(デフォルト)
    // "rules": {}
    // 変更後
    "rules": {
        "no-console": "off"
    }
    // ----------------------------------------------
}

補足

extendsでは、他の設定内容を継承してコードチェックをできるようにしています。

  • google・・・「Which style guide do you want to follow? 」でgoogleを選んだので設定されています。
  • eslint:recommended ・・・eslint の推奨ルールです。
    • eslintは本来、チェック項目を設定ファイルに個別で書かなければなりません。しかし、extends: eslint:recommendedと記載することで、eslint側で設定している推奨ルールに基づいてチェックを行ってくれるようになっています。
    • 推奨ルール適用で設定されるルールは、公式サイトの説明ページの右端にチェックがついているものになります。
  • prettier・・・prettierとeslintのルールで競合が起きた際に、prettierを優先するために記述しています。

※eslint:recommendedの推奨ルールは公式サイトを参照・・・ https://eslint.org/docs/latest/rules/

rulesについて

  • no-console:off・・・eslintのデフォルトの機能ではconsole.logしている箇所に警告を出してしまうので、警告をオフにするために入れています。

4-4.prettierの設定を行う

プロジェクトのルートディレクトリに.prettierrc.jsonファイルを作成します。

yarn add --dev prettier
echo {}> .prettierrc.json

何も設定しない場合はデフォルトルールに従ってフォーマットされます。(詳細は公式サイトを参照ください)
https://prettier.io/docs/en/options.html
試しに、以下のように設定してみます。
(基本的な設定のみを入れているので、プロジェクトの規約に応じて適宜設定しましょう)

{
  "tabWidth": 4,
  "semi": true,
  "singleQuote": true,
  "useTabs": true
}

4-5.settings.jsonで、以下の設定をしています。

  • eslintを有効にしています。
  • prettierをformatterとして使うようにしています。
  • javascriptを保存した場合に、prettierでフォーマットを行うようにしています。

これでVS Code上で常時eslintのチェックが走るようになり、さらに保存時にprettierで自動的にフォーマットされるようになります。

保存前
セミコロン、コーテーション、スペースなどをバラバラな状態で書いています。

保存後
prettierで設定したルールに基づきフォーマットされます。
・末尾にセミコロンをつけています。
・コーテーションをダブルコーてションからシングルコーテーションに統一しています。
また、eslintが警告を出してくれています。

最終的なディレクトリ構成

プロジェクトフォルダ
┠ ソースを入れるフォルダやファイルなど
┠ .vscodeフォルダ
┃ ┗ extensions.json
┃ ┗ settings.json
┠ .eslintrc.json
┗ .prettierrc.json

参考文献

eslintとprettierの導入
https://note.com/shift_tech/n/n8bbe1c05ba0b
https://zenn.dev/kohski/articles/eslint-prettier-integration

eslint:recommendedで適用されるルールについて
https://www.tam-tam.co.jp/tipsnote/javascript/post11934.html

prettierがeslintよりformatterとして優れている点について
https://qiita.com/soarflat/items/06377f3b96964964a65d

プロフィール

T Kato
T Kato
新卒でSIerに入社し、その後メンバーズに転職。
フロント案件を主に経験していたが、インフラ周りのスキルを身につけたいという思いから社内公募制度を利用し、2022年12月に異動。