フォーマッターとリンターを兼ね備えた「Biome」を触ってみる
Biomeとは
Romeのコアメンバー達が新しく開発したツールです。
Romeはフォーマッター、リンター、テスト、トランスパイラ、バンドラなどのチェンツールを1つで担っていましたが、Biomeでは現在(2023年10/2)フォーマッターとリンターの機能のみを提供しています。
導入
Romeからの移行も簡単に出来るようです。以下の記事が参考になります
インストール
npm install --save-dev --save-exact @biomejs/biome
or
yarn add --dev --exact @biomejs/biome
or
pnpm add --save-dev --save-exact @biomejs/biome
or
bun add --dev --exact @biomejs/biome
設定ファイルを生成する
pnpm biome init
Biomeの設定ファイルがプロジェクト直下に生成されます
{
"$schema": "https://biomejs.dev/schemas/1.2.2/schema.json",
"organizeImports": {
"enabled": true
},
"linter": {
"enabled": true,
"rules": {
"recommended": true
}
}
}
vscodeで使えるようにする
-
vscodeの拡張機能をインストールします
-
.vscode/extensions.json
で拡張機能のレコメンドもしましょう
{
"recommendations": [
"biomejs.biome"
]
}
-
.vscode/settings.json
に設定を追加します詳しい詳細
formatterの設定
-
js
,jsx
,ts
,tsx
ファイルをBiomeが担当 - それ以外はここでは
Prettier
に任せます
.vscode/settings.json{ "editor.formatOnSave": true, "editor.defaultFormatter": "esbenp.prettier-vscode", "[javascript]": { "editor.defaultFormatter": "biomejs.biome" }, "[javascriptreact]": { "editor.defaultFormatter": "biomejs.biome" }, "[typescript]": { "editor.defaultFormatter": "biomejs.biome" }, "[typescriptreact]": { "editor.defaultFormatter": "biomejs.biome" } }
lintの設定
- 保存時にlinterを走らせる
settings.json{ "editor.codeActionsOnSave": { "quickfix.biome": true } }
Analyzerの設定
- 保存時にimportのソートを実行
.vscode/settings.json{ "editor.codeActionsOnSave":{ "source.organizeImports.biome": true } }
全体のまとめ
.vscode/settings.json{ "editor.formatOnSave": true, "editor.defaultFormatter": "esbenp.prettier-vscode", "[javascript]": { "editor.defaultFormatter": "biomejs.biome" }, "[javascriptreact]": { "editor.defaultFormatter": "biomejs.biome" }, "[typescript]": { "editor.defaultFormatter": "biomejs.biome" }, "[typescriptreact]": { "editor.defaultFormatter": "biomejs.biome" }, "editor.codeActionsOnSave": { "quickfix.biome": true, "source.organizeImports.biome": true } }
-
コマンドを試す
コマンドの一覧
-
version
: Biomeバージョンの情報を表示して終了 -
rage
: デバッグの情報を印刷 -
start
: Biomeデーモンサーバープロセスを開始する -
stop
: Biomeデーモンサーバープロセスを停止する -
check
: 一連のファイルに対してさまざまなチェックを実行します。 -
lint
: 一連のファイルに対してlintterを実行します。 -
format
: 一連のファイルでformatterを実行します。 -
ci
: CI環境で使用するコマンド。一連のファイルのさまざまなチェックを実行します。 -
init
: 新しいバイオームプロジェクトをブートストラップします。一部のデフォルトで構成ファイルを作成します。 -
lsp-proxy
: stdin / stdout上のLanguage Server Protocolのサーバーとして機能します -
migrate
: 変更が発生したときに構成を更新します
formatterのコマンド
pnpm biome format ./src
書き換える時は --write
を追加します
pnpm biome format --write ./src
lintterのコマンド
pnpm biome lint ./src
書き換える時は --apply
を追加します
pnpm biome lint --apply ./src
biome.jsonのプロパティ
-
$schema
- Biomeのバージョン
- biome.jsonファイルで使うプロパティの型のようなもの
-
extends
- ファイルパスを指定して、他の設定ファイルを継承できる
-
files
-
maxSize
- バイト単位のソースコードファイルの最大許容サイズ デフォルト:1024 * 1024 ( 1MB )
-
ignore
- 無視するファイルパス。配列で書く
-
allowUnknown
- 処理できないファイルに遭遇した場合、検出するか
-
-
vsc
- Version Control System
- BiomeをVCSソフトウェアと統合するための一連のプロパティ。
-
linter
-
enable
- 許可する
-
ignore
- 除くファイルパス
-
rules
- リンターの設定(後に紹介します)
-
-
formatter
- フォーマッターの設定(後に紹介します)
-
organizeImports
- アナライザーの設定(後に紹介します)
-
javascript
- JS・TSのみ効く設定
-
parser.unsafeParameterDecoratorsEnabled
- 安全でない/実験的なパラメーターデコレーターをサポートできます。
-
formatter
- フォーマッターの設定(後に紹介します)
-
globals
- 無視するグローバル名
-
json
- jsonのみ効く設定
-
parser
-
allowComments
- コメントを許可
-
allowTrailingCommas
- 末尾のカンマを許可
-
-
formatter
- フォーマッターの設定(後に紹介します)
Anlyzer
アナライザーは、ユーザーが活用できる一連の機能を提供しています。現在はorganizeImports
だけ提供しているみたいです。
{
"organizeImports": {
"enabled": true
}
}
ソートは以下のように実行されます
- importの行のソート
- 参照先(from)で大文字をアルファベット順 → 小文字をアルファベット順
- importの{}の中のソート
- 大文字をアルファベット順 → 小文字をアルファベット順
ソート前
import { aa } from 'z'
import { a, B, c, D } from 'a'
import { C } from 'c'
import { b } from 'B'
import { d } from 'D'
ソート後
import { B } from 'B'
import { D } from 'D'
import { B, D, a, c } from 'a'
import { c } from 'c'
import { aa } from 'z'
改行があると、そのまとまりで上記のようにソートされる
ソート前
import { aa } from 'z'
import { a, B, c, D } from 'a'
import { B } from 'B'
import { c } from 'c'
import { D } from 'D'
ソート後
import { B } from 'B'
import { B, D, a, c } from 'a'
import { aa } from 'z'
import { D } from 'D'
import { c } from 'c'
注意点
- グループ化は自分で改行いれる必要がある
- 並び順をカスタマイズ出来ない
- 使っていないのを削除、重複で削除、fromが同じなら合体等は出来ない
formatter
フォーマットには3種類あります
-
formatter
: 全てのファイルのルール -
javascript
: js, ts, jsx, tsxのルール -
json
: jsonのルール
全体のformatterの設定
プロパティはPrettierと同じなので取っつきやすいです
- formatWithErrors: ファイルに構文エラーがある時に、フォーマットを許可するかどうか
{
"formatter": {
"enabled": true,
"formatWithErrors": false,
"ignore": [],
"indentSize": 2,
"indentStyle": "space",
"lineWidth": 80
}
}
javascriptのformatterの設定
"javascript"のformatterの詳細
js, ts, jsx, tsxで使用されるフォーマッターのルールです。
ここもPrettierと同じなので取っつきやすいです
{
"javascript": {
"parser": {
"unsafeParameterDecoratorsEnabled": true
},
"formatter": {
"enabled": true,
"quoteStyle": "single",
"jsxQuoteStyle": "single",
"trailingComma": "all",
"semicolons": "asNeeded",
"arrowParentheses": "asNeeded",
"indentSize": 2,
"indentStyle": "space",
"lineWidth": 80,
"quoteProperties": "asNeeded"
}
}
jsonのformatterの設定
{
"json": {
"parser": { "allowComments": true },
"formatter": {
"enabled": true,
"indentStyle": "space",
"indentSize": 2,
"lineWidth": 80
}
}
}
linter
ルールの値は、error
, warn
, off
の3段階で設定できます。これはESLintの2,1,0とも同じですね。
また、オプションがあるルールもあり、ルール: {level: "error", options: {...}}
のように設定できます。
以下は用途ごとに分類分けしたものです。これらの中にルールが複数存在するのでそれを確認して設定していきます。
-
a11y
- アクセシビリティの問題を防ぐことに焦点を当てたルール。
-
complexity
- 簡略化できる複雑なコードの検査に焦点を当てたルール。
-
correctness
- 正しくないか役に立たないことが保証されているコードを検出するルール。
-
performance
- コードをより速く実行するように記述する方法、または一般的により効率的にする方法をキャッチするルール。
-
security
- 潜在的なセキュリティ欠陥を検出するルール。
-
style
- コードを一貫して慣用する方法で作成するルール。
-
suspicious
- 正しくないか役に立たない可能性が高いコードを検出するルール。
-
nursery
- まだ開発中の新しいルール。
- バグやパフォーマンスの問題がまだある可能性があるため、安定バージョンの構成による明示的なオプトインが必要です。 これらは毎晩のビルドでデフォルトで有効になっていますが、不安定であるため、診断の重大度はエラーまたは 最終的に安定したときにルールを推奨するかどうかに応じて、警告。 保育園のルールは、安定するか削除されると、他のグループに昇格されます。
- このグループに属するルール セマンティックバージョンの対象ではありません。
また、Biomeではrules
でall
とrecommended
プロパティが使うことが出来てとても便利です。
rules
の直下で使うと全てのルールに適用されるので、recommended: true
で設定し、biome lint
で確認をして合わないルールがあれば個別でoff
にするのが良いかと思います。
以下は用途ごとに分類分けしたルールで、それぞれall
, recommended
プロパティが使えます。なので、例えばa11y
はall: true
, complexity
はrecommended: true
のような設定が出来ます。便利ですね!
- all
- trueで全てのルールを適用
- recommended
- trueで全てのルールのオススメを適用
- どのルールがrecommendedかは、ルール一覧で✅が付いているものから確認できます
以下のようにrules
の設定をすることが出来ます
{
"linter": {
"rules": {
"a11y": {
"noAccessKey": "error",
"noAriaUnsupportedElements": "warn",
"noAutofocus": "off",
"noBlankTarget": {
"level": "error",
"options": {
"strictCase": false,
"enumMemberCase": "CONSTANT_CASE"
}
}
},
"complexity": {
"recommended": true
},
"performance": {
"all": true
}
}
}
}
最終形態
最終的なbiome.json
は以下のようになりました!
linter
のルールはぱっとしか見れてないのでご了承
{
"$schema": "https://biomejs.dev/schemas/1.2.2/schema.json", // Biomeのバージョン
"extends": [], // ローカルの設定ファイルを継承できる
"files": { "ignoreUnknown": true }, // 処理できないファイルに遭遇した場合、検出するか
"organizeImports": {
"enabled": true // importのソートをする
},
"formatter": {
"enabled": true,
"formatWithErrors": false, // ファイルでエラーがある時フォーマットをしない
"ignore": [],
"indentSize": 2,
"indentStyle": "space",
"lineWidth": 80
},
"javascript": {
"parser": {
"unsafeParameterDecoratorsEnabled": true // 安全でない/実験的なパラメーターデコレーターをサポートする
},
"formatter": {
"quoteStyle": "single",
"jsxQuoteStyle": "single",
"trailingComma": "all", // 末尾のオブジェクトにカンマを付ける
"semicolons": "asNeeded",
"arrowParentheses": "asNeeded" // 関数のPropsが一つなら()で括らない
}
},
"json": {
"parser": { "allowComments": true }, // コメントを許可
"formatter": {
"enabled": true,
"indentStyle": "space",
"indentSize": 2,
"lineWidth": 80
}
},
"linter": {
"ignore": [],
"rules": {
"a11y": {
"noAriaUnsupportedElements": "error", // ARIAの役割、状態、およびプロパティをサポートしない要素には、これらの属性がないことを強制
"noBlankTarget": "error", // target="_blank"を使う時、rel=“noreferrer”を強制
"noDistractingElements": "error", // 存在しない要素でエラー
"noNoninteractiveElementToInteractiveRole": "error", // インタラクティブなARIAロールが非インタラクティブHTML要素に割り当てられないように
"noPositiveTabindex": "error", // tabIndexで整数使うとエラー
"noRedundantAlt": "error", // 暗黙的なロールでのroleの使用でエラー
"useAltText": "error", // alt必要な要素で強制
"useAriaPropsForRole": "error", // ARIAロールで必須のARIA属性を強制
"useHtmlLang": "error", // HTMLのlangを使う
"useIframeTitle": "error", // iframeでtitleを強制
"useMediaCaption": "error", // audio, video要素で、track要素を強制
"useValidAnchor": "error", // すべてのアンカーが有効である
"useValidAriaProps": "error", // 正しいaria-*を使う
"useValidAriaValues": "error", // 正しいARIAを使う
"useValidLang": "error" // lang属性で正しい言語・国を使う
},
"complexity": {
"noBannedTypes": "warn", // 誤解を招く型でエラー
"noExtraBooleanCast": "error", // 無駄なBooleanでエラー
"noForEach": "warn", // forEachでエラー。for ofを使う
"noMultipleSpacesInRegularExpressionLiterals": "error", // 正規表現の連続スペースでエラー
"noStaticOnlyClass": "error", // staticだけのclassでエラー
"noUselessConstructor": "error", // 無駄なconstructorでエラー
"noUselessRename": "error", // 無駄な as でエラー
"noUselessSwitchCase": "error", // 無駄なswitchのcaseでエラー
"useLiteralKeys": "error", // オブジェクトで、 a[b]ではなく、a.bを使う
"useOptionalChain": "error", // オプショナルチェーンを使うようにする
"useSimplifiedLogicExpression": "error" // 無駄な論理式でエラー出す 例) const bool = true || foo
},
"correctness": {
"noChildrenProp": "error", // コンポーネントのchildrenをPropsで渡すとエラー
"noConstAssign": "error", // constを再代入でエラー
"noConstantCondition": "error", // 条件式の中身が定数でエラー(確定するから)
"noEmptyPattern": "error", // 空のオブジェクトを禁止 const {} = a, const {a: {}} = foo
"noPrecisionLoss": "error", // 桁数の多すぎる数字でエラー(制度が落ちる)
"noRenderReturnValue": "error", // ReactDOM.renderの代入を許可しない const foo = ReactDOM.render()
"noSelfAssign": "error", // a = aを許可しない
"noSetterReturn": "error", // classのsetメソッドが値を直接返すのを禁止
"noStringCaseMismatch": "error", // 違う文字のCaseとの比較でエラー 例)toUpperCaseした文字と、そうでない文字との比較
"noUnnecessaryContinue": "error", // ループ文の最初でcontinueするとエラー
"noUnreachable": "error", // 到達不可能なコードでエラー
"noInvalidConstructorSuper": "error", // extendsしてたらconstructorでsuperを強制
"noUnsafeOptionalChaining": "error", // 安全でないオプショナルチェーンでエラー
"noUnusedVariables": "warn", // 未使用の変数でエラー
"noVoidElementsWithChildren": "error", // childrenの無い要素に入れるとエラー
"noVoidTypeReturn": "error", // 返り値がvoid型の関数が、returnするとエラー
"useIsNan": "error", // NaNを比較するとエラー
"useValidForDirection": "error" // forループで、終了しない条件だとエラー
},
"performance": {
"noDelete": "error" // delete演算子使うとエラー
},
"security": {
"noDangerouslySetInnerHtml": "warn" // dangerouslySetInnerHTML禁止
},
"style": {
"noArguments": "error", // 定義してない変数使うとエラー
"noNegationElse": "warn", // 条件で!fooのように書いてelseがあるとエラー
"noNonNullAssertion": "warn", // foo!.varの書き方でエラー
"noParameterAssign": "error", // 関数の引数を関数内で更新するとエラー
"noUnusedTemplateLiteral": "error", // 普通の文字列でテンプレート文字列使うとエラー
"noVar": "error", // var使うとエラー
"useConst": "error", // letで再代入されないお変数はエラー、constにする
"useExponentiationOperator": "error", // 階乗でMath.pow使うとエラー、**に置換
"useNamingConvention": "off", // snakeCaseでエラー、optionで変えられる
"useSelfClosingElements": "error", // <div></div>のように子供の無い要素でエラー、<div/>に置換
"useShorthandArrayType": "error", // 型でArray使うとエラー、[]に置換
"useTemplate": "error" // 文字の足し算は全てテンプレート文字列にする
},
"suspicious": {
"noArrayIndexKey": "error", // JSXのmapでkeyにindexを渡すとエラー
"noAssignInExpressions": "error", // 条件式に中で再代入するとエラー
"noAsyncPromiseExecutor": "error", // new Promise()の中でasync関数使用するとエラー
"noCatchAssign": "error", // catch(e)のeに再代入するとエラー
"noClassAssign": "error", // classに再代入するとエラー
"noCommentText": "error", // JSX内の正しくないコメントでエラー <div>// a</div> => <div>{/* a */}</div>
"noCompareNegZero": "error", // -0と比較するとエラー
"noConsoleLog": "warn", // console.logでエラー
"noDoubleEquals": "error", // 比較で==を禁止、===にする
"noDuplicateCase": "error", // switchの重複するcaseでエラー
"noDuplicateClassMembers": "error", // classの重複するメソッドでエラー
"noDuplicateJsxProps": "error", // コンポーネントの重複するPropsでエラー
"noDuplicateObjectKeys": "error", // 重複するオブジェクトのkeyでエラー
"noDuplicateParameters": "error", // 関数の重複するparamsでエラー
"noEmptyInterface": "error", // 空のinterfaceの定義でエラー
"noExplicitAny": "warn", // anyの仕様を禁止
"noExtraNonNullAssertion": "error", // 間違った非nullアサーションでエラー
"noFunctionAssign": "error", // functionの再代入するとエラー
"noImportAssign": "error", // importで使う値を再代入するとエラー
"noPrototypeBuiltins": "error", // エラーの恐れのあるオブジェクトのプロパティでエラー 例 propertyIsEnumerable, isPrototypeOf
"noRedeclare": "error", // 同じ名前の宣言でエラー
"noRedundantUseStrict": "error", // use strictが同じファイルで重複するとエラー
"noSelfCompare": "error", // 同じ値の比較でエラー
"noShadowRestrictedNames": "error", // 予約語で命名するとエラー
"noUnsafeDeclarationMerging": "error", // 同じ名前のclassとinterfaceを定義するとエラー
"useDefaultSwitchClauseLast": "error", // switchでdefaultが最後でないとエラー
"useGetterReturn": "error", // classのgetメソッドでreturnをしないとエラー
"useValidTypeof": "error" // typeofで比較する値が正しくないとエラー
},
"nursery": {
"noDuplicateJsonKeys": "error", // JSONオブジェクトで同じkey使うとエラー
"noEmptyCharacterClassInRegex": "error", // 正規化の[]の中が空だとエラー
"noExcessiveComplexity": "warn", // 複雑なコード書くとエラー(階層が深くなる)
"noGlobalIsFinite": "error", // isFiniteでは無く、Number.isFiniteを使う
"noGlobalIsNan": "error", // isNaNでは無く、Number.isNaNを使う
"noUselessElse": "warn", // 無駄なelseは早期リターンにする
"useArrowFunction": "warn", // アロー関数を強制
"useCollapsedElseIf": "warn", // elseの中の無駄な条件をelse ifに強制する
"useExhaustiveDependencies": "warn", // useEffect等のHooksの依存配列が正しくないとエラー
"useGroupedTypeImport": "error", // import {type A, type B}を、import type {A, B}に強制
"useHookAtTopLevel": "error", // HooksはTopレベルで使わないとエラー
"useIsArray": "error", // instanceof Arrayではなく、Array.isArray()を強制
"useShorthandAssign": "error" // 短い書き方を強制 a = a + 1 => a += 1
}
}
}
}
コメントなしver
{
"$schema": "https://biomejs.dev/schemas/1.2.2/schema.json",
"extends": [],
"files": { "ignoreUnknown": true },
"organizeImports": {
"enabled": true
},
"formatter": {
"enabled": true,
"formatWithErrors": false,
"ignore": [],
"indentSize": 2,
"indentStyle": "space",
"lineWidth": 80
},
"javascript": {
"parser": {
"unsafeParameterDecoratorsEnabled": true
},
"formatter": {
"quoteStyle": "single",
"jsxQuoteStyle": "single",
"trailingComma": "all",
"semicolons": "asNeeded",
"arrowParentheses": "asNeeded"
}
},
"json": {
"parser": { "allowComments": true },
"formatter": {
"enabled": true,
"indentStyle": "space",
"indentSize": 2,
"lineWidth": 80
}
},
"linter": {
"ignore": [],
"rules": {
"a11y": {
"noAriaUnsupportedElements": "error",
"noBlankTarget": "error",
"noDistractingElements": "error",
"noNoninteractiveElementToInteractiveRole": "error",
"noPositiveTabindex": "error",
"noRedundantAlt": "error",
"useAltText": "error",
"useAriaPropsForRole": "error",
"useHtmlLang": "error",
"useIframeTitle": "error",
"useMediaCaption": "error",
"useValidAnchor": "error",
"useValidAriaProps": "error",
"useValidAriaValues": "error",
"useValidLang": "error"
},
"complexity": {
"noBannedTypes": "warn",
"noExtraBooleanCast": "error",
"noForEach": "warn",
"noMultipleSpacesInRegularExpressionLiterals": "error",
"noStaticOnlyClass": "error",
"noUselessConstructor": "error",
"noUselessRename": "error",
"noUselessSwitchCase": "error",
"useLiteralKeys": "error",
"useOptionalChain": "error",
"useSimplifiedLogicExpression": "error"
},
"correctness": {
"noChildrenProp": "error",
"noConstAssign": "error",
"noConstantCondition": "error",
"noEmptyPattern": "error",
"noPrecisionLoss": "error",
"noRenderReturnValue": "error",
"noSelfAssign": "error",
"noSetterReturn": "error",
"noStringCaseMismatch": "error",
"noUnnecessaryContinue": "error",
"noUnreachable": "error",
"noInvalidConstructorSuper": "error",
"noUnsafeOptionalChaining": "error",
"noUnusedVariables": "warn",
"noVoidElementsWithChildren": "error",
"noVoidTypeReturn": "error",
"useIsNan": "error",
"useValidForDirection": "error"
},
"performance": {
"noDelete": "error"
},
"security": {
"noDangerouslySetInnerHtml": "warn"
},
"style": {
"noArguments": "error",
"noNegationElse": "warn",
"noNonNullAssertion": "warn",
"noParameterAssign": "error",
"noUnusedTemplateLiteral": "error",
"noVar": "error",
"useConst": "error",
"useExponentiationOperator": "error",
"useNamingConvention": "off",
"useSelfClosingElements": "error",
"useShorthandArrayType": "error",
"useTemplate": "error"
},
"suspicious": {
"noArrayIndexKey": "error",
"noAssignInExpressions": "error",
"noAsyncPromiseExecutor": "error",
"noCatchAssign": "error",
"noClassAssign": "error",
"noCommentText": "error",
"noCompareNegZero": "error",
"noConsoleLog": "warn",
"noDoubleEquals": "error",
"noDuplicateCase": "error",
"noDuplicateClassMembers": "error",
"noDuplicateJsxProps": "error",
"noDuplicateObjectKeys": "error",
"noDuplicateParameters": "error",
"noEmptyInterface": "error",
"noExplicitAny": "warn",
"noExtraNonNullAssertion": "error",
"noFunctionAssign": "error",
"noImportAssign": "error",
"noPrototypeBuiltins": "error",
"noRedeclare": "error",
"noRedundantUseStrict": "error",
"noSelfCompare": "error",
"noShadowRestrictedNames": "error",
"noUnsafeDeclarationMerging": "error",
"useDefaultSwitchClauseLast": "error",
"useGetterReturn": "error",
"useValidTypeof": "error"
},
"nursery": {
"noDuplicateJsonKeys": "error",
"noEmptyCharacterClassInRegex": "error",
"noExcessiveComplexity": "warn",
"noGlobalIsFinite": "error",
"noGlobalIsNan": "error",
"noUselessElse": "warn",
"useArrowFunction": "warn",
"useCollapsedElseIf": "warn",
"useExhaustiveDependencies": "warn",
"useGroupedTypeImport": "error",
"useHookAtTopLevel": "error",
"useIsArray": "error",
"useShorthandAssign": "error"
}
}
}
}
所感
良いと思ったところ
- 設定ファイルが1つにまとまるので見通しが良い
- コードの実行速度がPrettier、ESLintよりも速い
- formatterのルールがPrettier互換で取っつきやすい
- lintのルールがある程度充実しているので、公式ドキュメントからプロジェクトに合うルールが探しやすい
- pluginを入れずにルールを充実させられる
- lintのルールが用途ごとに分類されていて探しやすい!
- lintのルールの
all
、recommended
プロパティが便利!
改善して欲しいところ
- フォーマッターがjs, ts, jsx, tsx, jsonのみのサポートなので、それ以外のファイルは別のフォーマッターが必要になる
- Analyzerでのimportのソートが微妙。グループ化が出来ないので、現段階で他のツールに頼るしかないです。なので現段階だと足りないlintのルールだけESLintで補う、みたいになるのでしょうか...?
- 実装されていないformatterやlintのルールを取り入れる方法が現段階で無い(pluginの導入出来るようになって欲しいです)
Biomeは導入が簡単なので、初学者やある程度の設定だけでならアリだと思います。
ですが、個人的にゴリゴリにルールを追加したいプロジェクトではまだ早いと感じました。
Biomeは絶賛開発中のため、これからもっと使いやすくなることに期待大です!
Discussion