Apollo HOC for NextJS.
Install the package with npm
npm install nextjs-with-apollo
or with yarn
yarn add nextjs-with-apollo
- Create a HOC
Create the HOC using a basic setup.
// hocs/withApollo.js import withApollo from 'nextjs-with-apollo'; import ApolloClient from 'apollo-client'; import { InMemoryCache } from 'apollo-cache-inmemory'; const GRAPHQL_URL = 'https://your-graphql-url'; const createApolloClient = ({ initialState, headers }) => new ApolloClient({ uri: GRAPHQL_URL, cache: new InMemoryCache().restore(initialState || {}) // hydrate cache }); export default withApollo(createApolloClient);
Parameters initialState
and headers
are received in the hoc.
If the render is happening in server, all headers received by the server can be accessed via headers
. If the render is happening in browser, we hydrate the client cache with the initial stated created in server.
- Now use the HOC
import React from 'react'; import { useQuery } from '@apollo/react-hooks'; import withApollo from 'hocs/withApollo'; const QUERY = gql` query Profile { profile { name displayname } } `; const ProfilePage = () => { const { loading, error, data } = useQuery(PROFILE_QUERY); if (loading) { return <p>loading..</p>; } if (error) { return JSON.stringify(error); } return ( <> <p>user name: {data.profile.displayname}</p> <p>name: {data.profile.name}</p> </> ); }; export default withApollo(ProfilePage);
Thats all. Now Profile page will be rendered in the server. You do not need to do anything in getInitialProps
. All queries are resolved in the sever.
If you dont want to SSR the above page then you can pass {ssr: false}
to the hoc.
export default withApollo(ProfilePage, { ssr: false });
If you want, you can also access instance of apolloClient
in getInitialProps
.
ProfilePage.getInitialProps = ctx => { const apolloClient = ctx.apolloClient; };
Often graphQL server requires AuthorizationToken
for authorizing requests. We can use the headers received in server to parse token from client side cookies.
// hocs/withApollo.js import withApollo from 'nextjs-with-apollo'; import fetch from 'isomorphic-unfetch'; import { InMemoryCache } from 'apollo-cache-inmemory'; import ApolloClient from 'apollo-client'; import { HttpLink } from 'apollo-link-http'; import { ApolloLink } from 'apollo-link'; import { setContext } from 'apollo-link-context'; import cookie from 'cookie'; import get from 'lodash/get'; const isServer = typeof window === 'undefined'; const getToken = headers => { const COOKIE_NAME = 'your_auth_cookie_name' const cookies = isServer ? get(headers, 'cookie', '') : document.cookie; return get(cookie.parse(cookies), COOKIE_NAME, ''); }; const attachAuth = headers => () => { const token = getToken(headers); return { headers: { authorization: `Bearer ${token}` } }; }; const createApolloClient = ({ initialState, headers = {} }) => { const authLink = () => setContext(attachAuth(headers)); const httpLink = new HttpLink({ credentials: 'include', uri: GRAPHQL_ENDPOINT, fetch }); return new ApolloClient({ ssrMode: isServer, link: ApolloLink.from([authLink(), httpLink]), cache: new InMemoryCache().restore(initialState || {}) }); }; export default withApollo(createApolloClient);
Feel free to use the code, it's released using the MIT license.