コンパイラアーキテクチャ
コンパイラはコードベース全体からGraphQLドキュメントを抽出し、それらを変換/最適化し、ビルドアーティファクトを生成するように設計されたモジュールのセットです。一般的なタイプのアーティファクトの例としては、サーバーに永続化するための最適化されたGraphQL、GraphQLクライアント(Relayランタイムなど)で使用するためのクエリの実行時表現、コンパイル済み言語(Java/Swift/など)のGraphQLフレームワークで使用するための生成されたソースコードなどがあります。
データフロー
コンパイラを通過するデータのハイレベルなフローは以下の図に示します
┌─────────────┐┌─────────────┐
│ GraphQL ││ Schema │
└─────────────┘└─────────────┘
│ │ parse
└───────┬──────┘
▼
┌────────────────────────────┐
│ CompilerContext │
│ │
│ ┌─────┐ ┌─────┐ ┌─────┐ │──┐
│ │ IR │ │ IR │ │ ... │ │ │
│ └─────┘ └─────┘ └─────┘ │ │
└────────────────────────────┘ │ transform/
│ │ ▲ │ optimize
│ │ └────────────┘
│ │
│ └──────────┐
│ print │ codegen
▼ ▼
┌─────────────┐ ┌─────────────┐
│ GraphQL │ │ Artifacts │
└─────────────┘ └─────────────┘
- GraphQLテキストはソースファイルから抽出し、スキーマの情報を使用して中間表現(IR)に「解析」されます。
- 一連のIRドキュメントによりCompilerContextが形成され、それらが変換され、最適化されます。
- 最後に、GraphQLが印刷され(例:ファイルへの印刷、データベースへの保存など)、すべてのアーティファクトが生成されます。
データタイプとモジュール
コンパイラモジュールは、主要なビルディングブロックのセットおよびそれらを使い勝手のよいAPIにパッケージ化するヘルパーで構成されています。コンパイラの主なデータタイプとモジュールには以下のようなものがあります
IR
(中間表現):スキームのタイプ情報をはじめとして、GraphQLドキュメント(クエリ、フラグメント、フィールドなど)の(実質的に不変の)表現を、ツリー構造として示します。標準のGraphQL AST(例:graphql-js
によって生成される)と比べて主な違いは、GraphQLのセマンティクスをより多くエンコードしていることです。たとえば、条件分岐(@include
および@skip
)が直接表現されており、これらの指令の最適化を容易にしています(そのような最適化の一つが、条件が同じ兄弟フィールドをマージすることであり、実行時に評価する必要のある条件の数を減らすことができます)。CompilerContext
:GraphQLドキュメントコーパスの不変表現。スキーマと、ドキュメント名からドキュメント表現(上記のIRとして)へのマッピングを含んでいます。Transform
:CompilerContext
を入力として受け取り、新しい変更されたコンテキストを出力として返す「マップ」のような関数です。以下の例を参照してください。パーサ
: GraphQL スキーマおよび未処理の GraphQL テキストを変換して、型付き IR オブジェクトにします。プリンタ
: IR を受け取り GraphQL 文字列に変換する関数です。
RelayCompiler
モジュールは、これらのプリミティブを組み合わせることを示すヘルパークラスです。これらでは、IR 変換を使用して、IR 定義が与えられると、それらの定義から CompilerContext を構築して変換し、Relay ランタイムで使用するための出力アーティファクトを生成します。
変換
コンパイラの主なゴールの 1 つは、GraphQL を変換または最適化するツールを作成するための安定したプラットフォームを提供することです。これには、コンパイル時にそれらを変換して、新しいディレクティブを試す機能が含まれます。変換関数は通常は 1 種類の変更を実行します。アプリにはコンパイラインスタンスに構成された複数の変換があると想定されています。
同梱の変換の例をいくつか示します。
FlattenTransform
: クエリ内の余分なレベルの間接化を減らし、親タイプと一致する匿名フラグメントからフィールドをインラインします。これは、重複するフィールド処理を減らすため、クエリの結果を読み取るコードの生成またはクエリの結果を処理する場合に役立つ可能性があります。例:
# before: `id` is processed twice
foo { # type FooType
id
... on FooType { # matches the parent type, so this is extraneous
id
}
}
# after: `id` is processed once
foo {
id
}
SkipRedundantNodeTransform
: フラットニングのより高度なバージョンであるこれを使用すると、条件付きと無条件の両方でフィールドを取得する場合や、2 つの異なるサブフラグメントで取得する場合などの、より複雑なフィールドの重複を削除できます。例:
# before: `id` processed up to 2x
foo {
bar {
id
}
... on FooType @include(if: $cond) { # can't be flattened due to conditional
id # but this field is guaranteed to be fetched regardless
}
}
# after: `id` processed at most once
foo {
bar {
id
}
}
このページは役立ちましたか?
以下の方法でサイトをより改善するのに協力してください いくつかの簡単な質問に答える.