---
title: "Sitecore GraphQLベストプラクティス"
slug: "sitecore-graphql-best-practices"
abstract: "Sitecore GraphQL使用時の推奨ベストプラクティスと、パフォーマンス向上の方法。"
---
# Sitecore GraphQLベストプラクティス

Sitecore GraphQL APIと取引する際は、以下のベストプラクティスを遵守することをお勧めします。

## コンテキスト認識エンドポイントを活用しましょう

公開サイトでは、正しいコンテンツデータベース(master/web/etc)を尊重するためにデータベースコンテキスト認識エンドポイントを使用しましょう。これにより、APIは認証済みモード(プレビュー、エクスペリエンスエディター)で適切なアイテムデータを返します。

> !注Edge Previewのエンドポイントにはコンテキスト認識型エンドポイントを使用する必要はありません。

エンドポイントをコンテキスト認識型にするには:

-   エンドポイントが型として定義されていることを確認してください Sitecore.Services.GraphQL.Hosting.DatabaseAwareGraphQLEndpoint, Sitecore.Services.GraphQL.NetFxHost
-   ContentSchemaProviderのデータベース設定を設定する際は、実際のデータベース名ではなくcontextに設定してください。これにより、Sitecore.Context.Databaseに従ってください。
-   コンテキスト認識エンドポイントはデータベースごとに異なるスキーマを提供するため、検証したクエリは master 背後のテンプレートが公開されていなければ web に対して検証できない可能性があります。
-   エンドポイントがデータベース固有のコンテンツを提供していない場合は、コンテキスト認識型エンドポイントにしないでください。例えば、CRMに接続するためだけに指定したり、分析データをプッシュしたりするエンドポイントなど、

## 公開ウェブサイトでの購読はご禁止ください

公開ウェブサイトでのGraphQLサブスクリプションは使用しないでください。

サブスクリプションは、著者が使用するContent Managementサーバーのカスタマイズに使用することを意図しています。Sitecoreは、スケールされた公開環境でのサブスクリプション使用をサポートしていません。

## 自分でグラフタイプを実装してください

自分のIGraphType実装でフィールドを定義する方法には多くの選択肢があります。

一般的に、最も性能が高く柔軟な方法はFieldメソッドを使い、グラフ型を明示的に指定し、名前付きリゾルバ関数を使用することです。こうすることで、エラーが発生した際に良好なスタックトレースが得られます。以下はその例です:

// the <ItemState> determines the data object type this graph type maps to
// (in a resolver, context.Source is of this type)
public class ItemWorkflowGraphType : ObjectGraphType<ItemState>
{
 public ItemWorkflowGraphType()
 {
 // ALWAYS set the name. Note that the name must be unique within a schema so be descriptive.
 Name = "ItemWorkflow";

 // define your field (note: wrap type in NonNullGraphType<T> if it should never be null)
 Field<ItemWorkflowStateGraphType>("workflowState", resolve: ResolveWorkflowState);

 // this would automatically map to a property on the ItemState called WorkflowState
 // DO NOT use this format, because it causes reflection during queries = slow
 Field<ItemWorkflowStateGraphType>("workflowState");

 // Expression-based resolver. Reasonable performance, non-verbose, but cannot specify
 // the graph type (or its nullablilty), and you do not get nice stack traces on error
 // useful for very simple scalar type resolution (e.g. strings, ints)
 Field("workflowState", state => GetWorkflowState());

 // Sometimes you might not have access to the Field() method, in which case
 // you can use manual field-adding syntax. This example is equivalent to the first recommended one.
 // Note: DO NOT set the ResolvedType property by accident. This will mess things up.
 AddField(new FieldType
 {
 Name = "workflowState",
 Type = typeof(ItemWorkflowStateGraphType),
 Resolver = new FuncFieldResolver<ItemState, WorkflowState>(ResolveWorkflowState)
 });
 }

 // explicit named resolver function means that you will see a reasonable stack trace if a resolve error occurs
 // (as oppposed to an anonymous function in the constructor)
 private WorkflowState ResolveWorkflowState(ResolveFieldContext<ItemState> context)
 {
 return context.Source.GetWorkflowState();
 }
}

### 任意の階層への対処

特に恣意的に入れ子状にされた階層構造など、GraphQLでは扱いにくい種類のデータがあります。

例えば、ある項目のすべての子孫を取得したい場合、子の階層数が不明な場合、GraphQLはグラフのどの部分を指定する必要があるため、これをサポートしていません。

また、常にフィールドの集合を一緒にしたい場合や、全く使わない場合(例えば、レンダリングツールキットで使われる任意のJSONのブロックで、ユーザーにGraphQL断片を暗記させたくない場合などです)。この場合、JsonGraphTypeを使うことができます。このタイプでは、任意のJSONをGraphQLフィールドとして返すことができます。これは、グラフがデータを適切に表現できない場合の最後の手段です。JsonGraphTypeのリゾルバは、任意のオブジェクト(直列化されたもの)やJToken (そのまま使うもの)を返すことができます。

JsonGraphTypeは入力グラフタイプとしても使われ、その場合はエスケープ文字列として値を渡す必要があります。これは、実際のJSONがエスケープせずに返される出力タイプとは異なります。

## GraphQL APIを最初から消費しましょう

GraphQL APIを最初から視聴する際には、以下のことをお勧めします。

-   フロントエンドサイトやアプリケーションのGraphQL APIを使う際は、必ずそのサイトごとに独自のエンドポイントを定義してください。これにより、攻撃対象、認証、APIのURLを細かく制御できます。できるだけAPIを露出させましょう。
-   もし ContentSchemaProvider のようなスキーマ提供者がすでに存在する場合は再利用してください。
-   クエリは .graphql ファイルに分けてください。コードと混ぜてはいけません。
    -   これにより問題の分離がうまくでき、 graphql-tag/loaderのようなツールを使えば、JavaScriptファイルと同じ方法でファイルをインポートできます。
    -   静的に解析可能なクエリは、ビルド時にすべてのクエリを検証しやすくし、セキュリティホワイトリストを実行し、その他の一般的な操作を行わせます。
    -   これができない場合(例えば現在のAngularでは、GraphQLローダーを追加するビルドをカスタマイズできません)、クエリを .js ファイルや .ts Angularコンポーネントの mycomponent.graphql.ts だけを含むファイルに分けてください。
-   動的文字列連結クエリ(クエリテキストにGraphQL以外の変数を含むもの)は絶対に使わないでください。クエリ変数は常にGraphQLクエリ変数でなければなりません。
    -   これはホワイトリストや静的分析、パフォーマンス分析を無効にし、一般的にはあまり良い考えではありません。
-   クエリバッチングを活用しましょう:
    -   GraphQLがRESTに比べて持つ大きな利点の一つは、GraphQLがプロトコルであるため、RESTではできないことのいくつかを可能にできることです。
    -   クエリバッチングにより、短時間内に複数のクエリを自動的に1つのHTTPリクエストにまとめることが可能になります。
-   GraphQLクエリがGraphQLスキーマに対して有効であることを確認するためのツールを使いましょう。例えば eslint-plugin-graphql。
    -   これにより、クエリ式が有効で実行時に壊れないというビルドタイムの安全性が保証されます。

## GraphQL工具とSitecore GraphQLを使え

多くの種類のGraphQLツール( [例えば、eslint-plugin-graphql](https://github.com/apollographql/eslint-plugin-graphql)はビルド時にクエリを検証し、graphql-toolsは切り離されたモックGraphQL APIを作成し、[ts-graphql-plugin](https://github.com/Quramy/ts-graphql-plugin)はTypeScriptでGraphQLのコード補完を提供します)は、正しく実行するためにGraphQLスキーマのコピーが必要です。場合によっては、Sitecoreインスタンスから直接ダウンロードしてライブスキーマを得ることもできます。ただし、他の場合にはライブのSitecoreインスタンスが存在しないため、スキーマの静的コピーが必要です。

スキーマ入力には主に2つのタイプがあります。

-   JSONフォーマットのスキーマです。これは、GraphQL APIに対する内省クエリの結果です。例えば、GraphiQLがブラウザ上でドキュメントを提供するためにこれを使っています。
-   スキーマ定義言語スキーマです。これは読みやすい形式でスキーマを定義するテキスト形式です。 $endpointUrl/schema にアクセスして内容を取得し、 .graphql ファイルとして保存することでダウンロードできます。

Sitecoreの設定変更(テンプレートの変更や追加など)がGraphQLスキーマを変更すると、静的スキーマファイルを使用する場合は、誤った検証を防ぐために常に最新の状態を維持する必要があります。