3
votes

I am working on a Gatsby based website which is so far going well in development. Running into an issue though when building for production whereby we do not get any static html in the various page index files and instead it looks like Gatsby is going to attempt to inject the page from javascript which is contra to our expectation.

I have seen some posts related to the Gatsby offline plugin which I have disabled but this has not resolved the issue. Our pages contain no static html output and the meta content I would expect react-helmet to inject is also not present.

Are there any recommendations on how to debug the build to see what may be resetting the static output and replacing it with dynamically generated Gatsby bootstrap code.

Plugins being used for the site are:

 plugins: [
    `gatsby-plugin-react-helmet`,
    `gatsby-transformer-sharp`,
    `gatsby-plugin-sharp`,
    {
      resolve: `gatsby-plugin-manifest`,
      options: {
        name: `gatsby-starter-default`,
        short_name: `starter`,
        start_url: `/`,
        background_color: `#663399`,
        theme_color: `#663399`,
        display: `minimal-ui`,
        icon: `src/images/favicon.png`, // This path is relative to the root of the site.
      },
    },
    `gatsby-transformer-json`,
    {
      resolve: `gatsby-source-filesystem`,
      options: {
        name: 'data',
        path: `${__dirname}/src/data/`,
      },
    },
    {
      resolve: `gatsby-source-filesystem`,
      options: {
        name: `images`,
        path: `${__dirname}/src/images`,
      },
    },
    `gatsby-plugin-styled-components`,
    // this (optional) plugin enables Progressive Web App + Offline functionality
    // To learn more, visit: https://gatsby.dev/offline
    //`gatsby-plugin-offline`,
    {
      resolve: 'gatsby-plugin-root-import',
      options: {
        src: path.join(__dirname, 'src'),
        pages: path.join(__dirname, 'src/pages'),
        images: path.join(__dirname, 'src/images'),
      },
    },
    `gatsby-plugin-transition-link`,
    {
      resolve: `gatsby-plugin-google-analytics`,
      options: {
        trackingId: process.env.GOOGLE_ANALYTICS_TRACKING_ID,
        head: true,
      },
    },
  ]

Thanks in advance for any pointers

2
Are you able to expand on contra to our expectation?ksav
Gatsby should be generating a static version of pages. For example, if I have an about page which will render as <h1>About</h1><p>a bunch of content</p> then that raw markup should be present in the associated /about/index.html file when I run a Gatsby build. This is not happening, the only html element in the build generated file is a top level <div id="___gatsby">In addition, none of the SEO meta content we expect to be injected by react helmet is present.Andrew Rutter
Did you gatsby clean + gatsby build + gatsby serve? gatsby develop does not always create all the parts of the page that you would see with gatsby build. If you do not see the React helmet meta tags I believe something is configured wrong. I see them in my project when I gatsby build.EliteRaceElephant
Thats the crux of our issue, Gatsby build is not generating pages which include static html or meta tags. The site works in develop and even from Gatsby serve but does not have fully hydrated pages that we need for SEO and we cannot determine the break in the installed plugins or configurationAndrew Rutter
Having the same problem. Did you discover anything?Maurício Araldi

2 Answers

3
votes

Had the same problem.

It appears that PersistGate breaks ssr. Since ssr is done during build time and we don't need it there, we can check our environment.

Changing wrap-with-provider.js from 1. to 2. did the trick

import React from "react"
import { Provider } from "react-redux"
import { PersistGate } from 'redux-persist/integration/react'

import {store, persistor} from "./src/redux/store"

1:

export default ({ element }) => (
  <Provider store={store}>
    <PersistGate loading={null} persistor={persistor}>
      {element}
    </PersistGate>
  </Provider>
)

2:

export default ({ element }) => {
  if (typeof window === "undefined") {
    return (
      <Provider store={store}>
        {element}
      </Provider>
    )
  }
  return (
    <Provider store={store}>
      <PersistGate loading={null} persistor={persistor}>
        {element}
      </PersistGate>
    </Provider>
  )
}
2
votes

I managed to track the issue down to a conflict between Redux (redux-persist) and Gatsby SSR - specifically related to the use of a PersistGate element. The following is a pretty common pattern where you have the following in gatsby-browser and gatsby-ssr

export { default as wrapRootElement } from 'src/store/ReduxWrapper';

Which ReduxWrapper would contain the following:

export default ({ element }) => (
  <Provider store={store}>
    <PersistGate loading={<h2>Loading...</h2>} persistor={persistor}>
      {element}
    </PersistGate>
  </Provider>
);

This unfortunately breaks SSR which can be resolved by creating a different ReduxWrapper that does not depend on . Assuming this is called ReduxSSRWrapper then gatsby-ssr will be changed to:

export { default as wrapRootElement } from 'src/store/ReduxSSRWrapper';

and ReduxSSRWrapper will contain the following which is basically a removal of PersistGate:

export default ({ element }) => (
  <Provider store={store}>
    {element}
  </Provider>
);