リアルタイムビューコンポーネントのビルドとデプロイ

GitLab は、ユーザーからの入力を受け付け、状態の変更をユーザーに反映する個々のビューコンポーネントを通して、インタラクティブなユーザー体験を提供します。例えば、マージリクエストページでは、ユーザーは承認したり、コメントを残したり、CI/CDパイプラインとやり取りしたりすることができます。

しかし、GitLab は状態の更新をタイムリーに反映しないことがよくあります。これは、ページの一部が古いデータを表示し、ユーザーがページをリロードした後にのみ更新されることを意味します。

このアドレスに対応するため、GitLabはWebSocketを介してビューコンポーネントがリアルタイムで状態の更新を受け取ることができる技術とプログラミングAPIを導入しました。

以下のドキュメントでは、GitLab Ruby on Railsサーバからリアルタイムで更新を受け取るビューコンポーネントをビルドしてデプロイする方法を説明します。

note
アクションケーブルとGraphQLサブスクリプションは現在開発中であり、活発に開発が行われています。開発者は自分のユースケースを評価し、これらが使用するのに適したツールかどうかを確認する必要があります。よくわからない場合は、#f_real-time 内部 Slack チャンネルで助けを求めてください。

リアルタイムビューコンポーネントの構築

前提条件:

を読んでください:

GitLabでリアルタイム・ビュー・コンポーネントを構築するには、以下の手順が必要です:

  • VueコンポーネントをGitLabフロントエンドのApolloサブスクリプションとインテグレーションします。
  • GitLab Ruby on RailsバックエンドからGraphQLサブスクリプションを追加し、トリガーします。

VueコンポーネントとApolloサブスクリプションのインテグレーション

note
現在のリアルタイムスタックでは、クライアントコードはレンダリングレイヤーとしてVueを、ステートとネットワーキングレイヤーとしてApolloを使用してビルドされることを想定しています。GitLabフロントエンドの一部で、まだVue + Apolloにマイグレーションされていないものを使用している場合は、まずその作業を完了してください。

GitLabIssue のデータを観察し、レンダリングするIssueView Vue コンポーネントを仮想的に考えてみましょう。ここでは簡単のため、イシューのタイトルと説明をレンダリングするだけだと仮定します:

import issueQuery from '~/issues/queries/issue_view.query.graqhql';

export default {
  props: {
    issueId: {
      type: Number,
      required: false,
      default: null,
    },
  },
  apollo: {
    // Name of the Apollo query object. Must match the field name bound by `data`.
    issue: {
      // Query used for the initial fetch.
      query: issueQuery,
      // Bind arguments used for the initial fetch query.
      variables() {
        return {
          iid: this.issueId,
        };
      },
      // Map response data to view properties.
      update(data) {
        return data.project?.issue || {};
      },
    },
  },
  // Reactive Vue component data. Apollo updates these when queries return or subscriptions fire.
  data() {
    return {
      issue: {}, // It is good practice to return initial state here while the view is loading.
    };
  },
};

// The <template> code is omitted for brevity as it is not relevant to this discussion.

クエリは次のようにします:

  • app/assets/javascripts/issues/queries/issue_view.query.graqhql で定義されていること。
  • 次の GraphQL オペレーションをコンテナします:

     query gitlabIssue($iid: String!) {
       # We hard-code the path here only for illustration. Don't do this in practice.
       project(fullPath: "gitlab-org/gitlab") {
         issue(iid: $iid) {
           title
           description
         }
       }
     }
    

これまでのところ、このビューコンポーネントはそれ自体にデータを入力するための最初のフェッチクエリのみを定義しています。これは、ビューによって開始される HTTP POST リクエストとして送信される通常の GraphQLquery オペレーションです。その後のサーバーでの更新は、このビューを古いものにしてしまいます。このビューがサーバーからの更新を受け取るには、次のことが必要です:

  1. GraphQLサブスクリプション定義を追加します。
  2. Apolloサブスクリプションフックを定義します。

GraphQLサブスクリプション定義の追加

サブスクリプションは同様にGraphQLクエリを定義しますが、GraphQLsubscription オペレーションの内部にラップされます。このクエリはバックエンドによって開始され、その結果はWebSocketを介してビューコンポーネントにプッシュされます。

最初のフェッチクエリと同様に、次のことが必要です:

  • app/assets/javascripts/issues/queries/issue_updated.subscription.graqhql でサブスクリプションファイルを定義します。
  • 次のGraphQLオペレーションをファイルに含めます:

     subscription issueUpdatedSubscription($iid: String!) {
       issueUpdated($issueId: IssueID!) {
         issue(issueId: $issueId) {
           title
           description
         }
       }
     }
    

新しいサブスクリプションを追加するときは、以下の命名ガイドラインを使用してください:

  • サブスクリプションのオペレーション名の最後にSubscription 、GitLab EE専用であればSubscriptionEE を付けてください。例えば、issueUpdatedSubscription 、またはissueUpdatedSubscriptionEE
  • サブスクリプションのイベント名に “has happened” アクション動詞を使用してください。例えば、issueUpdated

サブスクリプション定義は通常のクエリと似ていますが、理解しておくべき重要な違いがいくつかあります:

  • query
    • フロントエンドから発信されています。
    • 内部 ID (iid, 数値) を使用します。これは、エンティティが通常 URL で参照される方法です。内部 ID は囲むネームスペース (この例ではproject) からの相対なので、クエリはfullPath の下に入れ子にする必要があります。
  • subscription
    • フロントエンドからバックエンドへの、将来のアップデートを受け取るためのリクエストです。
    • で構成されます:
      • サブスクリプション自身を記述するオペレーション名( この例ではissueUpdatedSubscription )。
      • ネストされたイベントクエリ( この例ではissueUpdated )。ネストされたイベントクエリ:
        • サブスクリプションで使用されるイベント名は、バックエンドで使用されるトリガーフィールドと一致しなければなりません
        • GraphQLでリソースを識別するための望ましい方法である、数値の内部IDの代わりにグローバルID文字列を使用します。詳細については、GraphQL グローバル ID を参照してください。

Apolloサブスクリプションフックの定義

サブスクリプションを定義したら、ApolloのsubscribeToMore プロパティを使ってビューコンポーネントに追加します:

import issueQuery from '~/issues/queries/issue_view.query.graqhql';
import issueUpdatedSubscription from '~/issues/queries/issue_updated.subscription.graqhql';

export default {
  // As before.
  // ...
  apollo: {
    issue: {
      // As before.
      // ...
      // This Apollo hook enables real-time pushes.
      subscribeToMore: {
        // Subscription operation that returns future updates.
        document: issueUpdatedSubscription,
        // Bind arguments used for the subscription operation.
        variables() {
          return {
            iid: this.issueId,
          };
        },
        // Implement this to return true|false if subscriptions should be disabled.
        // Useful when using feature-flags.
        skip() {
          return this.shouldSkipRealTimeUpdates;
        },
      },
    },
  },
  // As before.
  // ...
  computed: {
    shouldSkipRealTimeUpdates() {
      return false; // Might check a feature flag here.
    },
  },
};

これで、ビューコンポーネントがApolloを通じてWebSocket接続で更新を受信できるようになります。次に、バックエンドからイベントをトリガーして、フロントエンドへのプッシュ更新を開始する方法について説明します。

GraphQLサブスクリプションのトリガー

WebSocketから更新を受け取れるビューコンポーネントを書くことは、物語の半分に過ぎません。GitLab Railsアプリケーションでは、以下のステップを実行する必要があります:

  1. GraphQL::Schema::Subscription クラスを実装します。このクラスは
    • フロントエンドから送られたsubscription オペレーションを解決するためにgraphql-ruby によって使われます。
    • サブスクリプションが受け取る引数と、もしあれば呼び出し元に返されるペイロードを定義します。
    • 呼び出し元がこのサブスクリプションを作成する権限があることを確認するために必要なビジネスロジックを実行します。
  2. Types::SubscriptionType クラスに新しいfield を追加します。このフィールドは、Vueコンポーネントを GraphQL::Schema::Subscription クラスにインテグレーションする際に使用するイベント名をマッピングします。
  3. イベント名に一致するメソッドをGraphqlTriggers に追加し、対応する GraphQL トリガーを実行します。
  4. サービスまたは Active Record モデルクラスを使用して、ドメインロジックの一部として新しいトリガーを実行します。

サブスクリプションの実装

すでにGraphQL::Schema::Subscription として実装されているイベントをサブスクライブする場合、このステップは省略可能です。そうでなければ、app/graphql/subscriptions/ の下に新しいサブスクリプションを実装する新しいクラスを作成します。Issue が更新されたことに応答して起こるissueUpdated イベントの例では、サブスクリプションの実装は以下のようになります:

module Subscriptions
  class IssueUpdated < BaseSubscription
    include Gitlab::Graphql::Laziness

    payload_type Types::IssueType

    argument :issue_id, Types::GlobalIDType[Issue],
              required: true,
              description: 'ID of the issue.'

    def authorized?(issue_id:)
      issue = force(GitlabSchema.find_by_gid(issue_id))

      unauthorized! unless issue && Ability.allowed?(current_user, :read_issue, issue)

      true
    end
  end
end

この新しいクラスを作成するとき

  • すべてのサブスクリプションタイプがSubscriptions::BaseSubscription を継承していることを確認してください。
  • サブスクライブされたクエリがどのデータにアクセスできるかを示すために適切なpayload_type を使用するか、公開したい個々のfieldを定義してください。
  • また、クライアントがサブスクライブしたりイベントが発生したりするたびに呼び出されるカスタムフックsubscribeupdate を定義することもできます。これらのメソッドの使用方法については、公式ドキュメントを参照してください。
  • authorized? を実装して、必要な権限チェックを実行します。これらのチェックは、subscribe またはupdate を呼び出すたびに実行されます。

公式ドキュメントでGraphQLサブスクリプションクラスの詳細をお読みください。

サブスクリプションのフックアップ

新しいサブスクリプションクラスを実装しなかった場合、このステップはスキップします。

新しいサブスクリプション・クラスを実装したら、そのクラスを実行する前にSubscriptionType 上のfield にマップする必要があります。Types::SubscriptionType クラスを開き、新しいフィールドを追加します:

module Types
  class SubscriptionType < ::Types::BaseObject
    graphql_name 'Subscription'

    # Existing fields
    # ...

    field :issue_updated,
      subscription: Subscriptions::IssueUpdated, null: true,
      description: 'Triggered when an issue is updated.'
  end
end
note
EE サブスクリプションを接続している場合は、代わりにEE::Types::SubscriptionType を更新します。

:issue_updated graphql-ruby 引数が、フロントエンドからキャメルケースで送信されたsubscription リクエストで使用された名前 (issueUpdated) と一致していることを確認してください。イベントがトリガーできるようになりました。

新しいトリガーを追加します。

既存のトリガを再利用できる場合は、このステップはスキップしてください。

イベントのトリガを簡単にするために、GitlabSchema.subscriptions.trigger のファサードを使います。新しいトリガーをGraphqlTriggers に追加します:

module GraphqlTriggers
  # Existing triggers
  # ...

  def self.issue_updated(issue)
    GitlabSchema.subscriptions.trigger(:issue_updated, { issue_id: issue.to_gid }, issue)
  end
end
note
トリガーがEEサブスクリプションの場合は、代わりにEE::GraphqlTriggers
  • 最初の引数:issue_updated は、前のステップで使用されたfield の名前と一致しなければなりません。
  • 引数の hash は、イベントを発行するイシューを指定します。GraphQL はこのハッシュを使用して、イベントをパブリッシュするトピックを識別します。

最後のステップは、このトリガー関数を呼び出すことです。

トリガの実行

このステップの実装は、構築するものによって異なります。イシューのフィールドが変更される例では、Issues::UpdateService を拡張してGraphqlTriggers.issue_updated を呼び出すことができます。

これで、リアルタイムビューコンポーネントが機能するようになりました。これで、イシューの更新が GitLab UI に即座に反映されるようになりました。

リアルタイムビューコンポーネントのデプロイ

WebSocketはGitLabでは比較的新しい技術であり、大規模なサポートにはいくつかの課題があります。そのため、新機能の導入は以下の手順で行ってください。

リアルタイムコンポーネントの出荷

WebSocket経由の更新は、必要なバックエンドのコードが配置されていないとシミュレーションが難しいため、フロントエンドとバックエンドを同時に作業することができます。

しかし、別々のマージリクエストで変更を送信し、バックエンドの変更を最初にデプロイするほうが安全です。こうすることで、フロントエンドがイベントの購読を開始したときに、バックエンドがそのイベントに対応できるようになります。

既存の WebSocket 接続の再利用

既存の接続を再利用する機能のリスクは最小限です。機能フラグのロールアウトは、セルフホスティングの顧客により多くのコントロールを与えるために推奨されます。しかし、パーセンテージでロールアウトしたり、GitLab.comの新しい接続を見積もる必要はありません。

新しいWebSocket接続の導入

GitLabアプリケーションの一部にWebSocket接続を導入するような変更は、オープンな接続のメンテナーやダウンストリームサービス(Redisやプライマリデータベースなど)にスケーラビリティ上のリスクをもたらします。

ピーク接続数の見積もり

GitLab.com で最初に完全に有効になったリアルタイム機能は、リアルタイムの担当者でした。イシューページへのスループットのピークと WebSocket の同時接続のピークを比較することで、毎秒 1 リクエストで約 4200 の WebSocket 接続が追加されると大雑把に見積もることができます。

新機能が持つ可能性のある影響を理解するには、ピーク・スループット(RPS) の合計を、それが発信されたページ (n) に当てはめ、式を適用します:

(n * 4200) / peak_active_connections

現在のアクティブな接続は、このGrafanaチャートで見ることができます。

この計算は粗雑なものであり、新しい機能がデプロイされるにつれて修正されるべきです。これは、既存の容量の割合として、サポートされなければならない容量の概算をもたらします。

段階的ロールアウト

現在の飽和状態や必要な新規接続の割合によっては、変更をサポートするために新たなキャパシティをプロビジョニングする必要があります。Kubernetesはほとんどのケースでこれを比較的容易にしますが、ダウンストリーム・サービスへのリスクは残ります。

これを軽減するには、新しいWebSocket接続を確立するコードに機能フラグを付け、デフォルトをoff 。機能フラグを注意深く、パーセンテージベースで展開することで、WebSocketダッシュボードで効果を確認することができます。

  1. 機能フラグのロールアウトイシューを作成します。
  2. What are we expected to happenセクションに、新たに必要となる接続の見積もりを追加してください。
  3. 計画チームとスケーラビリティ・チームのメンバーをコピーして、パーセンテージ・ベースのロールアウト計画を見積もります。

下位互換性

機能フラグのロールアウト期間中およびその後無期限は、リアルタイム機能に下位互換性があるか、少なくともグレースフルに劣化する必要があります。すべての顧客がアクション・ケーブルを有効にしているわけではなく、アクション・ケーブルをデフォルトで有効にするには、さらなる作業が必要です。

リアルタイムを要件とすることは、大きな変更を意味するため、次の機会はバージョン15.0です。

GitLab.comのリアルタイム・インフラストラクチャ

GitLab.comでは、WebSocket接続は通常のWebフリートとは完全に分離された専用インフラから提供され、Kubernetesでデプロイされます。これにより、リクエストを処理するノードに対するリスクは制限されますが、共有サービスに対するリスクは制限されません。WebSockets Kubernetesデプロイの詳細については、こちらのエピックをご覧ください。

GitLabリアルタイムスタックの詳細

サーバーから開始されたプッシュはネットワークを伝搬し、ユーザーとのインタラクションなしにクライアントのビュー更新をトリガーする必要があります。

note
歴史的な理由から、クライアントからのポーリングに応答して更新を行うコントローラのルートはrealtime_changesと呼ばれます。これらは条件付きGETリクエストを使用し、このガイドで扱うリアルタイムの動作とは無関係です。

クライアントにプッシュされるリアルタイムの更新は、すべて GitLab Rails アプリケーションから発信されます。これらの更新を開始し、サービスを提供するために、私たちは以下の技術を使っています:

GitLab Railsバックエンド:

  • Redis PubSubでサブスクリプションの状態を処理します。
  • WebSocket接続とデータ転送を処理するアクションケーブル。
  • graphql-ruby GraphQL サブスクリプションとトリガーを実装します。

GitLabフロントエンドで:

  • GraphQLリクエスト、ルーティング、キャッシュを処理するApolloクライアント。
  • リアルタイムで更新されるビューコンポーネントを定義してレンダリングするVue.js。

次の図は、これらのレイヤー間でデータがどのように伝搬するかを示しています。

sequenceDiagram participant V as Vue Component participant AP as Apollo Client participant P as Rails/GraphQL participant AC as Action Cable/GraphQL participant R as Redis PubSub AP-->>V: injected AP->>P: HTTP GET /-/cable AC-->>P: Hijack TCP connection AC->>+R: SUBSCRIBE(client) R-->>-AC: channel subscription AC-->>AP: HTTP 101: Switching Protocols par V->>AP: query(gql) Note over AP,P: Fetch initial data for this view AP->>+P: HTTP POST /api/graphql (initial query) P-->>-AP: initial query response AP->>AP: cache and/or transform response AP->>V: trigger update V->>V: re-render and Note over AP,AC: Subscribe to future updates for this view V->>AP: subscribeToMore(event, gql) AP->>+AC: WS: subscribe(event, query) AC->>+R: SUBSCRIBE(event) R-->>-AC: event subscription AC-->>-AP: confirm_subscription end Note over V,R: time passes P->>+AC: trigger event AC->>+R: PUBLISH(event) R-->>-AC: subscriptions loop For each subscriber AC->>AC: run GQL query AC->>+R: PUBLISH(client, query_result) R-->>-AC: callback AC->>-AP: WS: push query result end AP->>AP: cache and/or transform response AP->>V: trigger update V->>V: re-render

以降のセクションでは、このスタックの各要素について詳しく説明します。

アクションケーブルと WebSocket

アクションケーブルは、Ruby on RailsにWebSocketサポートを追加するライブラリです。WebSocketは、既存のHTTPベースのサーバやアプリケーションを、単一のTCPコネクションを介した双方向通信で強化するHTTPフレンドリーなソリューションとして開発されました。クライアントはまずサーバに通常のHTTPリクエストを送信し、代わりに接続をWebSocketにアップグレードするよう依頼します。成功すると、クライアントとサーバーの両方が同じTCP接続を使用して、双方向でデータを送受信できます。

WebSocket プロトコルは、送信データのエンコード方法や構造化方法を規定していないため、Action Cable のようなライブラリが必要です。アクション・ケーブル

  • HTTP から WebSocket プロトコルへの最初の接続アップグレードを処理します。その後、ws:// スキームを使用するリクエストは、Action Pack ではなく Action Cable サーバーによって処理されます。
  • WebSocket 経由で送信されるデータのエンコード方法を定義します。アクションケーブルでは、JSON を指定します。これにより、アプリケーションはデータを Ruby Hash として提供し、Action Cable はそれを JSON から(または JSON へ)シリアライズします。
  • クライアントの接続や切断、クライアント認証を処理するコールバック・フックを提供します。
  • 開発者がパブリッシュ/サブスクライブやリモートプロシージャコールを実装するための抽象化としてActionCable::Channel を提供します。

アクション・ケーブルは、どのクライアントがどのActionCable::Channelを購読しているかを追跡するためのさまざまな実装をサポートしています。GitLabでは、分散メッセージバスとしてRedis PubSubチャンネルを使用するRedisアダプターを使用しています。異なるクライアントが異なるPumaインスタンスから同じAction Cableチャネルに接続する可能性があるため、共有ストレージが必要です。

note
アクション・ケーブル・チャネルとRedis PubSubチャネルを混同しないでください。アクション・ケーブル・Channel オブジェクトは、WebSocket接続を介して送信されるさまざまな種類のデータを分類して処理するためのプログラミング抽象化 Channelです。Channel Action Cableでは、基礎となるPubSubチャネルは代わりにブロードキャストと呼ばれ、クライアントとブロードキャストの関連付けはサブスクリプションと呼ばれます。特に、各アクションケーブルには多くのブロードキャスト(PubSubチャネル)とサブスクリプションが存在する可能性が Channelあります。

アクションケーブルは、そのChannel APIを通じて Channelさまざまな種類の動作を表現することができChannel 、どの更新も Channel同じWebSocket接続を使用することができるため、GitLabページごとに単一のWebSocket接続を確立するだけで、そのページ上のビューコンポーネントをリアルタイムの動作で拡張することができます。

GitLabページにリアルタイム更新を実装するために、Channel の実装を個別に書くことはしません。その代わりに、GitLabでプッシュベースの更新を必要とするすべてのページがサブスクライブするGraphqlChannel

GraphQLサブスクリプション:バックエンド

GitLabはGraphQLをサポートしており、クライアントはGraphQLクエリを使ってサーバーに構造化データをリクエストすることができます。GraphQLを採用した理由についてはGitLab GraphQL overviewを参照してください。GitLabバックエンドのGraphQLサポートはgraphql-ruby gemによって提供されています。

通常、GraphQLクエリはクライアント主導のHTTP POSTリクエストで、標準的なリクエスト-レスポンスサイクルに従います。リアルタイムの機能のために、私たちは代わりにGraphQLサブスクリプションを使用し、これはpublish/subscribeパターンの実装です。このアプローチでは、クライアントはまずGraphqlChannel にサブスクリプション リクエストを送信します:

  • サブスクリプションの名前field (イベント名)。
  • このイベントがトリガーされたときに実行するGraphQLクエリ。

この情報は、サーバーがこのイベントストリームを表すtopic を作成するために使用されます。トピックは、サブスクリプションの引数とイベント名から派生した一意の名前で、イベントがトリガーされた場合に通知される必要があるすべてのサブスクライバーを識別するために使用されます。複数のクライアントが同じトピックをサブスクライブすることができます。例えば、issuableAssigneesUpdated:issuableId:<hashed_id> は、指定されたIDを持つイシューの担当者が変更されるたびに更新を受けたい場合に、クライアントがサブスクライブするトピックとなります。

バックエンドは、”issue added to epic “や “user assigned to issue “のようなドメインイベントに応じてサブスクリプションを開始します。GitLabでは、これはサービスオブジェクトかActiveRecordモデルオブジェクトになります。トリガーは、GitlabSchema.subscriptions.trigger にそれぞれのイベント名と引数を指定して呼び出すことで実行され、graphql-ruby からトピックが導出されます。そして、このトピックのすべてのサブスクライバを見つけ、各サブスクライバに対してクエリを実行し、その結果をすべてのトピックサブスクライバにプッシュバックします。

GraphQLサブスクリプションの基礎となるトランスポートとしてAction Cableを使用するため、トピックはAction Cableブロードキャストとして実装されます。つまり、各サブスクライバに対して2つのPubSubチャネルが使用されます:

  • 各トピックにつき、graphql-event:<namespace>:<topic> 。このチャネルは、どのクライアントがどのイベントをサブスクライブしているかを追跡するために使用され、すべての潜在的なクライアント間で共有されます。namespace の使用はオプションで、空白にすることもできます。
  • 各クライアントにつき1つのgraphql-subscription:<subscription-id> チャネル。このチャネルはクエリ結果をそれぞれのクライアントに送り返すために使用され、したがって異なるクライアント間で共有することはできません。

次のセクションでは、GitLabフロントエンドがGraphQLサブスクリプションを使用してリアルタイム更新を実装する方法について説明します。

GraphQL サブスクリプションフロントエンド

GitLab フロントエンドは Ruby ではなく JavaScript を実行するので、GraphQL クエリや変異、サブスクリプションをクライアントからサーバーに送信するには別の GraphQL 実装が必要です。そのためにApolloを使います。

ApolloはJavaScriptにおけるGraphQLの包括的な実装であり、apollo-server andやapollo-client 追加のユーティリティモジュールに分かれて apollo-client apollo-serverいます。apollo-server apollo-client 私たちはRubyバックエンドを実行しているため apollo-client apollo-serverapollo-server.NET Frameworkの代わりに apollo-server.NET Frameworkをapollo-server apollo-client 使用して apollo-client apollo-serverいます。

これは単純化します:

  • ネットワーキング、接続管理、リクエストルーティング。
  • クライアント側の状態管理とレスポンスのキャッシュ
  • ブリッジモジュールを使用したGraphQLとビューコンポーネントのインテグレーション。
note
Apollo Clientのドキュメントを読むと、ビューのレンダリングにReact.jsが使用されていることを前提としています。GitLabではReact.jsは使用していません。私たちはVue.jsを使っており、Vue.jsアダプターを使ってApolloとインテグレーションしています。

Vue.jsは、Vue.jsアダプタを使用してApolloと統合します。Apolloは関数とフックを提供しており、これを使用してどのようにVue.jsを定義するかを定義します:

  • ビューがクエリ、変異、サブスクリプションを送信する方法を定義する関数とフックを提供します。
  • 応答は処理されるべきです。
  • レスポンスデータはキャッシュされます。

エントリ ポイントはApolloClient で、これは GraphQL クライアント オブジェクトです:

  • 単一ページ上のすべてのビュー コンポーネント間で共有されます。
  • すべてのビューコンポーネントは内部でサーバとの通信に使用します。

異なるタイプのリクエストをどのようにルーティングすべきかを決定するために、ApolloはApolloLink 抽象を使用します。具体的には、ActionCableLink を使用して、リアルタイムのサーバー サブスクリプションを他のGraphQLリクエストから分割します:

  • Action CableへのWebSocket接続を確立します。
  • マップサーバーは、ビューが自分自身を更新するためにサブスクライブできるクライアント内のObservable イベントストリームにプッシュします。

ApolloとVue.jsの詳細については、GitLab GraphQL開発ガイドを参照してください。