Vue+Apollo Client连接GraphQL服务器WebSocket失败求助
排查WebSocket连接失败(Websocket failed to Connect)问题
问题概述
客户端与服务器端均出现「WebSocket failed to Connect」错误,仅通过Apollo Client配置WebSocket连接,无其他相关配置,问题已持续2天。环境为Vue客户端连接GraphQL Apollo服务器。
相关代码
ApolloClient配置
// Apollo packages import { ApolloClient } from "apollo-boost-upload"; import { WebSocketLink } from "apollo-link-ws"; import { HttpLink } from "apollo-link-http"; import { InMemoryCache } from "apollo-cache-inmemory"; import { split } from "apollo-link"; import { getMainDefinition } from "apollo-utilities"; import VueApollo from "vue-apollo"; Vue.use(VueApollo); const wsLink = new WebSocketLink({ uri: "ws://localhost:4000/graphql", // use wss for a secure endpoint options: { reconnect: true, }, }); // 注意:原代码缺少httpLink的初始化,需补充 const httpLink = new HttpLink({ uri: "http://localhost:4000/graphql", credentials: "include" }); const link = split( // split based on operation type ({ query }) => { const definition = getMainDefinition(query); return ( definition.kind === "OperationDefinition" && definition.operation === "subscription" ); }, wsLink, httpLink ); // Cache implementation export const defaultClient = new ApolloClient({ link, cache: new InMemoryCache(), fetchOptions: { credentials: "include", }, request: (operation) => { // if no token in local storage, add it if (!localStorage.anaceptToken) { localStorage.setItem("anaceptToken", ""); } // operation adds the token to authorization header, which is sent to backend operation.setContext({ headers: { authorization: "Bearer " + localStorage.getItem("anaceptToken"), }, }); }, onError: ({ graphQLErrors, networkError }) => { if (networkError) { console.log("[networkError]", networkError); } if (graphQLErrors) { for (const error of graphQLErrors) { console.dir(error); console.log(error); if ( error.name === "AuthenticationError" || error.message === "jwt expired" ) { // set auth error in state store.commit("setError", error); // signout user to clear error store.dispatch("signUserOut"); } } } }, });
Vue配置文件
const { defineConfig } = require("@vue/cli-service"); const NodePolyfillPlugin = require("node-polyfill-webpack-plugin"); module.exports = defineConfig({ pluginOptions: { apollo: { enableMocks: true, enableEngine: true, }, }, transpileDependencies: ["vuetify"], chainWebpack: (config) => { config.performance.maxEntrypointSize(400000).maxAssetSize(400000); // 修正插件注册方式,原写法不会生效 config.plugin('node-polyfill').use(NodePolyfillPlugin); }, });
错误截图

排查与修复步骤
- 补全httpLink初始化:原代码未实例化
httpLink,会导致链路拆分逻辑失效,必须添加上述代码中的httpLink初始化部分。 - 验证服务器WebSocket配置:确认Apollo Server已启用WebSocket支持(如使用
subscriptions-transport-ws或graphql-ws库),且ws://localhost:4000/graphql端点可正常访问。 - 添加WebSocket的token传递:WebSocket连接不会自动继承HTTP请求的头信息,需在WebSocketLink的options中配置
connectionParams传递token:const wsLink = new WebSocketLink({ uri: "ws://localhost:4000/graphql", options: { reconnect: true, connectionParams: { authorization: "Bearer " + localStorage.getItem("anaceptToken"), }, }, }); - 修正Webpack插件配置:原chainWebpack中直接
new NodePolyfillPlugin无法正确注册插件,需改用config.plugin方式添加。 - 检查端口与跨域:确保4000端口未被占用,服务器已配置允许WebSocket的跨域规则(如CORS设置包含WebSocket相关允许项)。
内容的提问来源于stack exchange,提问作者rhythmo
相关产品推荐
相关产品推荐

