Skip to content

Instantly share code, notes, and snippets.

@Tylerian
Created October 18, 2019 16:09
  • Star 3 You must be signed in to star a gist
  • Fork 1 You must be signed in to fork a gist
Star You must be signed in to star a gist
Save Tylerian/16d48e5850b407ba9e3654e17d334c1e to your computer and use it in GitHub Desktop.
Next.js with Apollo implementation
import NextApp, {
AppInitialProps
} from "next/app";
import {
ApolloClient
} from "apollo-client";
import {
ApolloProvider
} from "@apollo/react-hooks";
import {
APOLLO_ENDPOINT
} from "../config";
import {
createApolloClient
} from "../lib/apollo";
type AppProps = AppInitialProps & {
apolloClient?: ApolloClient<object>;
};
class App extends NextApp<AppProps> {
render() {
const {
pageProps,
Component,
apolloClient = createApolloClient({ url: APOLLO_ENDPOINT }),
} = this.props;
return (
<ApolloProvider client={apolloClient}>
<Component {...pageProps} />
</ApolloProvider>
);
}
}
export default App;
import React from "react";
import Document, {
DocumentContext,
DocumentInitialProps,
Html,
Head,
Main,
NextScript
} from "next/document";
import {
ApolloClient
} from "apollo-client";
import {
getDataFromTree
} from "@apollo/react-ssr";
import {
createApolloClient
} from "../lib/apollo";
type DocumentProps = DocumentInitialProps & {
apolloState: object;
};
export default class extends Document<DocumentProps> {
/**
* Take the apolloState from apollo
* (as generated in getInitialProps)
* and assign them to __NEXT_DATA__ so that they
* are accessible to the client for rehydration.
*/
constructor(props: any) {
super(props);
const {
apolloState,
__NEXT_DATA__
} = props;
__NEXT_DATA__.apolloState = apolloState;
}
/**
* Called once on the initial app entry-point (server-side).
*
* @param {DocumentContext} ctx
*/
static async getInitialProps(ctx: DocumentContext) {
const apolloClient = createApolloClient();
// render props
const renderPage = ctx.renderPage;
const renderPageEnhancer = {
enhanceApp: (App: any) =>
(ctx: any) => <App {...ctx} apolloClient={apolloClient} />
};
// swizzle render logic
ctx.renderPage = () =>
renderPage(renderPageEnhancer);
// run apollo before nextjs render
await getDataFromTree(
/* ctx.AppTree is App without appProps
* and without being renderPageEnhanced */
<ctx.AppTree {...ctx.appProps} apolloClient={apolloClient} />
);
// collect apollo state
const apolloState = (
apolloClient.extract()
);
// synchronously render page
const documentProps = (
await Document.getInitialProps(ctx)
);
return {
apolloState,
...documentProps
};
}
render() {
return (
<Html>
<Head/>
<body>
<Main />
<NextScript />
</body>
</Html>
);
}
}
import React from "react";
import fetch from "isomorphic-unfetch"
import {
ApolloClient
} from "apollo-client";
import {
HttpLink
} from "apollo-link-http";
import {
InMemoryCache
} from "apollo-cache-inmemory";
import {
ApolloProvider
} from "@apollo/react-hooks";
const isServer = (
typeof window === "undefined");
const windowApolloState = (
!isServer && window.__NEXT_DATA__.apolloState);
type ApolloClientOptions = {
url: string;
ssrMode: boolean;
initialState?: object;
};
/**
* Creates and configures an ApolloClient
* @param {Object} [initialState=window.__NEXT_DATA__.apolloState]
*/
export function createApolloClient(options: ApolloClientOptions) {
const {
url,
ssrMode = isServer,
initialState = windowApolloState
} = options;
// Check out https://github.com/zeit/next.js/pull/4611
// if you want to use the AWSAppSyncClient
return new ApolloClient({
ssrMode: ssrMode,
link: new HttpLink({ uri: url, fetch }),
cache: new InMemoryCache().restore(initialState)
});
}
const APOLLO_ENDPOINT = "https://<your_graphql_endpoint>";
export {
APOLLO_ENDPOINT
};
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment