[React] アプリのビルド時にBrowserslistの更新を要求されるので対処してみる

2021.09.12

こんにちは、CX事業本部 IoT事業部の若槻です。

今回は、Reactアプリケーションのビルド時にBrowserslistの更新を要求されるので対処してみました。

ビルド時にBrowserslistの更新を要求される

本日(2021/09/12)より一ヶ月ほど前(2021/08/13)にcreate-react-appして作成したReactアプリケーションがあります。

このアプリケーションでデバッグを行うためにローカルでビルドや起動を行う際に、いつの日からか次のようなメッセージが表示されるようになりました。

Browserslist: caniuse-lite is outdated. Please run the following command: npx browserslist --update-db

  • ビルド時
$ npm run build

> react-app@0.1.0 build
> react-scripts build

Creating an optimized production build...
Browserslist: caniuse-lite is outdated. Please run the following command: `npx browserslist --update-db`
  • 起動時
$ npm run start

Starting the development server...

Browserslist: caniuse-lite is outdated. Please run the following command: `npx browserslist --update-db`

アプリケーションの動作には特に影響が無いため放置していたのですが、気になってはいたため、一体このメッセージは何なのか調べつつ対処してみることにしました。

調査

Browserslistとは

まずBrowserslistとは何か?というところから。

Browserslistを使用すると、異なるフロントエンドツール間でターゲットブラウザとNode.jsバージョンを共有することができます。

対象のツールは下記となります。

  • Autoprefixer
  • Babel
  • postcss-preset-env
  • eslint-plugin-compat
  • stylelint-no-unsupported-browser-features
  • postcss-normalize
  • obsolete-webpack-plugin

package.jsonまたは.browserslistrcに設定を追加することにより、これらのツールはターゲットブラウザを自動的に検出可能となります。

Reactの場合は、create-react-app実行時にpackage.jsonに既定で以下の設定が追加されます。

package.json

{
  "browserslist": {
    "production": [
      ">0.2%",
      "not dead",
      "not op_mini all"
    ],
    "development": [
      "last 1 chrome version",
      "last 1 firefox version",
      "last 1 safari version"
    ]
  }
}

上記のようなクエリを使用することにより、ターゲットブラウザのバージョンを動的に指定可能となります。Browserslistは、このクエリの対象としてcaniuse-liteを使用します。

caniuse-liteとは

ではcaniuse-liteとは何か?の前にまずCan I Useについて。

Can I Useとは、HTMLやCSS3などの各ブラウザごとのサポートテーブルを提供するサービスです。

Can I Useのサイトでは、CSSプロパティ名などを指定すればどのブラウザで使えるか(=Can I Use)を確認することができます。

background-colorプロパティの場合。各ブラウザおよびバージョンごとの対応状況が表示されています。緑色サポート可能、赤色が非サポートのバージョンです。主要なプロパティなのでほとんどブラウザ、バージョンでサポートされています。

justify-contentプロパティの場合は、サポート可能なバージョンが限られてきます。IEに至っては最新の11でも不可です。

このCan I Useのデータベースのうち重要な部分のみを軽量な形式でまとめたデータセットがcaniuse-liteとなります。

対処

ここまでの調査を踏まえて再度メッセージを見返してみます。

Browserslist: caniuse-lite is outdated. Please run the following command: npx browserslist --update-db

要は、package.jsonに記載のクエリを使用してBrowserslistによりクエリが行われるが、そのクエリ対象のcaniuse-liteがoutdated(=期限切れ)となっているため、npx browserslist --update-dbを実行してcaniuse-liteを更新し、アプリケーションのビルド時にターゲットブラウザを最新バージョンとすることを促すメッセージである、ということが分かりますね。

おそらく、前述のフロントエンドツール間で共有されるターゲットブラウザが最新であることにより、古いバージョンのブラウザへの後方互換を排除できるようになり、アプリケーションのビルドが最適化されるのだと思います。

caniuse-liteを更新する

更新前のcaniuse-liteのバージョンです。1.0.300012511.0.30001035が混在していますね。

$ npm list caniuse-lite
react-app@0.1.0 /Users/wakatsuki.ryuta/projects/cm-rwakatsuki/react-app
└─┬ react-scripts@4.0.3
  ├─┬ @svgr/webpack@5.5.0
  │ ├─┬ @babel/core@7.15.0
  │ │ └─┬ @babel/helper-compilation-targets@7.15.0
  │ │   └─┬ browserslist@4.16.7
  │ │     └── caniuse-lite@1.0.30001251
  │ └─┬ @babel/preset-env@7.15.0
  │   └─┬ core-js-compat@3.16.1
  │     └─┬ browserslist@4.16.7
  │       └── caniuse-lite@1.0.30001251
  ├─┬ optimize-css-assets-webpack-plugin@5.0.4
  │ └─┬ cssnano@4.1.10
  │   └─┬ cssnano-preset-default@4.0.7
  │     └─┬ postcss-merge-rules@4.0.3
  │       └─┬ caniuse-api@3.0.0
  │         └── caniuse-lite@1.0.30001035 deduped
  ├─┬ postcss-normalize@8.0.1
  │ └─┬ browserslist@4.10.0
  │   └── caniuse-lite@1.0.30001035 deduped
  ├─┬ postcss-preset-env@6.7.0
  │ ├─┬ autoprefixer@9.7.4
  │ │ └── caniuse-lite@1.0.30001035 deduped
  │ └── caniuse-lite@1.0.30001035
  └─┬ react-dev-utils@11.0.4
    └─┬ browserslist@4.14.2
      └── caniuse-lite@1.0.30001251

更新前のbrowserslistのクエリ結果です。

$ npx browserslist
and_chr 92
and_ff 90
and_uc 12.12
android 4.4.3-4.4.4
chrome 92
chrome 91
chrome 90
chrome 89
chrome 87
chrome 85
edge 92
edge 91
firefox 90
firefox 89
ie 11
ios_saf 14.5-14.7
ios_saf 14.0-14.4
ios_saf 13.4-13.7
opera 77
safari 14.1
safari 14
safari 13.1
samsung 14.0
samsung 13.0

念のため、browserslistのバージョン。

$ npx browserslist --version
browserslist 4.16.7

npx browserslist --update-dbを実行してcaniuse-liteを更新します。

$ npx browserslist --update-db
Latest version:     1.0.30001256
Installed versions: 1.0.30001035, 1.0.30001251
Removing old caniuse-lite from lock file
Installing new caniuse-lite version
$ npm install caniuse-lite
npm WARN EBADENGINE Unsupported engine {
npm WARN EBADENGINE   package: '@jest/types@27.0.6',
npm WARN EBADENGINE   required: { node: '^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0' },
npm WARN EBADENGINE   current: { node: 'v14.5.0', npm: '7.21.1' }
npm WARN EBADENGINE }
npm WARN EBADENGINE Unsupported engine {
npm WARN EBADENGINE   package: 'diff-sequences@27.0.6',
npm WARN EBADENGINE   required: { node: '^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0' },
npm WARN EBADENGINE   current: { node: 'v14.5.0', npm: '7.21.1' }
npm WARN EBADENGINE }
npm WARN EBADENGINE Unsupported engine {
npm WARN EBADENGINE   package: 'jest-diff@27.0.6',
npm WARN EBADENGINE   required: { node: '^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0' },
npm WARN EBADENGINE   current: { node: 'v14.5.0', npm: '7.21.1' }
npm WARN EBADENGINE }
npm WARN EBADENGINE Unsupported engine {
npm WARN EBADENGINE   package: 'jest-get-type@27.0.6',
npm WARN EBADENGINE   required: { node: '^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0' },
npm WARN EBADENGINE   current: { node: 'v14.5.0', npm: '7.21.1' }
npm WARN EBADENGINE }
npm WARN EBADENGINE Unsupported engine {
npm WARN EBADENGINE   package: 'pretty-format@27.0.6',
npm WARN EBADENGINE   required: { node: '^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0' },
npm WARN EBADENGINE   current: { node: 'v14.5.0', npm: '7.21.1' }
npm WARN EBADENGINE }
Cleaning package.json dependencies from caniuse-lite
$ npm uninstall caniuse-lite
npm WARN EBADENGINE Unsupported engine {
npm WARN EBADENGINE   package: '@jest/types@27.0.6',
npm WARN EBADENGINE   required: { node: '^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0' },
npm WARN EBADENGINE   current: { node: 'v14.5.0', npm: '7.21.1' }
npm WARN EBADENGINE }
npm WARN EBADENGINE Unsupported engine {
npm WARN EBADENGINE   package: 'diff-sequences@27.0.6',
npm WARN EBADENGINE   required: { node: '^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0' },
npm WARN EBADENGINE   current: { node: 'v14.5.0', npm: '7.21.1' }
npm WARN EBADENGINE }
npm WARN EBADENGINE Unsupported engine {
npm WARN EBADENGINE   package: 'jest-diff@27.0.6',
npm WARN EBADENGINE   required: { node: '^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0' },
npm WARN EBADENGINE   current: { node: 'v14.5.0', npm: '7.21.1' }
npm WARN EBADENGINE }
npm WARN EBADENGINE Unsupported engine {
npm WARN EBADENGINE   package: 'jest-get-type@27.0.6',
npm WARN EBADENGINE   required: { node: '^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0' },
npm WARN EBADENGINE   current: { node: 'v14.5.0', npm: '7.21.1' }
npm WARN EBADENGINE }
npm WARN EBADENGINE Unsupported engine {
npm WARN EBADENGINE   package: 'pretty-format@27.0.6',
npm WARN EBADENGINE   required: { node: '^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0' },
npm WARN EBADENGINE   current: { node: 'v14.5.0', npm: '7.21.1' }
npm WARN EBADENGINE }
caniuse-lite has been successfully updated

Target browser changes:
- and_chr 92
+ and_chr 93
- and_ff 90
+ and_ff 92
- chrome 89
- edge 91
- firefox 89
+ firefox 91
+ opera 78
- samsung 13.0

更新コマンド実行結果の末尾がターゲットブラウザの変更結果です。低いバージョンが削除され、最新のバージョンが追加されています。

更新後のcaniuse-liteのバージョンです。更新後は1.0.30001256に統一されていますね。

$ npm list caniuse-lite
react-app@0.1.0 /Users/wakatsuki.ryuta/projects/cm-rwakatsuki/react-app
└─┬ react-scripts@4.0.3
  ├─┬ @svgr/webpack@5.5.0
  │ ├─┬ @babel/core@7.15.0
  │ │ └─┬ @babel/helper-compilation-targets@7.15.0
  │ │   └─┬ browserslist@4.16.7
  │ │     └── caniuse-lite@1.0.30001256 deduped
  │ └─┬ @babel/preset-env@7.15.0
  │   └─┬ core-js-compat@3.16.1
  │     └─┬ browserslist@4.16.7
  │       └── caniuse-lite@1.0.30001256 deduped
  ├─┬ optimize-css-assets-webpack-plugin@5.0.4
  │ └─┬ cssnano@4.1.10
  │   └─┬ cssnano-preset-default@4.0.7
  │     └─┬ postcss-merge-rules@4.0.3
  │       └─┬ caniuse-api@3.0.0
  │         └── caniuse-lite@1.0.30001256 deduped
  ├─┬ postcss-normalize@8.0.1
  │ └─┬ browserslist@4.10.0
  │   └── caniuse-lite@1.0.30001256 deduped
  ├─┬ postcss-preset-env@6.7.0
  │ ├─┬ autoprefixer@9.7.4
  │ │ └── caniuse-lite@1.0.30001256 deduped
  │ └── caniuse-lite@1.0.30001256
  └─┬ react-dev-utils@11.0.4
    └─┬ browserslist@4.14.2
      └── caniuse-lite@1.0.30001256 deduped

更新後のbrowserslistのクエリ結果です。

$ npx browserslist
and_chr 93
and_ff 92
and_uc 12.12
android 4.4.3-4.4.4
chrome 92
chrome 91
chrome 90
chrome 87
chrome 85
edge 92
firefox 91
firefox 90
ie 11
ios_saf 14.5-14.7
ios_saf 14.0-14.4
ios_saf 13.4-13.7
opera 78
opera 77
safari 14.1
safari 14
safari 13.1
samsung 14.0

動作確認

caniuse-liteの更新後は、Reactアプリケーションのビルド時も起動時も更新前に出ていたメッセージは表示されなくなりました。

 $ npm run build

> react-app@0.1.0 build
> react-scripts build

Creating an optimized production build...
Compiled successfully.
$ npm run start

Compiled successfully!

You can now view react-app in the browser.

おわりに

Reactアプリケーションのビルド時にBrowserslistの更新を要求されるので対処してみました。

アプリケーションのCI/CDを行う際にCircle CIやGitHub Actionsなどの環境を使うのであれば、都度npm installされるのでcaniuse-liteもセマンティックバージョニングの範囲内で常に最新のものが使われるので問題にはならないと思います。ローカルでデバッグする際に今回のメッセージが気になったタイミングで都度コマンドを実行してアップデートする対処方針で良いのではないでしょうか。

参考

以上