この記事はVue.js Advent Calendar 23日目の記事です。
リアルタイム更新というとFirebase Firestoreが思い浮かびますが、
実はGraphQLのsubscriptionを使っても手軽に出来ます!
vue-apolloでのsubscriptionの設定についての日本語記事があまりなかったので今回紹介します。
サンプルアプリ
「説明いらんから、はよコード」という方は、こちらから。
https://github.com/kawamataryo/hasura-vue-chat-app
subscriptionsの練習用に作ったリアルタイム同期のチャットアプリです。
HasuraでGraphQLサーバーを立てて、vue-apolloでsubscriptionを行っています。
READMEの通り起動すれば数分でhasura, vue-apolloのsubscriptionを体験できます。
(練習用に作ったので優しい目でお願いします。。)
Subscriptionとは?
GraphQLでのWebSocketを使ったリアルタイムデータ通信の手段です。
subscriptionsを使うと、更新された内容をページリロードなしにリアルタイムでサーバーから、Webページに直接通知することが出来ます。
vue-apolloの設定
では本題のvue-apolloのsubscriptionの設定です。
ポイントは、クエリの種別でhttp通信にするか、websocket通信にするか設定しているところです。
new HttpLink
でhttp、new WebSocketLink
でwebsocketのエンドポイントを設定し、
split
関数で呼ばれるクエリによって向き先を変更しています。
import Vue from "vue";
import { ApolloClient } from "apollo-client";
import { HttpLink } from "apollo-link-http";
import { InMemoryCache } from "apollo-cache-inmemory";
import { split } from "apollo-link";
import { WebSocketLink } from "apollo-link-ws";
import { getMainDefinition } from "apollo-utilities";
import VueApollo from "vue-apollo";
// 通常のquery, mutationsで使われるhttp通信のエンドポイントを指定
const httpLink = new HttpLink({
uri: "http://localhost:8000/v1/graphql"
// トークンによる認証を追加する場合は以下のように設定
// headers: {
// authorization: `Bearer xxxxx`
// }
});
// subscriptionで使われるwebsocket通信のエンドポイントを指定
const wsLink = new WebSocketLink({
uri: "ws://localhost:8000/v1/graphql",
options: {
reconnect: true
// トークンによる認証を追加する場合は以下のように設定
// headers: {
// authorization: `Bearer xxxxx`
// }
}
});
// GraphQLのエンドポイントの向き先をクエリの種別で分離するための設定
// 参考 https://www.apollographql.com/docs/link/composition/#directional-composition
const link = split(
({ query }) => {
// クエリから種別を取得してsubscriptionの場合は、wsLink(websocket)を利用する。
const definition = getMainDefinition(query);
return (
definition.kind === "OperationDefinition" &&
definition.operation === "subscription"
);
},
wsLink,
httpLink
);
// Apollo Clientの作成
const apolloClient = new ApolloClient({
link,
cache: new InMemoryCache(),
connectToDevTools: true
});
Vue.use(VueApollo);
// vue-apolloへの接続
export const apolloProvider = new VueApollo({
defaultClient: apolloClient
});
subscribeの実行
サンプルアプリのコードをもとに説明します。
通常のvue-apolloのquery内にsubscriptionsToMore
を追加することでそのqueryに紐づくデータをsubscriptionsの結果でリアルタイム更新することが出来ます。
document
にsubscriptionのクエリを設定し、対象のデータに変更がある場合、updateQuery
で設定した関数が呼ばれ、queryに紐づくデータ(この場合はmessages
)が更新されます。
export default {
data() {
return {
messages: []
}
},
apollo: {
messages: {
query: gql`
query {
messages {
content
userId: user_id
iconColor: icon_color
id
}
}
`,
subscribeToMore: {
document: gql`
subscription {
messages {
id
userId: user_id
iconColor: icon_color
content
}
}
`,
updateQuery: (previousResult, { subscriptionData }) => {
return subscriptionData.data;
}
}
}
.
.
.
}
終わりに
以上、vue-apolloでのsubscriptionsの設定方法でした。
リアルタイム更新をしようと思うとぱっと思いつくのはFirestoreですが、GraphQLのSubscriptionも手軽でおすすめです。(Hasuraを使えばなおさら)
vue-apolloは、上手くApolloをVue.js仕様にラップしていて僅かなコードでGraphQL触れるのでとても良いですね。
参考
https://vue-apollo.netlify.com/guide/apollo/subscriptions.html#setup
https://www.howtographql.com/vue-apollo/8-subscriptions/