linterとformatterが一つに!?Biome使ってみた

はじめに

皆さんこんにちは。エンジニアの細川です。

今回はアドベントカレンダーで記事を書いてみたいと思います!

テーマは「サイオス社員が今年一年で新たに学んだ技術」です!

今回はTypeScript界隈で注目されている!?Biomeについて紹介したいと思います!

Biomeとは

BiomeはTypeScriptやJavaScriptなどの言語のLinterとFormatterが一つになったようなツールです。ESLintやprettierなどは皆さん使われているかと思いますが、それらの代わりにBiome一つで、コードの静的解析を行ったり、成形をしてくれたりします。

BiomeはRustで動作しており、既存のESLintやprettierなどと比べてかなり高速に動作するみたいです。

導入方法

早速導入方法について紹介します。

まず、Biomeを以下のコマンドでインストールします。

npm install --save-dev --save-exact @biomejs/biome

その後、以下のコマンドを叩くことで、Biomeの設定ファイルであるbiome.jsonが作成されます。

npx @biomejs/biome init

デフォルトの設定で良い場合は作成不要とのことですが、作成しておくことをお勧めします。

これで基本的には導入完了です。

使い方

導入が完了すれば以下のコマンドでlinterやformatterを実行できます。

formatコマンドでファイルやディレクトリなどをformatできます。

npx biome format --write <files>

lintコマンドを実行すると、コードの静的解析が行えます。

npx biome lint --write <files>

また、writeオプションを利用すると、安全に修正可能な問題に対しては修正をしてくれます。詳細はこちらをご確認ください。

checkコマンドを利用すればlintとformat両方を実行できます。

npx biome check --write <files>

それぞれpackage.jsonに以下のように設定しておくと便利かと思います。

"scripts": {
    "lint": "biome lint src",
    "format": "biome format src",
    "check": "biome check src"
  },

拡張機能

また、BiomeはVSCodeの拡張機能も存在しており、導入しておくことで、ルールにそぐわない場合にエラー表示を出してくれたり、保存時にformatをかけてくれたりするので、ぜひ導入しておくことをお勧めします。

こちらからインストールすることができます。

導入した後はCtrl + Shift + Pでコマンドパレットを開き、「format」と入力して表示されるFormat Documentをクリックしてください。

その後既定のフォーマッターを構成からBiomeを選択しておくことで、その言語のデフォルトのフォーマッターでBiomeが使われるようになります。

また、VSCodeの設定を開き、saveで検索して出てくるFormat On SaveをONにしておけば、save時に自動でフォーマットしてくれるようになります。

運用

linterを導入しても、手でいちいちコマンドを叩くのがめんどくさいこともあるのではないでしょうか?また、叩き忘れがあったりなども多いため、自動でlinterが走るようにしたいこともあると思います。

僕のプロジェクトでは、lefthookと併用し、commit時に自動でlintコマンドを走らせることで叩き忘れ等を防止しています。

lefthookとはgitコマンドが実行される前後に自動で走るスクリプトを管理できるツールです。詳しくは公式のドキュメントをご確認ください。

まず、以下のコマンドでlefthookをインストールします。

npm install @evilmartians/lefthook --save-dev

その後、.gitが存在するディレクトリで以下のコマンドを叩きます。

lefthook install

このコマンドを叩くことで、そのディレクトリにてlefthookが利用できるようになります。

lefthook.ymlが生成されるはずなので、pre-commit部分に以下を追記します。

pre-commit:
  commands:
  glob: "*.{js,ts,jsx,tsx}"
    biome:
      run: npm run check <- biome checkなど実行したいコマンド

これでcommit時に自動でbiome checkが走るようになります。

Biomeは動作も高速なので、そこまでストレスには感じずにチェックを行えるかと思います。

モノレポ設定について

一つのリポジトリでフロントとバックを両方管理するような場合もあるかと思います。

その場合、フロントとバックで共通のルールもあれば、このルールはバックエンドだけに適用したいなんて言うこともあるかと思います。

そのような場合、フロントとバックでそれぞれbiome.jsonを用意することで別々のルールを適用することができます(参考)。

ただし、この方法には一つ問題があります。それはVSCodeの拡張機能では現在開いているディレクトリに存在するbiome.jsonしか認識してくれないという点です。

具体的には、例えば以下のような構成があったとします。

- root
| - biome.json <- 共通の設定
| - front/
	| - biome.json <- フロントのみの設定
	| - src/
| - back/
  | - biome.json <- バックのみの設定
  | - src/

このときrootを開いて作業すると、フロントやバックに指定しているルールは拡張機能でエラー表示してくれず、クイックフィックスなども利用できません。

都度都度ディレクトリを開きなおせばいいのですが、フロントとバック横断して開発する場合などはいちいち開きなおすのが面倒なこともあると思います。

このような場合は、以下のようにoverridesを利用することで、フロントとバックのルールを一つにまとめることができます。

{
  "$schema": "https://biomejs.dev/schemas/1.8.0/schema.json",
  "formatter": {
    "indentStyle": "space",
    "indentWidth": 2
  },
  "organizeImports": {
    "enabled": true
  },
  "linter": {
    "enabled": true,
    "rules": {
      "recommended": true // <- 全体に適用するルール
    }
  },
  "overrides": [
    {
      "include": ["backend/**"],
      "ignore": [
        "backend/node_modules/**",
        "backend/dist/**",
      ],
      "linter": {
        "enabled": true,
        "rules": { // <- バックエンドのみに適用するルール
          "style": {
            "useImportType": "off"
          },
        }
      },
      "javascript": {
        "parser": {
          "unsafeParameterDecoratorsEnabled": true
        }
      }
    },
    {
      "include": ["frontend/**"],
      "ignore": [
        "frontend/node_modules",
        "frontend/dist",
      ],
      "linter": {
        "enabled": true,
        "rules": { // <- フロントエンドのみに適用するルール
	        "nursery": {
            "noConsole": "error" 
          }
        }
      }
    },
  ]
}

デメリットとして設定ファイルが巨大化して少し読みづらくなるという点はありますが、僕のプロジェクトでは拡張機能の利便性の方を優先し、このような設定にしています。

Biomeのデメリット

これまでBiomeのメリットや使い方等をお話ししてきましたが、Biomeには一つかなり大きな問題点があるかなと思います。

それはカスタムルールが設定できないという点です(このブログ執筆時点では方法を見つけられませんでした)。カスタムルールのためのプラグイン開発は進行中のようです(参考)。

そこで、Biomeで対応できないルールのみESLintでチェックを行うというような構成をお勧めします。

ESlintは以下のコマンドでインストールすることができます。

npm install --save-dev eslint

そのあとeslinrc.jsを作成します。(ymlやjsonでも設定ファイルを記述することができます。こちらの記事で分かりやすく書いてくれていました。)

module.exports = {
  parser: "@typescript-eslint/parser",
  parserOptions: {
    project: "tsconfig.json",
    tsconfigRootDir: __dirname,
    sourceType: "module",
  },
  plugins: ["@typescript-eslint/eslint-plugin"],
  extends: ["plugin:@typescript-eslint/recommended"],
  root: true,
  env: {
    node: true,
    jest: true,
  },
  ignorePatterns: [".eslintrc.js", "src/generated/*"],
  rules: {
    "@typescript-eslint/interface-name-prefix": "off",
    "@typescript-eslint/explicit-function-return-type": "off",
    "@typescript-eslint/explicit-module-boundary-types": "off",
    "@typescript-eslint/no-explicit-any": "off",
    //biomeがカバーしているルールを無効化
    semi: "off",
    quotes: ["error", "double"],
    // ----------------↓Biomeで対応できないルールを追加-----------------------
    "no-restricted-syntax": [
      "error",
      {
        // letを禁止
        selector: "VariableDeclaration[kind='let']",
        message: "'let'は禁止です。代わりに'const'を使用してください。",
      },
    ],
  },
};

注意点としては、Biomeで設定しているルールとバッティングする内容についてはoffにしておくことです。

基本的なチェックはBiomeで行うので、pluginなどが無い方が簡潔になるかもしれません。

今回は例として、letを禁止するルールを追加してみています。

後は、以下のコマンドをpackage.jsonに追加しておけばeslintも叩けるようになります。

"scripts": {
	"lint:es": "eslint --ext .ts src",
	...
}

ESLintはBiomeに比べると実行に時間がかかるので、僕のプロジェクトではcommit時のチェックはせずに、PR作成時にCIで回るようにしています。

このあたりは皆さんのプロジェクトに合わせて調整してください。

まとめ

  1. Biomeはlinterとformatterが一つになったツール

    1. lint

      npx biome lint --write <files>
    2. format

      npx biome format --write <files>
    3. lint + format

      npx biome check --write <files>
  2. VSCodeの拡張機能を導入すればエラー表示&自動フォーマット可能

  3. lefthookと併用することでcommit時に自動チェック

  4. フロント、バックなどでルールを分けたい場合はoverridesを利用

    1. overridesを利用することでVSCodeの拡張機能も問題なく利用できる!
  5. Biomeで設定できないルールはESLintでチェック

おわりに

今回は、Biomeについて紹介しました。基本的には設定も簡単で動作も早く、かなりお勧めなツールになります。ただ、カスタムルールを設定できないという弱点もあるので、その場合はぜひESLintと併用するという方法も試していただければと思います!

今後もお勧めの構成などがあれば紹介していきたいと思います!

他にも今月はアドベントカレンダーで様々な記事が投稿されると思うのでぜひチェックしてみてください。

今回参考にさせていただいた記事

https://biomejs.dev/ja/guides/getting-started/

https://qiita.com/howdy39/items/6e2c75861bc5a14b2acf

https://blog.solunita.net/posts/change-lefthook-instead-of-lintstaged-with-husky/

ご覧いただきありがとうございます! この投稿はお役に立ちましたか?

役に立った 役に立たなかった

0人がこの投稿は役に立ったと言っています。

コメントを残す

メールアドレスが公開されることはありません。 が付いている欄は必須項目です