PrettierとESLintが不要に!?噂のBiomeを触ってみた!
はじめに
Biome とは ESLint や Prettier を合体させたようなライブラリです。
今回は Nextjs で Biome を日本語公式ドキュメントに沿って触ってみました。
公式ドキュメント
インストール方法
インストールは npm,yarn,pnpm,bun からインストールできます
今回は pnpm を使用していくので pnpm 以外は割愛します。
pnpm add --save-dev --save-exact @biomejs/biome
設定方法
設定方法は biome.json ファイルを作成して設定していきます。
npm なら npx,yarn なら yarn で
@biomejs/biome init
をコマンドで打ち込むと
biome.json とデフォルトのコードが生成されます。
pnpm dlx @biomejs/biome init
Biome は基本デフォルトで使えることを
強く謳っていますが、
細かい設定もできるのでそちらも紹介していきます。
使い方
format
コマンドで--write
オプションをし、
<files>の中にフォーマットしたいファイルを指定することで、
Prettier と同じようなフォーマットを行うことができます。
pnpm dlx @biomejs/biome format <files> --write
lint
コマンドで ESLint と同じようなことを効かせる
ことができます。
--apply
オプションすることにより、できそうな範囲を
自動で修正してくれるようになります。
pnpm dlx @biomejs/biome lint <files>
check
コマンドでは先程の2つのことを
実行することができます。
こちらも--apply
オプションで自動で修正してくれるようになります。
pnpm dlx @biomejs/biome check --apply <files>
大きなプロジェクトでの使用方法
設定ファイルをいくつか置くことができます。
その設定ファイルとかを extends したりとか
それぞれのプロジェクトごとに設定を行うことができます。
backend は backend で front は front で Biome を
効かせることができます。
frontend ディレクトリ内のlegacy-app
とnew-app
は
biome.json ファイルが無いですが
Biome は設定ファイルが見つかるまで上へ上へとディレクトリを移動します。
なのでlegacy-app
とnew-app
の biome 設定ファイルは
frontend 内の biome.json ファイルが適応されます。
設定の共有
extends オプションで設定ファイルを共有することができます。
{
"extends": ["../biome.json"],
"formatter": {
"indentStyle": "space"
}
}
上記は extends で 1 つ手前のディレクトリ内の
biome.json の設定を引き継いでかつ、
上書きしたい設定を書いています。
設定
biome.json
はプロジェクトのルートディレクトリに置く必要があります。
通常package.json
が置かれているところがルートディレクトリです。
設定方法としてformatter
とlinter
に分かれており
わかりやすく設定が行えます。
{
"formatter": {
//有効にするか
"enabled": true,
//インデント
"indentStyle": "tab",
//文字の折返し
"lineWidth": 120
},
"linter": {
//有効にするか
"enabled": false
}
}
package.json や lock ファイル tsconfig.json などは
Biome の設定から自動で外されるようになっています。
VSCode で使う際
VScode では Biome の拡張機能があるので入れておきましょう
Biome VS Code extension
拡張機能を入れることで以下のことができるようになります。
・ファイル保存やコマンドを実行したさいに format を実行する。
・ファイルの静的解析をし、コードの修正を適用してくれます。
Analyzer Import
import の順番
Biome は import 文を距離によってソートします。
ユーザーから遠い
モジュールが上に配置され、
ユーザーに近い
モジュールが下に配置されます。
以下の順番で整理されるようになります。
-
bun: Bun によって実行されるコード
-
node: assert などの一般的な Node ビルドイン
-
npm: Deno で実行されるコード
-
URL を介してインポートされたもの
-
ライブラリからインポートされたもの
-
absolute import(絶対インポート) を使用してインポートされたもの
-
#の接頭辞が付いた名前からインポートされたもの
-
relative import(相対インポート)を使用してインポートされたもの
-
前述の基準で識別できなかったモジュール
import uncle from "../uncle";
import sibling from "./sibling";
import express from "npm:express";
import imageUrl from "url:./image.png";
import assert from "node:assert";
import aunt from "../aunt";
import { VERSION } from "https://deno.land/std/version.ts";
import { mock, test } from "node:test";
import { expect } from "bun:test";
import { internal } from "#internal";
import { secret } from "/absolute/path";
import React from "react";
このコードが次のようにソートされます。
import { expect } from "bun:test";
import assert from "node:assert";
import { mock, test } from "node:test";
import express from "npm:express";
import { VERSION } from "https://deno.land/std/version.ts";
import React from "react";
import { secret } from "/absolute/path";
import { internal } from "#internal";
import aunt from "../aunt";
import uncle from "../uncle";
import sibling from "./sibling";
import imageUrl from "url:./image.png";
グループインポート
import "../styles/reset.css";
import "../styles/layout.css";
import { Grid } from "../components/Grid.jsx";
上記のコードはよくある reset.css をした後に layout.css を 宣言して、
Grid コンポーネントを読み込んでいます。
自動ソートで順番が変わってしまうのはよくないです。
こういった場合に import 文のグループを作成することができます。
やり方は簡単で改行することによりグループを作成することができます。
// グループ 1, この2つのファイルがソートされます。
import "../styles/reset.css";
import "../styles/layout.css";
// グループ 2, この1つのファイルがソートされます。
import { Grid } from "../components/Grid.jsx";
ソートさせたくないものをグループ化する以外で
import type
等のモジュールを分けたい場合などにも
グループ化することができます。
見栄えがよくなりますね
CLI でも import のソートを変更することができます。
biome check --apply ./path/to/src
VSCode の拡張機能では settings.json をいじって設定を行います
{
"editor.codeActionsOnSave": {
"source.organizeImports.biome": true
}
}
{
"editor.defaultFormatter": "biomejs.biome",
"editor.formatOnSave": true,
"editor.codeActionsOnSave": {
//常にオーガナイズインポートを保存時に効かせることができる
"source.organizeImports.biome": "always"
}
}
Formatter
Pritter相当のことをしてくれます。
例えばインデントの整理を行ってくれます。
export const metadata: Metadata = {
title: 'Create Next App',
description: 'Generated by create next app',
}
このようにインデントがめちゃくちゃでも
export const metadata: Metadata = {
title: 'Create Next App',
description: 'Generated by create next app',
}
このようにインデントをきれいにしてくれます。
細かい設定
Formatterをbiome.jsonで細かい設定を行うことができます。
以下はデフォルトです。
{
"formatter": {
//フォーマッタを有効にするか
"enabled": true,
//エラーのあるドキュメントをフォーマット
"formatWithErrors": false,
//インデントのスタイル
"indentStyle": "tab",
//インデントの大きさ
"indentWidth": 2,
//一行に何文字まで書けるか
"lineWidth": 80,
//行末のタイプ
"lineEnding": "lf",
//スタイル パターンの配列 ["scripts/*.js"]など
"ignore": []
}
}
formatの無効化
// biome-ignore format: <説明文>
とすることでコードのフォーマットを無効かすることができます。
説明文の部分は必須です
Pritterとの違い
- 全ての有効な引用符を外してくれます。
const obj = {
a: true,
b: true,
- "𐊧": true,
+ 𐊧: true,
};
- 計算プロパティでの代入で一貫性のない挙動をしない
a = {
- [(x = 0)]: 1,
+ [x = 0]: 1,
};
class C {
[x = 0] = 1;
}
- 必須でない場合はアロー関数の
型パラメータの末尾にコンマを追加しない
- <T = unknown,>() => {};
+ <T = unknown>() => {};
- 括弧で囲まれた非 null アサートの
オプション チェーンに対して1貫制をもたせる
a.?.b!
- (a.?.b)!
+ a.?.b!
- (a.?.b)!
+ a.?.b!
-
Prettierにはいくつかの無効なフォーマット構文があります。
-
TypeScript と Babel の解析の間に矛盾がある
PrettierではisEqual
を呼び出すけど
Biomeではbabel
及びbabel-ts
を照合します。
function someFunctionName(
someLongBreakingParameterName,
anotherLongParameterName,
) {
- return isEqual(a?.map(([t, _]) => t?.id), b?.map(([t, _]) => t?.id));
+ return isEqual(
+ a?.map(([t, _]) => t?.id),
+ b?.map(([t, _]) => t?.id),
+ );
}
Biomeの方が見やすいよねってことです。
Linter
ESLint相当のことをしてくれます。
Linterとはコードの指針みたいなものです。
例えばfunctionじゃなくarrow関数使いましょう
みたいな感じです。
例えばapp直下のlayout.tsxにあるMetadataの
import文でtypeを消すと
import type { Metadata } from 'next'
↓
import { Metadata } from 'next'
//All these imports are only used as types.
//タイプをつけろよと怒られます。
設定したLinterで下記のコードでチェックを行うことができます。
pnpm biome lint ./app
✖ All these imports are only used as types.
1 │ import { Metadata } from "next";
先程のMetadataにtypeを入れましょうねと言われています。
Biomeが自動でこのコードを修正しても
問題ないだろうと判断したものを修正するコマンドがあります。
pnpm biome check --apply ./app
上記のコマンドを打つことにより
Layout.tsxのMetadataに自然とtypeが
付与されています。
Linterでチェックを行った際にpage.tsxにも
エラーが出ていると思います。
- <h2 className={`mb-3 text-2xl font-semibold`}>
+ <h2 className={"mb-3 text-2xl font-semibold"}>
クラスネームの中はバッククォートではなく
ダブルクォートを使ってくださいねと言われています。
ただし、checkコマンドでは修正できず
修正したら問題がおきるかもとBiomeが判断しています。
ぶっ壊れてもいいから修正してねのコマンドがあります。
pnpm biome check --apply-unsafe ./app
こちらを打つことによりpage.tsx内の
コードも修正されました。
あんまりやらないでねと公式には書いてあるので
手動で直していきましょう。
linterの無効化
// biome-ignore lint: <explanation>
formaterの時と同じく無効化することができます。
やり方はほとんど一緒です。
lintルールを設定する。
biome.jsonファイルでrulesを指定することにより
細かい設定を行うことができます。
{
"linter": {
"enabled": true,
"rules": {
"style": {
//ブロックにステートメントが1しかなくても中括弧つける
"useBlockStatements": "error",
//T[]の配列型で短縮表現する
"useShorthandArrayType": "error",
//定数の大文字はだめ
"noShoutyConstants": "warn"
}
}
}
}
rulesの下にあるstyle
って何を指してるかと言うと
lint/nursery
のnurseryを指しています。
jsonファイルはstyleを指定しているので
styleのルールを指定していることになります。
対応言語
Biomeの言語サポートは以下の通りになっています。
HTMLやCSSなどはまだ実装されておらず
これから実装されていくかと思われます。
なので現段階では、対応されていない言語などに
関してはPrettierを指定することをおすすめしています。
まとめ
ESLintとPritterを設定するの大変なのですが
Biomeはlinterとformaterを設定が行えて
同時に構文解析ができる利点もあるので
僕自身は今後Biomeでプロジェクトを作成して
いこうと思いました!
Discussion