NextJS can make your website blazing fast. Thanks to the server side rendering, website of your single-page app is preloaded. However, despite being built on React, NextJS has some differences that make integrating GraphQL an unique challenge. I had a very hard time finding a tutorial like that so I decided to write one on my own. We'll explore First, let's create our next app:
npx create-next-app
Give your app a name. We'll be running in a development environment with
npm run dev
Enter the project folder:
cd MyApp
Install the packages
npm install apollo-server-micro graphql apollo-boost graphql-tag @apollo/react-hooks
Backend
Inside the 'pages/api' create a file named 'graphql.js'. We'll create an apollo server on this endpont (NextJS will make an endpoint on 'api/graphql' for this server).
Let's define the type for query:
import { ApolloServer, gql } from "apollo-server-micro";
const typeDefs = gql`
type Query {
user: String,
email: String
}
`;
Now, let's create resolvers with dummy data. In another post we'll replace this with mongoose resolvers:
const test_user = 'jaguar'
const test_email = 'jaguar@gmail.com'
const resolvers = {
Query: {
user: () => test_user,
email: () => test_email,
},
};
Let's run the Apollo Server:
const apolloServer = new ApolloServer({
typeDefs,
resolvers,
context: () => {
return {};
}
});
const handler = apolloServer.createHandler({ path: "/api/graphql" });
Also make sure that this API route is not parsed and interpreted by NextJS. It has to be interpreted by the Apollo Server: nextjs.org/docs/api-routes/api-middlewares#.. Add the configuration:
export const config = {
api: {
bodyParser: false
}
};
The whole graphql.js file is now:
import { ApolloServer, gql } from "apollo-server-micro";
const typeDefs = gql`
type Query {
user: String,
email: String
}
`;
const test_user = 'jaguar'
const test_email = 'jaguar@gmail.com'
const resolvers = {
Query: {
user: () => test_user,
email: () => test_email,
},
};
const apolloServer = new ApolloServer({
typeDefs,
resolvers,
context: () => {
return {};
}
});
const handler = apolloServer.createHandler({ path: "/api/graphql" });
export const config = {
api: {
bodyParser: false
}
};
export default handler;
Frontend
In the 'pages/_app.js' import the Apollo Client and react hook:
import ApolloClient from 'apollo-boost';
import { ApolloProvider } from '@apollo/react-hooks';
point the Apollo Client instance to the Apollo Server:
const client = new ApolloClient({
uri: 'http://localhost:3000/api/graphql'
});
And add Apollo Provider wrapper for the Component:
function MyApp({ Component, pageProps }) {
return <ApolloProvider client={client}>
<Component {...pageProps} />
</ApolloProvider>
}
So the whole '_app.js' file is:
import '../styles/globals.css'
import ApolloClient from 'apollo-boost';
import { ApolloProvider } from '@apollo/react-hooks';
const client = new ApolloClient({
uri: 'http://localhost:3000/api/graphql'
});
function MyApp({ Component, pageProps }) {
return <ApolloProvider client={client}>
<Component {...pageProps} />
</ApolloProvider>
}
export default MyApp
Now let's use the data inside the 'index.js' file. First, let's import the GraphQL query parser and useQuery hook:
import gql from 'graphql-tag';
import { useQuery } from '@apollo/react-hooks';
Inside the 'Home' function we'll be resolving a query:
const USER_QUERY = gql`
{
user
email
}
`;
const { loading, error, data } = useQuery(USER_QUERY);
if (loading) {
return <p>Loading...</p>;
}
if (error) {
console.log(error)
return <p>Error :(</p>;
}
So we can use it inside 'main' component:
<p>
User is: {data.user}
</p>
<p>
Email is: {data.email}
</p>
Finally, the whole 'index.js' file is:
import Head from 'next/head'
import styles from '../styles/Home.module.css'
import gql from 'graphql-tag';
import { useQuery } from '@apollo/react-hooks';
export default function Home() {
const USER_QUERY = gql`
{
user
email
}
`;
const { loading, error, data } = useQuery(USER_QUERY);
if (loading) {
return <p>Loading...</p>;
}
if (error) {
console.log(error)
return <p>Error :(</p>;
}
return (
<div className={styles.container}>
<Head>
<title>Create Next App with GraphQL</title>
<link rel="icon" href="/favicon.ico" />
</Head>
<main className={styles.main}>
<div className="App">
<header className="App-header">
<p>
User is: {data.user}
</p>
<p>
Email is: {data.email}
</p>
</header>
</div>
</main>
<footer className={styles.footer}>
</footer>
</div>
)
}
Let's check the browser at 'localhost:3000/'. You should see:
Voila! We successfully integrated GraphQL with NextJS. Next - integrating mongoose.
Let the good times roll!