原本 SSR環境就已經比較複雜了 現在要再加上上傳檔案middleware跟subscriptions的部分 有點小複雜
以下說明一下 如何組合 可以用的 apollo init 說明文字直接寫在 code備註中
import { ApolloClient } from 'apollo-client'
import { setContext } from 'apollo-link-context'
import fetch from 'isomorphic-unfetch'
import { createUploadLink } from 'apollo-upload-client' //可以使用graph上傳資料
import config from '../config'
import { SubscriptionClient } from 'subscriptions-transport-ws';
import { WebSocketLink } from 'apollo-link-ws';
import { InMemoryCache, NormalizedCacheObject } from 'apollo-cache-inmemory';
import { split } from 'apollo-link';
import { getMainDefinition } from 'apollo-utilities';
import ws from 'ws';
let apolloClient: any = null
const WS_URI = `wss://clawfun.online/graphql`; //設定socket uri
const cache = new InMemoryCache();
if (!process.browser) { global["fetch"] = fetch } //server端補一個fetch
const ssrMode = (typeof window === 'undefined'); //seever端另外一判方法比照上一行
function create(initialState: any, { getToken }: { getToken: any }) {
const token = getToken()
let link: any, linkServer: any, linkClient: any, wsLink: any
const httpLink = createUploadLink({ uri: `${config.serverURL()}/graphql`, credentials: 'include' });
//因為有上傳檔案的需求使用了 createUploadLink
const authLink = setContext((_, { headers }) => { const token = getToken(); return { headers: { ...headers, authorization: token ? `Bearer ${token}` : '' } } })
//這裏先取得token 如果有token 就夾到 headers 之後打api都會附加上去作為jwt驗證用
try {
if (!ssrMode) {
//client 建立socket 並要記得設定 reconnect :true
wsLink = new SubscriptionClient(WS_URI, { reconnect: true, connectionParams: { headers: { authorization: token ? `Bearer ${token}` : '' } } });
//這裏是區分query的時候要用哪種模式 wsLink 與 httpLink 由 apollo 提供的 getMainDefinition 去判斷
linkClient = split(
({ query }) => {
const definition = getMainDefinition(query);
return (definition.kind === 'OperationDefinition' && definition.operation === 'subscription');
}, wsLink, httpLink);
console.log('linkClient');
} else {
linkServer = authLink.concat(httpLink); //server部分就不需要建立 socket
}
} catch (err) { console.log('err', err); }
const client: ApolloClient<NormalizedCacheObject> = new ApolloClient({
connectToDevTools: process.browser,
ssrMode: !process.browser,
link: ssrMode ? linkServer : linkClient,
cache: new InMemoryCache({ dataIdFromObject: (object: any) => object["key"] || null }).restore(initialState || {})
})
return client
}
export default function initApollo(initialState: any, options: any) {
if (!ssrMode) { return create(initialState, options) }
if (!apolloClient) { apolloClient = create(initialState, options) }
return apolloClient
}
在判斷 wsLink與 httpLink 與 SSR 區分 是在設定 apollo init 要特別注意的 ,希望對初次設定的朋友 有幫助