LoginSignup
0

JavaScriptのブラウザ互換性をESLintでチェックする

Last updated at Posted at 2023-10-15

Webサイト制作でトランスパイル環境のない生のJavaScriptを書く機会があり、そこそこ古いバージョンのブラウザでも動くようにLintでコードチェックできたらなーと思って調べてみました。導入手順とかんたんな使い方を紹介します。

環境

  • Node.js v20
  • VS Code v1.82

TL;DR

国内シェア1%以上、かつES6サポートのブラウザをターゲットとした例:

package.json
{
  "scripts": {
    "lint": "eslint .; exit 0"
  },
  "devDependencies": {
    "eslint": "^8.51.0",
    "eslint-plugin-compat": "^4.2.0"
  },
  "browserslist": [
    ">= 1% in JP and not dead"
  ]
}
.eslintrc.js
module.exports = {
  env: {
    browser: true,
  },
  extends: ["eslint:recommended", "plugin:compat/recommended"],
  overrides: [
    {
      env: {
        node: true,
      },
      files: [".eslintrc.{js,cjs}"],
      parserOptions: {
        sourceType: "script",
      },
    },
  ],
  parserOptions: {
    ecmaVersion: 6,
    sourceType: "module",
  },
  rules: {},
  plugins: ["compat"],
  settings: {
    polyfills: [],
  },
};

セットアップ

package.jsonを作成します。

npm init -y

ESLintをセットアップします。

npm init @eslint/config

✔ How would you like to use ESLint? · problems
✔ What type of modules does your project use? · esm
✔ Which framework does your project use? · none
✔ Does your project use TypeScript? · No / Yes
✔ Where does your code run? · browser
✔ What format do you want your config file to be in? · JavaScript
Local ESLint installation not found.
The config that you've selected requires the following dependencies:

eslint@latest
✔ Would you like to install them now? · No / Yes
✔ Which package manager do you want to use? · npm

ESLintのプラグインをインストールします。

npm install -D eslint-plugin-compat

CLIでかんたんにLintが呼び出せるようにスクリプトを追加しておきましょう。

package.json
"scripts": {
  "lint": "eslint .; exit 0"
}

VS Codeエクステンションの追加もオススメします。コードを書くとリアルタイムでチェックが実行されます。

ターゲットを決める

すでに公開済みのサイトであれば、Googleアナリティクスなどを参考にアクセスの多いブラウザやバージョンの目処をつけておきます。

これから公開するサイトであれば、主要なブラウザの最新5バージョンなど制作者サイドでルールを決めるのも良いでしょう。

以降、サイトの訪問を意図したブラウザおよびバージョンを「ターゲット」と記載します。

APIのチェック

Browserslistのサイトで、ターゲットに該当するブラウザとバージョンを確認してみましょう。

最新5バージョンをターゲットとした例:

last 5 versions and not dead

特定のブラウザをターゲットとした例:

Chrome >= 116 or FireFox >= 115

not dead は過去1年間にアップデートされたブラウザのみ対象とします。これを指定しておくと、サポート終了してもなお使われ続けているブラウザを除外できます。

コードベース上のターゲット指定はpackage.jsonで行います。
ここではシェア1%以上をターゲットとしました。

package.json
"browserslist": [
  ">= 1% and not dead"
]

ESLintプラグイン「eslint-plugin-compat」を有効化します。
このプラグインはターゲット指定を読み込んでサポートしていないAPIをエラーとして検出します。

.eslintrc.js
extends: [
  "eslint:recommended",
  "plugin:compat/recommended"
],
plugins: ["compat"],

任意のファイルを作成して、試しにfetchAPIを使ってみましょう。
VSCodeエクステンションによりリアルタイムでエラーが検出されます。

CLIでは以下のようにエラーが検出されます。

記事執筆時点のシェア1%にはOperaモバイル版の「Opera Mini」が含まれ、これがfetchAPIをサポートしていません。 in JP を追加して国内シェアに絞り込んでみましょう。

package.json
"browserslist": [
  ">= 1% in JP and not dead"
]

Opera Miniは国内シェアが低いためターゲットから外れ、エラーは検出されなくなりました。

サイトのターゲットとするべきブラウザやバージョン、それらがサポートするAPI群を記憶しておくことは、人間にとってとんでもなく困難です。Lintでチェックできるなんて最高に便利ですね!

ここでひとつ注意事項があります。
「eslint-plugin-compat」はグローバルに存在するAPI(URLSearchParamsオブジェクトや、fetch関数など)をチェックしてくれますが 言語構文(letやスプレッド構文など)についてはチェックしない ようです。理由についてissueの中で「トランスパイルできるものは対応の優先度が低いから」と述べられています。
https://github.com/amilajack/eslint-plugin-compat/issues/454

試しにオプショナルチェーンを使ってみても、エラーは何も検出されません。

言語構文のチェック

言語構文についてはESLintの設定の中でECMAScriptレベルの指定ができます。browserslistの指定とはリンクしませんが、これだけでも大きな助けとなります。

デフォルトの設定は比較的新しいものになっているので、ES6レベルに下げてみましょう。

.eslintrc.js
  env: {
    browser: true,
  },
  ...
  parserOptions: {
    ecmaVersion: 6,
    ...
  },

オプショナルチェーンはES2020で導入された構文です。ES6では解釈できずパースエラーとして検出されるようになりました。

CLIでも同じエラーが検出されます。

おまけ

eslint-plugin-compatに付随してインストールされる「browserslist」コマンドを叩くと、ターゲットのブラウザとバージョンがリスト表示されます。User Agent Client Hintsと組み合わせてサイト訪問者にブラウザアップデートの補足を表示するなど活用できそうですね。

./node_modules/.bin/browserslist

> and_chr 117
> chrome 117
> chrome 116
> edge 117
> edge 116
> firefox 117
> ios_saf 17.0
> ios_saf 16.6
> safari 16.6

おわりに

思い出せばAPIをひとつずつ Can I use で調べながらコードを書いていた時代もありましたが、機械的なチェックが格段に進化を遂げていて衝撃的でした。ESLintやプラグイン開発者の方々に感謝です!

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0