Page HTML Generation
This documentation isn’t up to date with the latest version of Gatsby.
Outdated areas are:
- replace mentions of
You can help by making a PR to update this documentation.
The high level process is:
- Create a webpack configuration for Node.js Server Side Rendering (SSR)
- Build a
render-page.jsthat takes a page path and renders its HTML
- For each page in Redux, call
For the first step, we use webpack to build an optimized Node.js bundle. The entry point for this is called
static-entry.js exports a function that takes a path and returns rendered HTML. Here’s what it does to create that HTML:
- Require page, json, and webpack chunk data sources
- Create HTML React Container
- Load Page and Data
- Create Page Component
- Add Preload Link and Script Tags
- Inject Page Info to CDATA
- Render Final HTML Document
In order to perform the rest of the operations, we need some data sources to work off. These are:
components which is a map of componentChunkName to require statements for the disk location of the component. See Write Out Pages.
Contains all the pages (with componentChunkName, jsonName, and path) and the dataPaths which map jsonName to dataPath. See Write Out Pages for more.
Contains a mapping from componentChunkName to the webpack chunks comprising it. See Code Splitting for more.
Contains a mapping from componentChunkName to their core (non-shared) chunks. See Code Splitting for more.
We create an
html React component that will eventually be rendered to a file. It will have props for each section (e.g.
postBodyComponents). This is owned by default-html.js.
The only input to
static-entry.js is a path. So we must look up the page for that path in order to find its
jsonName. This is achieved by looking up the pages array contained in
data.json. We can then load its data by looking it up in
Now we’re ready to create a React component for the page (inside the HTML container). This is handled by RouteHandler. Its render will create an element from the component in
This is covered by the Code Splitting docs. We essentially create a
<link rel="preload" href="component.js"> in the document head, and a follow-up
<script src="component.js"> at the end of the document. For each component and page JSON.
The production-app.js needs to know the page that it’s rendering. The way we pass this information is by setting it in CDATA during HTML generation, since we know that page at this point. So we add the following to the top of the HTML document:
Finally, we call react-dom and render our top level HTML component to a string and return it.
So, we’ve built the means to generate HTML for a page. These webpack bundles are saved to
.cache/page-ssr/routes. Next, we need to use it to generate HTML for all the site’s pages.
Page HTML does not depend on other pages. So we can perform this step in parallel. We use the jest-worker library to make this easier. By default, the render-html.ts creates a pool of workers equal to the number of physical cores on your machine. You can configure the number of pools by passing an optional environment variable,
GATSBY_CPU_COUNT. It then partitions the pages into groups and sends them to the workers, which run worker.
The workers iterate over each page in their partition, and call the
render-page.js with the page. It then saves the HTML for the page’s path in
Once all workers have finished, we’re done!