next-graphql-static-export
v1.1.8
Published
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
Downloads
69
Maintainers
Readme
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.
Documentation
About this package
It is suggested that you begin by reading about Next.js Static HTML Exports. Upon doing so you will quickly realize that dynamic exports will require additional work.
This package should help you get up an running with minimal configuration, assuming you use GraphQL as a data source. The package is an early work in progress, and contributors / feedback are definitely welcome.
Usage
Create a config file in your Next.js project. If you already have a config.js
that you use for ES6 exports imports within your Next.js project, you'll want to create a separate config-export.js
for this purpose, as the next.config.js
does not support import
s.
In your config file, add something similar to the following information in your config
file:
const postsQuery = require("./queries/posts-query");
const pagesQuery = require("./queries/pages-query");
const productsQuery = require("./queries/products-query");
const endpoint = `https://www.website.com/graphql`;
const typeParams = [
{
pageComponent: "page",
contentType: "pages",
query: pagesQuery,
urlBase: "pages",
perPage: 100,
endpoint
},
{
pageComponent: "article",
contentType: "posts",
query: postsQuery,
urlBase: "articles",
perPage: 100,
endpoint
},
{
pageComponent: "product",
contentType: "products",
query: productsQuery,
urlBase: "products",
perPage: 100,
endpoint
}
];
module.exports = {
typeParams
};
With the lines below we require the files containing the GraphQL files we'll use to pull the data we need to populate our dynamic pages upon static export. For example in postsQuery.js
:
module.exports = `
query GET_POSTS($first:Int $after:String){
posts(
first: $first
after:$after
where: { status:PUBLISH }
) {
pageInfo {
endCursor
hasNextPage
}
nodes {
id
uri
title
}
}
}
`;
Here we simply establish the location of our GraphQL endpoint:
const endpoint = `https://www.website.com/graphql`;
Next we setup the parameters of the content types we pass to the application. The objects in the typeParams
array are the parameters that describe the data we want to pull (via the query
) and the way the data should be structured for output to the Next.js exportPathMap
function.
pageComponent
is the component in ./pages
in our Next.js project that this object should relate to. contentTypes
is interpolated within this library's fetchPosts
function to destructure data from the response. A future version of this library (PRs welcome) could take a function as input to perform the destructuring of the response from the query.
query
is the GraphQL query we pass to this library.
urlBase
is the base of the eventual URL created by the Next.js export process, i.e. the URL where our static HTML exports for this content type should live.
perPage
will determine how many pieces of content per page this library will pull
endpoint
is the GraphQL endpoint to query.
parseQueryResults
(optional) is a custom query result parsing function we can pass along with typeParams
to allow for schemas which vary from the built-in "standard" assumption. This function takes in the query response and content type, and returns an object containing nodes
, hasNextPage
, and endCursor
. Your custom parsing function can take any route you like to arriving at those values, but they are required.
// An example of the optional query result parsing function. This example just reimplements the standard used by the library.
const parseQueryResults = (input, contentType) => {
const {
[contentType]: {
nodes,
pageInfo: { hasNextPage, endCursor }
}
} = input;
return { nodes, hasNextPage, endCursor };
};
const typeParams = [
{
pageComponent: "page",
contentType: "pages",
query: pagesQuery,
urlBase: "pages",
perPage: 100,
endpoint,
parseQueryResults // optional
},
{
pageComponent: "article",
contentType: "posts",
query: postsQuery,
urlBase: "articles",
perPage: 100,
endpoint
},
{
pageComponent: "product",
contentType: "products",
query: productsQuery,
urlBase: "products",
perPage: 100,
endpoint
}
];
module.exports = {
typeParams
};
Note that we can have different endpoint
s and parseQueryResults
for each content type.
Next, import this config in to next.config.js
, and add the following to your exportPathMap function:
const processContent = require("next-graphql-static-export");
const { typeParams } = require("./config-export");
exportPathMap: async function() {
// We don't want to do all of this export work if were just developing another part of the app.
// But we don't want to hook this to NODE_ENV=dev, because we might be developing
// but still want to evaluate the export, thus a new env var
if (process.env.EXPORT === "false") return {};
// Create our static export data
const [pages, products, posts] = await processContent(typeParams);
// Create the static pages with Next
return {
"/": { page: "/" },
...pages,
...products
...posts
};
}
To Do
- Replace
perPage
with a general purposefilter
, so as to not assume the schema of the GraphQL endpoint to be hit.
Credits
Hat tip to @jasonbahl for the inspiration for the orignal fetchPosts
function.
NPM
https://www.npmjs.com/package/next-graphql-static-export
Pull Requests
PRs welcome.