Skip to content

Commit

Permalink
Support Next.js static HTML export.
Browse files Browse the repository at this point in the history
Fixes #4 .
  • Loading branch information
jaydenseric committed May 3, 2020
1 parent 9755552 commit bf107b8
Show file tree
Hide file tree
Showing 2 changed files with 73 additions and 45 deletions.
1 change: 1 addition & 0 deletions changelog.md
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@
- Reorder Babel config fields.
- Ensure GitHub Actions run on pull request.
- Also run GitHub Actions with Node.js v14.
- Support Next.js static HTML export, fixing [#4](https://github.com/jaydenseric/next-graphql-react/issues/4).

## 6.0.1

Expand Down
117 changes: 72 additions & 45 deletions src/universal/withGraphQLApp.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,6 @@

const GraphQL = require('graphql-react/universal/GraphQL.js');
const { default: NextApp } = require('next/app');
const { default: Head } = require('next/head');
const React = require('react');

/**
Expand Down Expand Up @@ -109,57 +108,85 @@ module.exports = function withGraphQLApp(App) {
? App.getInitialProps(context)
: NextApp.getInitialProps(context)
).then((props) => {
// Next.js webpack config uses process.browser to eliminate code from
// the relevant server/browser bundle.
// Next.js webpack config uses `process.browser` to eliminate code
// from the relevant server/browser bundle.
if (process.browser) resolve(props);
else
Promise.all([
import('http-link-header'),
import('graphql-react/server/ssr.js'),
]).then(([{ default: LinkHeader }, { default: ssr }]) => {
const graphql = new GraphQL();
const graphqlLinkHeader = new LinkHeader();
else {
const graphql = new GraphQL();

graphql.on('cache', ({ response }) => {
// The response may be undefined if there were fetch errors.
if (response) {
const linkHeader = response.headers.get('Link');
if (linkHeader) graphqlLinkHeader.parse(linkHeader);
}
});
// Check if this is a Next.js static HTML export. If it is, Next.js
// docs say `ctx.res` will be an empty object, although in reality a
// few header related properties are mimicked. That is why
// `statusCode` is checked here instead of something more relevant.
// See: https://nextjs.org/docs/advanced-features/static-html-export#caveats
if (context.ctx.res.statusCode)
Promise.all([
import('graphql-react/server/ssr.js'),
import('http-link-header'),
import('next/head'),
]).then(
([
{ default: ssr },
{ default: LinkHeader },
{ default: Head },
]) => {
const graphqlLinkHeader = new LinkHeader();

ssr(graphql, <context.AppTree {...props} graphql={graphql} />)
.catch(console.error)
.then(() => {
Head.rewind();
graphql.on('cache', ({ response }) => {
// The response may be undefined if there were fetch errors.
if (response) {
const linkHeader = response.headers.get('Link');
if (linkHeader) graphqlLinkHeader.parse(linkHeader);
}
});

const responseLinkHeader = new LinkHeader(
// Might be undefined.
context.ctx.res.getHeader('Link')
);
ssr(graphql, <context.AppTree {...props} graphql={graphql} />)
.catch(console.error)
.then(() => {
Head.rewind();

graphqlLinkHeader.refs.forEach((graphqlLink) => {
if (
FORWARDABLE_LINK_REL.includes(graphqlLink.rel) &&
// Similar link not already set.
!responseLinkHeader.refs.some(
({ uri, rel }) =>
uri === graphqlLink.uri && rel === graphqlLink.rel
)
)
responseLinkHeader.set(graphqlLink);
});
const responseLinkHeader = new LinkHeader(
// Might be undefined.
context.ctx.res.getHeader('Link')
);

if (responseLinkHeader.refs.length)
context.ctx.res.setHeader(
'Link',
responseLinkHeader.toString()
);
graphqlLinkHeader.refs.forEach((graphqlLink) => {
if (
FORWARDABLE_LINK_REL.includes(graphqlLink.rel) &&
// Similar link not already set.
!responseLinkHeader.refs.some(
({ uri, rel }) =>
uri === graphqlLink.uri && rel === graphqlLink.rel
)
)
responseLinkHeader.set(graphqlLink);
});

props.graphqlCache = graphql.cache;
resolve(props);
});
});
if (responseLinkHeader.refs.length)
context.ctx.res.setHeader(
'Link',
responseLinkHeader.toString()
);

props.graphqlCache = graphql.cache;
resolve(props);
});
}
);
else
Promise.all([
import('graphql-react/server/ssr.js'),
import('next/head'),
]).then(([{ default: ssr }, { default: Head }]) => {
ssr(graphql, <context.AppTree {...props} graphql={graphql} />)
.catch(console.error)
.then(() => {
Head.rewind();
props.graphqlCache = graphql.cache;
resolve(props);
});
});
}
});
});

Expand Down

0 comments on commit bf107b8

Please sign in to comment.