❤️

【ESLint alternative】既存のNext.jsプロジェクトにxoを導入する

2022/11/29に公開

フロントエンド開発をしているとフォーマッターはPrettierとESLintを使うのがスタンダードになっていると思います。Next.jsではESLintをデフォルトのlinterとしていますし。今回は、最近知ったxoというlinterを導入していこうと思います。

https://github.com/xojs/xo

なかなか使うのに苦戦し、結果フォーマッターについての理解も深まったのでみなさんの参考にしていただければと思います!

xoとは

xoとは多くのデフォルトルールをもったESLintのラッパーです。インストールするだけで簡単に使えるデフォルトlinterを目指しているようです。

Next.jsに導入する方法

xoを導入する方法は2つあるでしょう。ひとつはESLintにxo configを入れて拡張する方法。もうひとつはESLintを無効にしてxoをインストールする方法です。

Next.jsは(バージョン11以降だったか)ESLintをあらかじめ設定してあります。yarn lintをターミナルで実行するだけでプロンプトがあらわれ設定ファイルがつくられます。xoにはeslintで使えるようにルールをまとめた共有ファイルもあるので、ESLintに簡単に追加できそうです。

ただ今回はxoがうたう"It just work!"というのが本当なのかを検証したいため、後者の方法をとります。xojs/xo: ❤️ JavaScript/TypeScript linter (ESLint wrapper) with great defaultsによると

Never discuss code style on a pull request again! No decision-making. No .eslintrc to manage. It just works!

本当にコーディングスタイルの論争がなくなれば世界は平和になるでしょうし(?)、フォーマッターのセットアップってなにげに面倒くさいですよね。これが解消されるなら大いに利用していきたいです。

xoをインストールして実際に使う

環境

  • M1 MacBook Air 2020
  • macOS Ventura 13.0.1
  • VS Code

準備

なにごとも準備は大事です。今回なかなかに沼ってしまったのですが、原因のひとつはもともとセットアップしていたPrettier, ESLintがxoと競合してしまったことでした。まず、エディタの拡張機能はオフにしておきましょう!VS Codeはワークスペースごとに拡張機能をDisableにすることができるので、Prettier、ESLintをオフにします。

次に、パッケージからもPrettier、ESLintを削除します。

yarn remove prettier eslint eslint-config-next {その他関係するパッケージ}

これでエディタにもパッケージにもフォーマッターがインストールされていない状態になりました。create-next-appで生成される.eslintrc.jsonも削除しておきましょう。

xoをインストール

公式のInstallにしたがって進めていきます。

yarn add -D xo

なお、xo公式ではnpmを推奨しているようです。過去のIssuesをみるとyarnで動作不良がおこることもあるようです... Reactで使用するにはxojs/eslint-config-xo-react: ESLint shareable config for React to be used with eslint-config-xoというパッケージもインストールする必要があります。

yarn add -D eslint-config-xo-react eslint-plugin-react eslint-plugin-react-hooks

npm scriptとextendsも追加しておきましょう。

package.json
{
  ...
  "scripts": {
    "dev": "next dev",
+   "xo": "xo --fix",
    "build": "next build",
    "start": "next start",
    "lint": "next lint"
  },
  "xo": {
+   "extends": ["xo-react"]
    }
  ...
}

これでyarn run xoあるいはVS Codeで"Run Task" > "npm: xo"と実行することができるようになりました。

Next.js対応

さらにNext.jsのconfigも入れていきます。

yarn add -D @next/eslint-plugin-next

xoの設定に追加します。

package.json
{
  ...
  "xo": {
-   "extends": ["xo-react"]
+   "extends": [
+     "plugin:@next/next/core-web-vitals",
+     "xo-react"
+   ]
    }
  ...
}

これでNext.jsのESLintルールが適用されるようになりました。

おすすめ設定

「xoさえ入れればなにも心配いらないぜ Yeah!」というノリがみえるのですが、どうもNext.jsの都合上「NO Config」とはいきませんでした。

package.json
{
  "xo": {
    "ignores": [
      "next-env.d.ts",
      "next.config.js"
    ],
  }
}

create-next-appで生成するファイルがxoのポリシーに触れてしまうようです。next-env.d.tsは型情報を読みこむファイルですが、"three slash"という普段つかわないtypescriptの文法をつかっており、xoに注意されます。このファイルはいじらない方がいいのでignoresに追加。config関係のファイルはignoresに追加した方がいいですね。

package.json
{
  "xo": {
    "rules": {
+     "react/react-in-jsx-scope": "off",
+     "n/prefer-global/process": [
+       "error",
+       "always"
+     ]
    }
  }
}

Next.jsは先ほどのnext-env.d.tsのおかげでReactをグローバルに使えます。わざわざimport React from 'react'と書かなくてもいいということですね。しかしこれもxoには注意されるので、"react/react-in-jsx-scope"ルールを追加。

おなじように、processはNext.jsのどこでも使えますが、require(process)しろ!と怒られるので、"n/prefer-global/process"で無効にします。

最後に

ESLintのルールはバリエーションが多くて、xoのようなものが広まるといいのかもしれません。現状では少し重いかなとか、Prettierとの連携がよくわからないとか不満点はありますが、これからもウォッチしていきたいと思います。

参考文献

Discussion