20251103

Biome

https://biomejs.dev/

JavaScript、TypeScript用のリンター + フォーマッター。

Rustで作られているためESLint+Prettierより速いらしい。

インストール

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

マイナーバージョンの更新でも挙動が変わる可能性があるらしいので --save-exact をつける。

設定

biome.json または biome.jsonc で設定する。以下コマンドで自動生成可能。

npx @biomejs/biome init

リント

npx biome lint

フォーマット

npx biome format --write

--write オプションをつけてファイルの修正を許可。

リント + フォーマット

check コマンドを使うと両方実行される。

npx biome check --write

ESLintとの互換性

互換性はないがマイグレーションツールはある。

https://biomejs.dev/ja/guides/migrate-eslint-prettier/

使用しているプラグインなども読み込んで最終的に一つの biome.json を作成する感じ?

  ℹ 42% (48/113) of the rules have been migrated.
  
  ℹ Migrated rules:
  
  - constructor-super
  - getter-return
  - no-array-constructor
  - no-class-assign
  - no-const-assign
  - no-dupe-args
  - no-dupe-class-members
  - no-dupe-keys
  - no-func-assign
  - no-import-assign
  - no-new-native-nonconstructor
  - no-obj-calls
  - no-redeclare
  - no-setter-return
  - no-this-before-super
  - no-undef
  - no-unreachable
  - no-unsafe-negation
  - no-unused-vars
  - no-var
  - no-with
  - prefer-const
  - prefer-rest-params
  - @typescript-eslint/no-array-constructor
  - @typescript-eslint/no-explicit-any
  - @typescript-eslint/no-extra-non-null-assertion
  - @typescript-eslint/no-misused-new
  - @typescript-eslint/no-namespace
  - @typescript-eslint/no-non-null-asserted-optional-chain
  - @typescript-eslint/no-require-imports
  - @typescript-eslint/no-unnecessary-type-constraint
  - @typescript-eslint/no-unsafe-declaration-merging
  - @typescript-eslint/no-unused-vars
  - @typescript-eslint/prefer-as-const
  - @typescript-eslint/prefer-namespace-keyword
  - jsx-a11y/alt-text
  - jsx-a11y/aria-props
  - jsx-a11y/aria-proptypes
  - jsx-a11y/aria-unsupported-elements
  - jsx-a11y/role-has-required-aria-props
  - jsx-a11y/role-supports-aria-props
  - react/jsx-key
  - react/jsx-no-comment-textnodes
  - react/jsx-no-duplicate-props
  - react/no-children-prop
  - react/no-danger-with-children
  - react-hooks/exhaustive-deps
  - react-hooks/rules-of-hooks
  
  ℹ Rules that can be migrated to an inspired rule using --include-inspired:
  
  - @typescript-eslint/ban-ts-comment
  - @typescript-eslint/no-this-alias
  - react/jsx-no-target-blank
  
  ℹ Rules that can be migrated to a nursery rule using --include-nursery:
  
  - no-unused-expressions
  
  ℹ Unsupported rules:
  
  - no-new-symbol
  - prefer-spread
  - @next/next/google-font-display
  - @next/next/google-font-preconnect
  - @next/next/inline-script-id
  - @next/next/next-script-for-ga
  - @next/next/no-assign-module-variable
  - @next/next/no-async-client-component
  - @next/next/no-before-interactive-script-outside-document
  - @next/next/no-css-tags
  - @next/next/no-document-import-in-page
  - @next/next/no-duplicate-head
  - @next/next/no-head-element
  - @next/next/no-head-import-in-document
  - @next/next/no-html-link-for-pages
  - @next/next/no-img-element
  - @next/next/no-page-custom-font
  - @next/next/no-script-component-in-head
  - @next/next/no-styled-jsx-in-document
  - @next/next/no-sync-scripts
  - @next/next/no-title-in-document-head
  - @next/next/no-typos
  - @next/next/no-unwanted-polyfillio
  - @typescript-eslint/no-duplicate-enum-values
  - @typescript-eslint/no-empty-object-type
  - @typescript-eslint/no-unsafe-function-type
  - @typescript-eslint/no-unused-expressions
  - @typescript-eslint/no-wrapper-object-types
  - @typescript-eslint/triple-slash-reference
  - import/no-anonymous-default-export
  - react/display-name
  - react/jsx-no-undef
  - react/jsx-uses-react
  - react/jsx-uses-vars
  - react/no-deprecated
  - react/no-direct-mutation-state
  - react/no-find-dom-node
  - react/no-is-mounted
  - react/no-render-return-value
  - react/no-string-refs
  - react/no-unescaped-entities
  - react/no-unknown-property
  - react/no-unsafe
  - react/prop-types
  - react/react-in-jsx-scope
  - react/require-render-return
  - react-hooks/component-hook-factories
  - react-hooks/config
  - react-hooks/error-boundaries
  - react-hooks/gating
  - react-hooks/globals
  - react-hooks/immutability
  - react-hooks/incompatible-library
  - react-hooks/preserve-manual-memoization
  - react-hooks/purity
  - react-hooks/refs
  - react-hooks/set-state-in-effect
  - react-hooks/set-state-in-render
  - react-hooks/static-components
  - react-hooks/unsupported-syntax
  - react-hooks/use-memo

試しにNext.jsのデフォルトのESLint設定からマイグレーションしてみた結果。

40%ほどはマイグレーションできたみたい。React環境で使えるのはまだ先かも。フォーマッターとしてだけ使うのはアリ?

Next.jsの初期設定時にリンターとしてBiomeを指定すると以下の biome.json が生成される。

{
  "$schema": "<https://biomejs.dev/schemas/2.2.0/schema.json>",
  "vcs": {
    "enabled": true,
    "clientKind": "git",
    "useIgnoreFile": true
  },
  "files": {
    "ignoreUnknown": true,
    "includes": ["**", "!node_modules", "!.next", "!dist", "!build"]
  },
  "formatter": {
    "enabled": true,
    "indentStyle": "space",
    "indentWidth": 2
  },
  "linter": {
    "enabled": true,
    "rules": {
      "recommended": true,
      "suspicious": {
        "noUnknownAtRules": "off"
      }
    },
    "domains": {
      "next": "recommended",
      "react": "recommended"
    }
  },
  "assist": {
    "actions": {
      "source": {
        "organizeImports": "on"
      }
    }
  }
}

domainnextreact を指定すればいいっぽい。いずれにせよ含まれるルールはESLintに比べて少ない模様。

https://biomejs.dev/linter/domains/

GritQLというものを使えば独自にルールを追加できる?

https://biomejs.dev/reference/gritql/

Oxlint

https://oxc.rs/docs/guide/usage/linter.html

JavaScript、TypeScriptのリンター。

ESLintとの互換性をモットーとしている。

フォーマッターは無いがBiomeよりさらに速いらしい。

 npm install --save-dev oxlint

ESLintからのマイグレーション

Next.jsのプロジェクトをマイグレーションしてみる。

npx @oxlint/migrate
unsupported rule: react/display-name
unsupported rule: react/jsx-uses-react
unsupported rule: react/jsx-uses-vars
unsupported rule: react/no-deprecated
unsupported rule, but in development: react/require-render-return
unsupported rule: react-hooks/static-components
unsupported rule: react-hooks/use-memo
unsupported rule: react-hooks/component-hook-factories
unsupported rule: react-hooks/preserve-manual-memoization
unsupported rule: react-hooks/incompatible-library
unsupported rule: react-hooks/immutability
unsupported rule: react-hooks/globals
unsupported rule: react-hooks/refs
unsupported rule: react-hooks/set-state-in-effect
unsupported rule: react-hooks/error-boundaries
unsupported rule: react-hooks/purity
unsupported rule: react-hooks/set-state-in-render
unsupported rule: react-hooks/unsupported-syntax
unsupported rule: react-hooks/config
unsupported rule: react-hooks/gating
unsupported rule: jsx-a11y/aria-proptypes
special parser detected: eslint-config-next/parser
unsupported rule, but in development: constructor-super
unsupported rule, but in development: getter-return
unsupported rule, but in development: no-undef
unsupported rule, but in development: no-unreachable
unsupported rule: prefer-const

いくつかのルールはマイグレーションできなかったがNext.js系のものは全てマイグレーションできてるっぽい?

ESLint用のルールが自動的に使えるようになるわけではなく、おそらく個別でOxlint用に実装している、、、

https://github.com/oxc-project/oxc/issues/1022

https://github.com/oxc-project/oxc/issues/1929

すごすぎ。