Я недавно перешел с apollo-boost
на ручную или стандартную конфигурацию Apollo.У меня есть некоторые небольшие проблемы с рендерингом на стороне сервера от Next JS и заголовками, которые я установил в контексте запроса.Вот мой конфиг с комментарием рядом с проблемой:
import withApollo from 'next-with-apollo';
import { ApolloClient } from 'apollo-client';
import { InMemoryCache } from 'apollo-cache-inmemory';
import { HttpLink } from 'apollo-link-http';
import { onError } from 'apollo-link-error';
import { withClientState } from 'apollo-link-state';
import { getMainDefinition } from 'apollo-utilities';
import { ApolloLink, Observable, split } from 'apollo-link';
import { endpoint, WSendpoint } from '../config';
import { LOCAL_STATE_QUERY } from '../components/page/page';
import { WebSocketLink } from 'apollo-link-ws';
const wsLink = process.browser ? new WebSocketLink({
uri: 'development' ? WSendpoint : WSendpoint,
options: {
reconnect: true
},
credentials: 'include'
}): null;
const httpLink = new HttpLink({
uri: process.env.NODE_ENV === 'development' ? endpoint : endpoint,
credentials: 'include',
})
const link = process.browser ? split(
({ query }) => {
const { kind, operation } = getMainDefinition(query);
return kind === 'OperationDefinition' && operation === 'subscription';
},
wsLink,
httpLink,
) : httpLink;
const cache = new InMemoryCache({});
// HERE IS WHERE THE ISSUE LIES
const request = (operation) => {
let token = null;
// if (typeof localStorage !== 'undefined') {
token = localStorage.getItem('token') || null
//}
operation.setContext({
headers: {
token
}
});
};
const requestLink = new ApolloLink((operation, forward) =>
new Observable(observer => {
let handle;
Promise.resolve(operation)
.then(oper => request(oper))
.then(() => {
handle = forward(operation).subscribe({
next: observer.next.bind(observer),
error: observer.error.bind(observer),
complete: observer.complete.bind(observer),
});
})
.catch(observer.error.bind(observer));
return () => {
if (handle) handle.unsubscribe();
};
})
);
function createClient({ headers }) {
return new ApolloClient({
link: ApolloLink.from([
onError(({ graphQLErrors, networkError }) => {
if (graphQLErrors) {
console.log(graphQLErrors)
}
if (networkError) {
console.log(networkError)
}
}),
requestLink,
withClientState({
defaults: {
ui: {
__typename: 'ui',
signupOverlayActive: false
}
},
resolvers: {
Mutation: {
toggleOverlay(_, variables, { cache }) {
// some stuff here
}
}
},
cache
}),
link
]),
cache
});
}
export default withApollo(createClient);
Проблема заключается в моей функции request
.С оператором if в этой функции закомментировано, я получаю следующую терминальную ошибку:
'Ошибка сети: localStorage не определено'
Я понимаю, что это происходит от Nextвыполнение рендеринга на стороне сервера, который явно не имеет локального состояния.У меня была похожая проблема с функцией wsLink
, которая устанавливает конечную точку веб-сокета, но я смог просто решить ее, добавив троичный оператор process.browser ?
, чтобы остановить работу веб-сокета на стороне сервера, если process.browser
неопределены.
Я пытался применить аналогичный подход к функции request
, но проблема в том, что при начальной загрузке страницы он не отправляет токен из локального хранилища (так как первая загрузка страницы происходит из кода, представленного сервером),
Это создает проблему, заключающуюся в том, что при первой загрузке страницы пользователь не будет автоматически входить в систему!
Проблема отсутствовала, когда я использовал apollo-boost
, так что, вероятно, я могупропустить что-то вне конфигурации здесь.
Спасибо