目次
ESLintの公式ロゴ。引用元https://eslint.org/docs/about/
静的解析、いわゆるLintと呼ばれるツールを使用されたことはあるでしょうか?
設定に基づきソースコードを解析して、チームのコーディング規約から外れた記述があれば、警告やエラーを出力してくれ、場合によっては自動的に修正もしてくれる頼れるツールです。
言語により様々なLintが開発・提供されているのですが、それらを使用する際このような疑問・課題を感じたことは無いでしょうか?
- 初めてこの言語を使用するのだが、この言語の一般的なコーディングスタイルはどんなのだろう?
- とりあえずデフォルトのLintの設定を使っているがどうにもチェックが厳しすぎる。設定を変えたいのだが、この設定を変えることでバグを見逃したりしないだろうか。
一つの言語でも様々なコーディング規約が提案されており、特に初めての言語を使用するときなど、どのコーディング規約に沿って良いのか判断が難しい場合があるかと思います。
そこで、有名なOSSで使用されているLintの設定を調査して、どのような設定やコーディング規約が使われているのか見てみましょう。
JavaScriptでよく使われているLintであるESLintを対象として、JavaScriptを使用しているOSSで使用されているコーディング規約を見ていきたいと思います。
今回はReactに焦点を当てて使用されているESLintのルールを見ていきます。
ESLintの概要と特徴
ESLintはJavaScriptのための静的解析ツールです。
ESLintは特定のコーディング規約に依存せず、個別のコーディング規約はユーザーは自由に有効無効が設定可能です。
このように、カスタマイズ性が非常に高いのが特徴です。
豊富なデフォルトで定義されているルールと呼ばれるコーディング規約や、ユーザー独自で定義できるルールを駆使して、柔軟にコーディング規約を設定することができます。
また、サードパーティなどが公開している「Google JavaScript Style Guide」や「Airbnb JavaScript Style Guide」等、有名なコーディング規約も設定一つで再利用が可能です。
さらに、それらのコーディング規約に従いつつも、特定のルールを特定のファイルのみ有効/無効にする、などと言った設定も簡単に行うことができます。
全くどのような設定にすればわからないという場合は、最初にESLint公式が提供しているGetting Startedを参考にして設定すると、ESLintが推奨するコーディング規約を設定することできます。
ESLintのルールの見方
ESLintのコーディングルールの設定は非常に簡単です。
簡単な例として、ステートメントの末尾にセミコロンを付けるというルールを設定するconfigを定義してみましょう。
{ "rules": { "semi": [2, "always"] } }
個別のコーディングルールは、設定ファイル内のrules
内で定義することが可能です。
今回の場合はsemi
と呼ばれるルールを設定しており、ESLintがデフォルトで提供しています。
ESLintでは2をERROR, 1をWARN, 0をルールのOFFと定義されています。
今回の例の場合は、ステートメントにセミコロンがついていないとlint実行時にERRORになるように設定しています。
また、ESLintは他にも大量のコーディングルール群を提供しており、それらを利用してルールのカスタマイズをする事ができます。
サードパーティが提供している設定の利用
有名なコーディング規約は、既にパッケージとして提供されている場合あります。
例えば、先述したGoogle JavaScript style guideのルールを適用したい場合は、npmに公開されているeslint-config-googleというパッケージをインストールすることで使用できます。
{ "extends": "google", }
と記述すること、でユーザーは、一から設定せずともGoogle JavaScript style guideのコーディング規約の設定を利用できます。
このルール群は、ESLint自体のデフォルトで提供されている設定もありますが、上記で紹介したeslint-config-googleように、npm moduleとしてサードパーティが提供しているベース設定を利用することができます。
また自身で開発して外部に公開したり、複数のプロジェクトで使いまわすこともできます。
このルールの設定群はsharable configといいます。
「基本的にGoogle JavaScript style guideに従いたいが、どうしてもステートメントの最後にセミコロンは付けたくない」という場合(Google JavaScript styleはセミコロンをつける設定を推奨しています)は、以下のようにrules
にsemi
の設定をすれば簡単に実現が可能です。
{ "extends": "google", "rules": { // Additional, per-project rules... "semi": [2, "never"] } }
Plugin
ESLintが提供しているデフォルトのルールは、基本的なルールは網羅していますが、JavaScriptが使用できる範囲は非常に広いです。
そのため、デフォルトのルールの中には、自分が使用したいルールが存在しない場合があるかもしれません。
そのような場合、ESLintではルール自体を独自に開発することができます。
ESLintは独自のルールを第三者が開発できるようにするため、Pluginという仕組みを提供しています。
npmでeslint-pluing-*
と検索すると、サードパーティーが提供するカスタムプラグインが大量にあるのが確認できます。
もし、ESLintが提供しているデフォルトのルールの中に、使用したいルールが存在しない場合プラグインの方も見てみると良いでしょう。
使い方もsharable configと同様に簡単に設定できます。
例えばReactのコードを静的解析をしたい場合、eslint-plugin-reactというプラグインをインストールし、下記のように設定することでReact独自の構文の静的解析をすることができます。
{ "extends": "google", "plugins": [ "react" ], "rules": { "semi": [2, "never"], "react/display-name": 2 } }
上記のルールを設定することで、React component内でdisplayNameという変数の宣言忘れを防ぐ事ができます。
このようにESLintは、一つ一つのルールについても簡単に設定・再利用することが可能です。
ここまで、ESLintはカスタマイズ性が非常に高く、様々な設定が可能であることを説明しました。
しかし、ユーザーとして気になるのはどんなルールを適用すればよいかいうことではないでしょうか。
「うちのプロダクトではこんなコーディング規約で開発しているけど他のプロジェクトではどんな規約を使ってるのだろう?」などの疑問を感じたことはありませんか?
タイトルにあるように今回の記事では、有名なフロントエンドフレームワークの一つであるReactで使用している静的解析ルールを調査して、どのようなコーディング規約を設定しているのか見ていきましょう。
React
概要
ReactとはFacebook社が主導で開発を行っているフロントエンドライブラリです。
公式のドキュメントにはReactのキーワードとして以下の3つのキーワードが紹介されています。
Declarative (宣言的)
宣言的プログラミングが可能。
Component-Based (コンポーネントベース)
コンポーネントの考え方により複雑なUIの構成を簡単に実現可能。
Learn Once, Write Anywhere(一度学べば、どこでも書くことができる)
Reactで使用した技術はWebフロントエンドだけでなく、React Nativeのようなモバイルアプリにも使用可能。
という特徴があります。
ESLint in React
React内で定義されている、大枠のeslintの設定ファイルはこちらになります。
fbjs
上記設定ファイルの初めの方を見てましょう。
fbjsをextendsしていることがわかります。
module.exports = { extends: 'fbjs', }
Reactでは、eslint-config-fbjsというsharble configをベースルールとして使用しています。
fbjsは、Facebook社が内部的に使用していたESLintの設定をsharable configとしてまとめたものです。
その特徴として
- project毎に特殊なケースを設定しない
- Facebook独自のルールは設定しない
とあります。
ですが、実は二番目の特徴については、Facebookの内部の設定のためにいくつか独自のルールが設定されています。
ここに設定されているextendConfigによって、若干Facebook用の設定がされているようです。
Plugin in fbjs
次にfbjs自体に設定されているルールを見ていきましょう。
fbjsのESLintの設定ファイルでは、下記のように使用するプラグインが指定されています。
plugins: [ 'babel', 'flowtype', 'jsx-a11y', 'react', 'relay', ],
それぞれについて簡単に解説します。
- babel
- eslint-plugin-babelはBabelのためのルールセットです。
Babelは、ECMAScript2015/2016/2017やflowtypeで書かれたコードを、一般的なブラウザがサポートしている形式のJavaScriptに出力することができるトランスパイラです。
- eslint-plugin-babelはBabelのためのルールセットです。
- flowtype
- flowtype-pluginは、ESLintでFlowの静的解析をするためのプラグインです。
FlowはJavaScriptで静的型付けを可能にするツールです。静的型付けのチェックはFlow側に任して、ESLintではすべてのjsファイルに対して、
@flow
アノテーションがつき、Flowで型をチェックをしているかをチェックしています。 - jsx-a11y
- jsx-a11yは、react-a11yというReactの潜在的なアクセシビリティの問題についてのルールが定義されているプラグインです。
- react
- reactのためのルールが定義されています。
- relay
- relay-pluginは、RelayとよばれるJavaScriptフレームワークを静的解析するためのプラグインです。
さて、この唐突に出てきたfbjsというリポジトリですが、Facebook社開発のプロダクトチームが素早く、安心してコードを書くためのFacebook社のためのライブラリ、モジュールという位置づけのようです。
ESLintのshareable config以外にも様々なスクリプトがありますが、本番環境のコードに適用すると、思わぬ問題を引き起こすかもしれませんので注意してください。
また、同リポジトリにおいて、よりモダンなコードベースに対応するためのeslint-config-fbjs-opensourceが開発されており、今後こちらのshareable configをベースとした開発がメインになるかもしれません。
ReactのESLint
上記で説明したfbjsをルールのベースとして、それ以外に記載されたルールがReactの独自のルールになります。
Plugin in React
ReactのESLintの設定ファイルでは更にpluginが追加されています。
plugins: [ 'jest', 'no-for-of-loops', 'react', 'react-internal', ],
それぞれについて簡単に解説します。
- Jest
JestはJavaScriptのためのテストフレームワークです。
もちろんFacebook謹製。
“zero-configuration”を哲学として掲げており、create-react-app
やreact-native init
でプロジェクトを作っていると、既に適切な設定がその時点でされるようになっています。
特にReactやReact Nativeを使用している場合、非常に導入しやすいテストフレームワークです。
このルールは'**/__tests__/**.js'
のファイルパスのみ適用されています。
- no-for-of-loops
no-for-of-loopsはfor (...of)
を抑制するルールです。
- react-internal
npmにプラグインとしてはあげられていませんが、react内で独自に定義されているカスタムプラグインです。
エラーメッセージのフォーマットに関するルールや、Boolean,String, Numberのプリミティブ型のコンストラクタを抑制するルールなどが追加されています。
その他の基本的なルールについて
ここまで、fbjsとReactが使用しているESLintのpluginについて一通り見てきました。
他にも、ESLintが提供しているデフォルトのルールによって、静的解析の設定がされています。
ルールの概要を説明すると下記の様なルールが設定されています。
- インデントの指定なし
- セミコロンをつけることを推奨
- ブロックや関数の後ろ、キーワードの前後にはスペースを入れる
- 比較演算子には
==
や!=
よりも===
や!==
を使用する - ファイル最後は改行で終わる
- 文字列は基本的にシングルクオートだが、JSXの場合はダブルクオートを使用する
- 使用しない変数の宣言は許可しない
一つ一つ解説していきたい所ではあるのですが、なんとその数約140個ものルールが細やかに設定されています。
そのため、今回ざっと特徴だけの説明に留めておきたいと思います。
静的解析の対象となるソースコード
この設定ファイルを元に、Reactでは3ケースに分けて静的解析が実施されています。
eslintrc.esnext.js
ここで、上記で設定したルールの他に、varの使用を許可しないというルールを追加しています。
大部分のファイルが、このルールで静的解析されています。
具体的な適用範囲は、Reactのリポジトリからみて、packages/*/*.js
,packages/*/src/**/*.js
,packages/events/**/*.js
,packages/shared/**/*.js
,scripts/flow/*.js
, scripts/rollup/shims/**/*.js
です。
eslintrc.es5.js
ecmaScript5で開発されたコードは、このルールで静的解析されます。
ルールとして追加されているのは、use strict
を強制している点と、parserがbabelからespreeに変更されている点です。
適用範囲はpackages/*/npm/**/*.js
です。
eslintrc.default.js
ECMAScript2017に対応しているコードに適用させるルールです。
前述したeslintrcに加えて、以下の3点がルールとして追加されています。
- varの使用を許可しない。
- strictを有効にする。
- ECMAScript6から導入されているRest PropertiesとSpread Propertiesのサポートを有効。
また、eslintrc.es5.jsと同様に、parserがbabelからespreeに変更されています。
適用範囲はeslintrc.esnext, eslint.es5.jsが適用されているファイル以外のJavaScriptのコードが対象となっています。
Reactで使用されているESLintの使い方まとめ
以上が現在Reactに設定されているESLintのルールになります。
ここまでの話をまとめると
-
基本的にはFacebook社内で使われていたルールをOSS化した(fbjs)が主。これはfacebookが作っているJSライブラリで広く使われている様子。但し、その他の開発チームが使う事を前提としたものではない。
-
Reactでは、上記に加えて、Jestなどのいくつかのプラグインが使われている。
-
ecmaScriptのバージョンが混在しているが、ちゃんとバージョンごとの静的解析ルールを作成してすべて静的解析を行っている。
無ければ独自でルールを開発したり、使用しているフレームワーク毎にプラグインを開発していたりで非常に多くのルールが設定されていました。
この多岐に渡るルールを自動化することで、JavaScriptのようなインタプリタ型言語による大規模開発において、バグを事前に潰すことに一役買っているのだろうと感じました。
おわりに
SideCIではESLintを用いたJavaScriptプロジェクトのコードレビューに対応しています。
SideCIを利用して、GitHub上でPullRequestと連携した自動レビューをプロジェクトメンバー全体で共通して使うと、コードレビューが非常に便利になります。
是非ご活用ください。