5

When running gatsby build, I get the following error.

I know how to fix it (e.g. check typedef of window) but I cannot find that window usage? How can I know where is it ? I suspect a node module since I do not have many window references in my own code

Thanks a lot

failed Building static HTML for pages - 10.845s

 ERROR #95312 

"window" is not available during server side rendering.

See our docs page for more info on this error: https://gatsby.dev/debug-html





  WebpackError: ReferenceError: window is not defined
  
  - build-html.js:110 doBuildPages
    /[gatsby]/dist/commands/build-html.js:110:24
  
  - build-html.js:124 async buildHTML
    /[gatsby]/dist/commands/build-html.js:124:3
  
  - build.js:206 async build
    /[gatsby]/dist/commands/build.js:206:5
dowi
  • 1,005
  • 15
  • 30

4 Answers4

2

Remove your third party node packages one at a time to find the offending module. Then you will either need to fork that package and fix it so it doesnt use the window object or find an alternative package.

apena
  • 2,091
  • 12
  • 19
2

Thanks for all the other answers

I tried @Raz Ronen's answer but changing the globalObject made other issues like undefined localStorage.

I tried removing all the node modules but it didn't help.

Oddly, after removing the node modules the error changed and I could see the line! of the error. It was in Gatsby's own "navigate" method.

I have private routes in my app similar to what explained in the docs:

mport React from "react"
import { navigate } from "gatsby"
import { isLoggedIn } from "../services/auth"

const PrivateRoute = ({ component: Component, location, ...rest }) => {
  if (!isLoggedIn() && location.pathname !== `/app/login`) {
    navigate("/app/login")
    return null
  }

  return <Component {...rest} />
}

export default PrivateRoute

But, I had to put the navigate inside a useEffect hook in order to resolve the issue like this:

const PrivateRoute = ({ component: Component, location, ...rest }) => {
  const user = useContext(AuthenticationContext)
  useEffect(() => {
    checkLoginStatus()
  }, [])

  const checkLoginStatus = () => {
    if (!user && location.pathname !== `/login`) {
      navigate("/login")
    }
  }

  return <Component {...rest} />
}
dowi
  • 1,005
  • 15
  • 30
  • 1
    You could try leaving Gatsby out of the programatic navigation (it does extra things) here. Try using the `@reach/router` `useNavigate` method. It should be passed in as a prop called `navigate` but to be sure just import it: `import { useNavigate } from "@reach/router"` – apena Aug 08 '20 at 16:53
1

Maybe setting globalObject will help.

output: {
    globalObject: "this",
  }

The default of the globalObject is window.

Raz Ronen
  • 2,418
  • 2
  • 14
  • 26
1

As you said, if you are not using window in your code (the way to fix is checking if it's defined using typeof), the issue comes from one of your third-party dependencies that is using the window as a global object in their own code.

You have to find which one is and add a null loader in your webpack configuration. In your gatsby-node.js:

exports.onCreateWebpackConfig = ({ stage, loaders, actions }) => {
  if (stage === "build-html") {
    actions.setWebpackConfig({
      module: {
        rules: [
          {
            test: /bad-module/,
            use: loaders.null(),
          },
        ],
      },
    })
  }
}

In the code above, /bad-module/ is the dependency in node_modules that you want to avoid to transpile. Basically, you are replacing the offending module with a dummy module during server rendering.

Ferran Buireu
  • 28,630
  • 6
  • 39
  • 67