私が歌川です

@utgwkk が書いている

relay-compilerが要求する命名規則

はじめに

みなさまはrelay-compilerを使っていて以下のようなエラーに遭遇したことはありませんか。私は3000回ぐらいあります。

ERROR:
Parse error: Error: RelayFindGraphQLTags: Operation names in graphql tags must be prefixed with the module name and end in "Mutation", "Query", or "Subscription". Got `BarQuery` in module `Foo`. in "components/Foo.tsx"

relay-compilerは graphql タグ内に記述したQuery, Mutation, Fragmentの名前に「モジュール名から始まる」「Fragment以外は種類 (Query, Mutation) で終わる」という規則を要求し、従っていない場合はコンパイルを失敗させます。例えば components/Foo.tsx なら FooQuery FooMutation Foo_user のように、モジュール名 Foo から始めないといけません。

一方で components/Bar/index.tsx のようなパスの場合は Bar がモジュール名になります。今のチームではReactコンポーネントのファイルパスは基本的にPascalCaseにして実装していますが、camelCase*1やsnake_caseやkebab-caseを使う場合も考えられるでしょう。

relay-compilerが要求するモジュール名がどのように判定されているのか、気になりませんか?

Relay 12の実装を見る

ということでrelay-compilerの実装を見ましょう。v12.0.0 タグにcheckoutして探してみます。

エラーメッセージをもとに探してみます。RelayFindGraphQLTags: でgrepするといくつか出てきます。今回該当するのは以下の行ですね。

github.com

validateTemplate 関数の呼び出し元は、同じファイルの find 関数のみなので、この引数が moduleName でモジュール名だと分かります。ということで getModuleName 関数の実装を見ればよさそうです。

getModuleName 関数の実装は以下です。コメントと合わせて読むと分かりやすいですね。kebab-caseはうまくcamelCaseに変換してくれるようです。snake_caseは回避したほうがよさそうなことも分かります。.ios.js.android.js のようなファイル名のときに特別対応が行われているのは知りませんでした。

getModuleName 関数のテストを見たほうが早いかもしれませんね。

github.com

Relay 13

ところで今日、Relay 13がリリースされていました。1行目にさらっと書いてありますが、relay-compilerは完全にRustで書き直されたようです。手元にrelayのリポジトリをcloneしていたのですが、久しぶりにpullしたらめちゃくちゃ時間がかかってびっくりしました。

github.com

気を取り直して勘でRustを読んでいきます。module name でgrepしたら以下の行が見つかりました。ここで module_name というフィールドに渡している値を特定できればよさそうに見えますね。

github.com

すぐ上を見ると extract_module_name という関数がありそうですね。この関数の定義は以下です。正規表現が使われていないのですが、おそらくここで互換性を壊すようなことはないだろうと想像します。

github.com

テストも見てみました。一見するとRelay 12までと挙動は変わっていなさそう?

github.com

おわりに

relay-compilerが要求する命名規則が分かりました。そろそろRustを難なく読み書きできるようになったほうがよいのかもしれません。

*1:先頭が小文字。Reactコンポーネントだとあまりない?