Link to WPGraphQL on Github
Link to WPGraphQL on WordPress.org

Easy static HTML exports of your Next.js + GraphQL site

By Paul Grieselhuber

March 1st, 2019

You’re here because you’d like to learn how to create static HTML exports for your Next.js site which uses GraphQL as a data source to create dynamic pages from page components. And that site may even use WPGraphQL to pull content from WordPress.

Fantastic, this article will describe the simple process of doing exactly that.

Generally speaking, all else being equal, serving a static HTML file as a webpage is generally going to be the fastest way to get that page in your users hands. There are exceptions to every rule, but this is a pretty safe bet. This speed is great for SEO, UX, conversion rates, blah blah blah, but building a site that delivers that fast is also just fun!

Bare with me for a few moments as we setup the solution with a bit of boilerplate.

As you will see if you peruse the interactive Next.js docs, they have a simple method of enabling static HTML exports. Create a file in your project at the root directory called next.config.js, and add the following code:

Then add the following to package.json:

And then run:

Now checkout the out directory. You’ll see static HTML file for your index route. You can now run the following to see your site in action:

The Next.js docs then extend this example with the following code snippet:

What we are doing here on the lines starting with '/p…' is passing query data to the component at '/post'.

Ok, now the problem becomes clear: we need a data source to populate the query (or params, title, date, etc.) that our components rely on. But the next export doesn’t “hook into” the GraphQL data source you have likely already setup in your _app.js.

So does this mean you need to rewire everything to hook up GraphQL, write fetching logic, looping, etc?

No, it means I had to. You can just install the NPM package I created and do some basic configuration. 🙂

Enter next-graphql-static-export:

A minimal package which provides the functionality required to perform a static HTML export of dynamic pages from Next.js when using GraphQL as a data source.


Ok, end of boilerplate setup. Let’s get down creating your Next.js+GraphQL+WPGraphQL+static-HTML-exported site.

By the way, you do not need to include WPGraphQL in your project to make use of this method. Though if your site has a WordPress backend, you probably should.

There are no assumptions in the code for the NPM package which rely on WPGraphQL, other than possibly the schema.

Here is the relevant bit of the WPGraphQL schema in a query result:

Notice the nesting of pageInfo, endCursor and hasNext page, along with nodes. It’s worth taking a quick look at the results you get from queries on your project if you are not using WPGraphQL. If your GraphQL server does not return data in this format, no problem, you can still easily use this package. You’ll just need to write a custom query result parsing function. Details below.

We’ll assume for the moment that your GraphQL server does have the same schema as WPGraphQL and move on.

First install ‘next-graphql-static-export’:

Now create a new config-exports.js file in the root directory of your project, where we will configure the parameters that we pass to the processContent made available via the next-graphql-static-export library. The following is an example of sensible defaults:

Open up your package.json again, and add change the line pertaining to the dev script to the following:

This EXPORT env var will allow us to continue to use npm run dev to develop our site, yet avoid doing a full static HTML export every time we change a line of code (see next step for where we use this env var).

Open up your next.config.js again, and make it look similar to the following:

Now go ahead and run the following again:

Open up localhost:8080 and you should see your beautiful site with all dynamic page fully rendered and served as static HTML!

Passing your own query result parsing function

If your schema differs from the one shown above, then you will need to pass your own query result parsing function to your typeParams in your config-export.js file. Here is an example function which exactly reproduces the existing functionality:

Note that the function takes in the queryResponse, and the current contentType, both of which are used to destructure the query result and return the following required values: nodes, hasNextPage, endCursor.

You can use any amount of logic in this function, but those values are required.

To use this function in your implementation, simply add the function as a parameter to the relevant content types. So our new config-exports.js would look like this:

And that’s all there is to adapting this module to a different schema than the one natively expected. Feel free to reach out with any questions.