🙂

ReactのソースコードをVSCodeで快適に読む

2023/08/13に公開

背景

ちょっと個人的な興味からReactのソースコードを読みたいと思っていたのですが、案外環境を整えるのが面倒だった&情報が少なかったので簡単に手順をまとめます。

結論

  • 2023年8月現在、ReactのソースコードはFlowという形式で書かれている
  • FlowはVSCodeでそのまま開いてもうまく補完等が効かないケースがある
  • Metaが出している公式のFlow用のVSCodeプラグインを入れると幸せになれる

前提

前提知識をつらつら書きます。手っ取り早く手順だけ知りたい方は「手順」の箇所まで飛ばしてください。

ReactのソースコードはFlowで書かれている

執筆時点において、ReactのソースコードはFlowという型アノテーションで記述されています。

https://flow.org/

筆者はJavaScript自体にそこまで詳しくなくて知らなかったのですが、これはTypeScriptにインスパイヤを受けた、Meta独自のJavaScriptに対する型アノテーションライブラリになっているようです。[1]

下記はReactのソースコードからのそのままの抜粋ですが、パッと見はTypeScriptの構文に結構近しい雰囲気です。

let legacyErrorBoundariesThatAlreadyFailed: Set<mixed> | null = null;

// Only used when enableProfilerNestedUpdateScheduledHook is true;
// to track which root is currently committing layout effects.
let rootCommittingMutationOrLayoutEffects: FiberRoot | null = null;

let rootDoesHavePassiveEffects: boolean = false;
let rootWithPendingPassiveEffects: FiberRoot | null = null;
let pendingPassiveEffectsLanes: Lanes = NoLanes;
let pendingPassiveProfilerEffects: Array<Fiber> = [];
let pendingPassiveEffectsRemainingLanes: Lanes = NoLanes;
let pendingPassiveTransitions: Array<Transition> | null = null;

ReactFiberWorkLoop.js#L564-L575

ところが一方で、TypeScriptにはない構文も存在します。

export type LoggerEvent =
  | {
      +event_name: 'loaded-dev-tools',
    }
  | {
      +event_name: 'error',
      +error_message: string | null,
      +error_stack: string | null,
      +error_component_stack: string | null,
    }
  | {
      +event_name: 'selected-components-tab',
    }
  | {
      +event_name: 'selected-profiler-tab',
    }

Logger.js#L12-L28

field名の先頭に + のシンボルが付いていますが、FlowではこれでfieldがreadOnlyであることをannotateできるようです。
https://flow.org/en/docs/types/interfaces/#toc-interface-property-variance-read-only-and-write-only

VSCodeは、JavaScriptとTypeScriptに対してはビルトインでLanguage Serverを含めてくれていますが、残念ながらFlowに対するLanguage Serverはありません。
従って、ReactのソースコードをそのままVSCodeで読み込むとエラーの嵐になるはずです😇 [2]

Flowに対応したVSCodeプラグイン

Flowで書かれたJavaScriptに対してもインテリセンスを効かせるために、MetaがVSCode向けのFlowプラグインを提供してくれています。

https://marketplace.visualstudio.com/items?itemName=flowtype.flow-for-vscode

ありがたくこれを使わせてもらいましょう。

手順

具体的な手順です。

1. ReactのリポジトリをClone

https://github.com/facebook/react

reactのリポジトリをローカルに落とします。事故らないようにforkしておくといいと思います。

2. 依存をinstall

cloneしたら依存をinstallします。
reactのリポジトリの場合はpackage.jsonにflowの設定スクリプトを用意してくれているので、これを叩きます。

$ yarn install

# flowの設定
$ yarn run flow dom-node

上記手順後に node_modules/.bin/flow が生成されますが、plugin側がこれを使います。

3. VSCode側の設定

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

https://marketplace.visualstudio.com/items?itemName=flowtype.flow-for-vscode

インストール後に、settings.jsonに次のような設定を追加。(その他の細かい設定はこの辺りを参照)

{
    "flow.pathToFlow": "${workspaceFolder}/node_modules/.bin/flow",
    "flow.useNPMPackagedFlow": true,
    "javascript.validate.enable": false
}

"javascript.validate.enable": false を追加しないと、VSCodeが普通のJavaScriptに対して出力するアラートを出力してしまうので必要です。[3]

4. 動作確認

上記手順でFlowのコードに対してもコードジャンプ等のエディタの機能が効くはずです!

まとめ

今後もReactがFlowで管理され続ける限りは、コードを快適に読むには上記の手順を踏む必要がありそうです。
個人的にはReactもTypeScriptを使用してくれた方がありがたい気もするのですが、Meta的になにか事情があるのでしょうか。似たような議論が下記のスレッドでも展開されていたので、気になる人はこの辺の話を追ってみても面白いかもしれません。

https://www.reddit.com/r/reactjs/comments/w4vgpj/will_facebook_ever_supportprovide_typescript_for/

脚注
  1. こちらのスレッドにFlowが導入された動機として、TypeScriptではパフォーマンスが十分でないケースに適応するため、という記述がありました。 ↩︎

  2. はじめのうちはFlowで書かれた.jsを無理やり.tsに拡張子を書き換えて、多少エディタからのwaringを少なくするみたいな暴挙をやったりしてました ↩︎

  3. マーケットプレイスに記載されてるor completely disable the built-in TypeScript extension for your project (see gif below): の手順だと何故かJavaScriptのalertが出力されたままになってしまい、こっちの"javascript.validate.enable": falseの方だとうまくいきました。 ↩︎

Discussion