Node.jsでGraphQLをやりたい~という時にTypeGraphQLやNexus、Pothosなど選択肢がありますが、TypeGraphQLとNexusはコミュニティのメンテナンス的な問題で敬遠し、Pothosも個人の方が中心でメンテしているので、なかなか採用しづらい…という状況が現在起きていると思います(2024年時点)
で、TypeGraphQLの開発者がNestJSの方と同じなので、
NestJSのGraphQLはTypeGraphQLと書き味ほぼ同じですし、
メンテナンス的にもNestJSは今後も生き残っていきそうだからNestJSで良いよね~となると思います(私のケースではそういう事情でNestJSを使っています~)
基本のGraphQLはNestJSでも全然使いやすいのですが、
1点だけ、Subscriptionの設定が非常に分かりづらくてハマります
というか、ハマったのでこの記事をご覧になっているかなと思います
結論から書くと、
@Subscription(() => GeneratedAiText)
generateAiText() {
return pubSub.asyncIterableIterator('generateAiText');
}
上記のような感じで書いているSubscriptionが、
構文的には正しいのにフロントエンドで値を取得できない、generateAiText()関数も実行されない~という時の理由は、websocketの設定です
app.module.tsに書いているでしょうwebsocketの設定のうち、
subscriptionsという項目を’graphql-ws’でもなく、’graphql-transport-ws’でもなく、
下記のように’subscriptions-transport-ws’にしてください
subscriptions: {
'subscriptions-transport-ws': true,
},
そして、フロントエンドのApollo Clientのwebsocketの設定を、
import { WebSocketLink } from '@apollo/client/link/ws';
import { SubscriptionClient } from 'subscriptions-transport-ws';
const wsLink = new WebSocketLink(
new SubscriptionClient('ws://localhost:4000/graphql', {
reconnect: true,
connectionParams: {
// 必要に応じて認証情報などを追加
},
})
);
という感じで、subscriptions-transport-wsで統一してください
参考記事: https://qiita.com/mu-suke08/items/6dc353dd641e352f350e
NestJSやApollo Clientのwebsocketの設定で調べたら、graphql-wsを使おうという話がよく出てきますが動きません(issueやDiscordでも議論されているようです)
なので、例えば下記の設定では@Subscriptionは実行されず、値を取得することもできません
サーバーサイドの設定を、
subscriptions: {
'graphql-ws': true,
},
や、
subscriptions: {
'graphql-ws': {
path: '/graphql',
}
},
↑としたら、そもそもこれはwebsocketの通信自体に失敗します…
次に、
subscriptions: {
'graphql-transport-ws': true,
},
subscriptions: {
'graphql-transport-ws': {
path: '/graphql',
}
},
↑とすると、接続には成功しますが、
エラーは出ないものの、@Subscriptionのメソッドは実行されず、フロントエンドにも値は返されません
上記のようなサーバーサイドの設定と、下記のようなフロントエンドの設定だと失敗します
const wsLink = new WebSocketLink({
uri: 'ws://localhost:4000/graphql',
options: {
reconnect: true,
},
});
困ったものですね…
ライブラリのメンテナンス的にはgraphql-wsが推奨されると思いますが、NestJSで動かないので、仕方ないですがいったんsubscriptions-transport-wsを使うしかないかなと思います
ChatGPTなど生成AIの台頭でリアルタイム、ストリーム通信をwebsocketでやりたい~というニーズが増えてきていると思うので、備忘録的に残しておきます~