Gatsby: Gatsby build error "document is not defined" only on Netlify

Created on 29 Aug 2019  Â·  8Comments  Â·  Source: gatsbyjs/gatsby

Summary

I'm getting a document is not defined build error on my 404 page when I build on Netlify but the build runs successfully locally. I'm not referencing any document or window object in my page either.

Relevant information

This is the error from the Netlify log

2:20:59 PM: success Generating image thumbnails — 850/850 - 162.737 s
2:21:07 PM: error #95313 ReferenceError: document is not defined
2:21:07 PM: Building static HTML failed for path "/404/"
2:21:07 PM: See our docs page for more info on this error: https://gatsby.dev/debug-html
2:21:07 PM: 
2:21:07 PM:   ReferenceError: document is not defined
2:21:07 PM:   
2:21:07 PM:   - render-page.js:21018 Object
2:21:07 PM:     /opt/build/repo/public/render-page.js:21018:21
2:21:07 PM:   
2:21:07 PM:   - react-dom-server.node.production.min.js:26 ya
2:21:07 PM:     [repo]/[react-dom]/cjs/react-dom-server.node.production.min.js:26:264
2:21:07 PM:   
2:21:07 PM:   - react-dom-server.node.production.min.js:29 Object.useState
2:21:07 PM:     [repo]/[react-dom]/cjs/react-dom-server.node.production.min.js:29:82
2:21:07 PM:   
2:21:07 PM:   - react.production.min.js:23 useState
2:21:07 PM:     [repo]/[react]/cjs/react.production.min.js:23:312
2:21:07 PM:   
2:21:07 PM:   - render-page.js:21017 ./node_modules/react-three-fiber/dist/index.js.Object
2:21:07 PM:     /opt/build/repo/public/render-page.js:21017:76
2:21:07 PM:   
2:21:07 PM:   - react-dom-server.node.production.min.js:33 c
2:21:07 PM:     [repo]/[react-dom]/cjs/react-dom-server.node.production.min.js:33:501
2:21:07 PM:   
2:21:07 PM:   - react-dom-server.node.production.min.js:36 Sa
2:21:07 PM:     [repo]/[react-dom]/cjs/react-dom-server.node.production.min.js:36:1
2:21:07 PM:   
2:21:07 PM:   - react-dom-server.node.production.min.js:41 a.render
2:21:07 PM:     [repo]/[react-dom]/cjs/react-dom-server.node.production.min.js:41:467
2:21:07 PM:   
2:21:07 PM:   - react-dom-server.node.production.min.js:41 a.read
2:21:07 PM:     [repo]/[react-dom]/cjs/react-dom-server.node.production.min.js:41:58
2:21:07 PM:   
2:21:07 PM:   - react-dom-server.node.production.min.js:53 renderToString
2:21:07 PM:     [repo]/[react-dom]/cjs/react-dom-server.node.production.min.js:53:83
2:21:07 PM:   
2:21:07 PM:   - render-page.js:563 Module../.cache/static-entry.js.__webpack_exports__.defau    lt
2:21:07 PM:     /opt/build/repo/public/render-page.js:563:28
2:21:07 PM:   
2:21:07 PM:   - render-html.js:35 Promise
2:21:07 PM:     [repo]/[gatsby]/dist/utils/worker/render-html.js:35:36
2:21:07 PM:   
2:21:07 PM:   - debuggability.js:313 Promise._execute
2:21:07 PM:     [repo]/[bluebird]/js/release/debuggability.js:313:9
2:21:07 PM:   
2:21:07 PM:   - promise.js:488 Promise._resolveFromExecutor
2:21:07 PM:     [repo]/[bluebird]/js/release/promise.js:488:18
2:21:07 PM:   
2:21:07 PM:   - promise.js:79 new Promise
2:21:07 PM:     [repo]/[bluebird]/js/release/promise.js:79:10
2:21:07 PM:   
2:21:07 PM:   - render-html.js:31 Promise.map.path
2:21:07 PM:     [repo]/[gatsby]/dist/utils/worker/render-html.js:31:37
2:21:07 PM:   
2:21:07 PM: 
2:21:07 PM: Skipping functions preparation step: no functions directory set`

And this is my 404 page

import React from "react";
import styled from "styled-components";
import AniLink from "gatsby-plugin-transition-link/AniLink";

const Container = styled.div`
  width: 100vw;
  height: 100vh;
  margin: 0;
  padding: 0;
  background: black;
  display: flex;
  flex-direction: column;
  justify-content: center;
  align-items: center;
  z-index: 800;
  color: white;
`;

const Heading = styled.h1`
  font-family: "URWAccidalia";
  font-size: 50px;
  color: white;
  text-align: center;
  z-index: 805;
`;

const HomeButton = styled(AniLink)`
  font-family: "URWAccidalia";
  font-size: 30px;
  color: white;
  text-align: center;
  margin-top: 50px;
  z-index: 806;
  background: none;
  border: none;
  text-decoration: none;
  opacity: 1;
`;

const ErrorPage = () => {
  return (
    <Container>
      <Heading>Page Not Found</Heading>
      <HomeButton fade to="/">
        Go Back to Home
      </HomeButton>
    </Container>
  );
};

export default ErrorPage;

File contents (if changed)

gatsby-config.js: N/A
package.json: N/A
gatsby-node.js: N/A
gatsby-browser.js: N/A
gatsby-ssr.js: N/A

question or discussion

Most helpful comment

@notbrian here are the steps that i took to triage and possibly solve your issue.

  • Created a new gatsby site based on the hello world starter.
  • Added the necessary dependencies, transforming my package.json into the following:
"dependencies": {
    "babel-plugin-styled-components": "^1.10.6",
    "gatsby": "^2.15.6",
    "gatsby-plugin-styled-components": "^3.1.4",
    "gatsby-plugin-transition-link": "^1.12.4",
    "gsap": "^2.1.3",
    "react": "^16.9.0",
    "react-dom": "^16.9.0",
    "styled-components": "^4.3.2",
  },
  "devDependencies": {
    "prettier": "^1.18.2"
  },

I've only left in the dependencies and devdependencies for brevity purposes.

  • Created a page called 404.js with the following code:
import React from "react";
import styled from "styled-components";
import AniLink from "gatsby-plugin-transition-link/AniLink";

const Container = styled.div`
  width: 100vw;
  height: 100vh;
  margin: 0;
  padding: 0;
  background: black;
  display: flex;
  flex-direction: column;
  justify-content: center;
  align-items: center;
  z-index: 800;
  color: white;
`;

const Heading = styled.h1`
  font-family: "URWAccidalia";
  font-size: 50px;
  color: white;
  text-align: center;
  z-index: 805;
`;

const HomeButton = styled(AniLink)`
  font-family: "URWAccidalia";
  font-size: 30px;
  color: white;
  text-align: center;
  margin-top: 50px;
  z-index: 806;
  background: none;
  border: none;
  text-decoration: none;
  opacity: 1;
`;

const ErrorPage = () => {
  return (
    <Container>
      <Heading>Page Not Found</Heading>
      <HomeButton fade to="/">
        Go Back to Home
      </HomeButton>
    </Container>
  );
};

export default ErrorPage;

-Issued gatsby build && gatsby serve and i'm presented with the following:
not_brian1

  • I was able to see the transitions working as they should by opening up a browser window to http://localhost:9000 and opening up for instance http://localhost:9000/banana (this page does not exist).
  • Based on your latest comment, i updated the dependencies to include react-three-fiber, three and react-loadable. The first two are based on your information and the third is a safeguard/workaround to make some components to work with gatsby, until suspense works correctly with ssr(server side rendering). You can read more about the react-loadable package here.
  • I looked up the react-three-fiber repository and grabbed one of the examples.
  • With the above in mind, i created a new component called Thing.js under ./src/components with the following code:
import React from 'react'
import * as THREE from 'three'
import {Canvas} from 'react-three-fiber'

const Thing=({ vertices = [[-1, 0, 0], [0, 1, 0], [1, 0, 0], [0, -1, 0], [-1, 0, 0]] })=>{
    return (
        <Canvas>
            <group>
                <line>
                    <geometry attach="geometry"
                    vertices={vertices.map(v=>new THREE.Vector3(...v))}
                    onUpdate={self=>(self.verticesNeedUpdate=true)}/>

                    <lineBasicMaterial attach="material" color="black"/>
                </line>
                <mesh>
                    <octahedronGeometry attach="geometry" />
                    <meshBasicMaterial attach="material" color="peachpuff" opacity={0.5} transparent/>
                </mesh>
            </group>
        </Canvas>
    )
}

export default Thing

  • Created a new page called page3.js under src/pages with the following code:
import React from "react"
import Loadable from "react-loadable"
import styled from "styled-components"
import AniLink from "gatsby-plugin-transition-link/AniLink"
// component to show something to the user while the actual component is loaded on the client side
const loader = () => <div>Loading threejs...</div>
//
// a component that will be defered to be rendered only on client side.
const MyLoadableThreejs = Loadable({
  loader: () => import("../components/Thing.js"), // imports the component with the three.js and allows use of it safely
  loading: loader,
})
//
const Container = styled.div`
  width: 100vw;
  height: 100vh;
  margin: 0;
  padding: 0;
  background: black;
  display: flex;
  flex-direction: column;
  justify-content: center;
  align-items: center;
  z-index: 800;
  color: white;
`

const Heading = styled.h1`
  font-family: "URWAccidalia";
  font-size: 50px;
  color: white;
  text-align: center;
  z-index: 805;
`

const HomeButton = styled(AniLink)`
  font-family: "URWAccidalia";
  font-size: 30px;
  color: white;
  text-align: center;
  margin-top: 50px;
  z-index: 806;
  background: none;
  border: none;
  text-decoration: none;
  opacity: 1;
`
export default () => (
  <Container>
    <Heading>This is a page with three js</Heading>
    <MyLoadableThreejs/>
    <HomeButton fade to="/">
      Go to a diferent page
    </HomeButton>
  </Container>
)

Basically what is happening here is this, the component that uses three.js and react-three-fiber render will be defered to the client side, when the client/user visits the page. When you visit the page with the component you'll probably see the text first and then the actual component.

  • Issued gatsby build && gatsby serve and no errors were generated.
  • Pushed the code to this repo and hooked it to netlify and waited for it to build and i'm presented with the following:
    not_brian2

A live version of the site is here.

Feel free to provide feedback so that we can close this issue and also #17396, or continue to work on it until we find a suitable solution.
Also @jevinsidhu see if this explanation and the code works on your case and provide feedback aswell.

All 8 comments

Still can't figure this problem out either

@jevinsidhu and @notbrian i'm going to try and create a reproduction based on the information and see what i can come up with and possibly offer a solution/workaround. Do you mind waiting a bit?

@jevinsidhu and @notbrian i'm going to try and create a reproduction based on the information and see what i can come up with and possibly offer a solution/workaround. Do you mind waiting a bit?

No problem, thanks!

@jevinsidhu and @notbrian i'm going to try and create a reproduction based on the information and see what i can come up with and possibly offer a solution/workaround. Do you mind waiting a bit?

For sure! Thanks :) @jonniebigodes

@jonniebigodes I updated my Node and all my packages and now it's erroring locally with the same error.

I can view the stack trace and can see that the error is being caused by three.js I believe.

  const _useState5 = Object(react__WEBPACK_IMPORTED_MODULE_3__["useState"])(() => {
    const element = document.createElementNS('http://www.w3.org/1999/xhtml', 'canvas');
    element.style.display = 'block';
    return element;
  }),
        defaultCanvas = _useState5[0];

@notbrian here are the steps that i took to triage and possibly solve your issue.

  • Created a new gatsby site based on the hello world starter.
  • Added the necessary dependencies, transforming my package.json into the following:
"dependencies": {
    "babel-plugin-styled-components": "^1.10.6",
    "gatsby": "^2.15.6",
    "gatsby-plugin-styled-components": "^3.1.4",
    "gatsby-plugin-transition-link": "^1.12.4",
    "gsap": "^2.1.3",
    "react": "^16.9.0",
    "react-dom": "^16.9.0",
    "styled-components": "^4.3.2",
  },
  "devDependencies": {
    "prettier": "^1.18.2"
  },

I've only left in the dependencies and devdependencies for brevity purposes.

  • Created a page called 404.js with the following code:
import React from "react";
import styled from "styled-components";
import AniLink from "gatsby-plugin-transition-link/AniLink";

const Container = styled.div`
  width: 100vw;
  height: 100vh;
  margin: 0;
  padding: 0;
  background: black;
  display: flex;
  flex-direction: column;
  justify-content: center;
  align-items: center;
  z-index: 800;
  color: white;
`;

const Heading = styled.h1`
  font-family: "URWAccidalia";
  font-size: 50px;
  color: white;
  text-align: center;
  z-index: 805;
`;

const HomeButton = styled(AniLink)`
  font-family: "URWAccidalia";
  font-size: 30px;
  color: white;
  text-align: center;
  margin-top: 50px;
  z-index: 806;
  background: none;
  border: none;
  text-decoration: none;
  opacity: 1;
`;

const ErrorPage = () => {
  return (
    <Container>
      <Heading>Page Not Found</Heading>
      <HomeButton fade to="/">
        Go Back to Home
      </HomeButton>
    </Container>
  );
};

export default ErrorPage;

-Issued gatsby build && gatsby serve and i'm presented with the following:
not_brian1

  • I was able to see the transitions working as they should by opening up a browser window to http://localhost:9000 and opening up for instance http://localhost:9000/banana (this page does not exist).
  • Based on your latest comment, i updated the dependencies to include react-three-fiber, three and react-loadable. The first two are based on your information and the third is a safeguard/workaround to make some components to work with gatsby, until suspense works correctly with ssr(server side rendering). You can read more about the react-loadable package here.
  • I looked up the react-three-fiber repository and grabbed one of the examples.
  • With the above in mind, i created a new component called Thing.js under ./src/components with the following code:
import React from 'react'
import * as THREE from 'three'
import {Canvas} from 'react-three-fiber'

const Thing=({ vertices = [[-1, 0, 0], [0, 1, 0], [1, 0, 0], [0, -1, 0], [-1, 0, 0]] })=>{
    return (
        <Canvas>
            <group>
                <line>
                    <geometry attach="geometry"
                    vertices={vertices.map(v=>new THREE.Vector3(...v))}
                    onUpdate={self=>(self.verticesNeedUpdate=true)}/>

                    <lineBasicMaterial attach="material" color="black"/>
                </line>
                <mesh>
                    <octahedronGeometry attach="geometry" />
                    <meshBasicMaterial attach="material" color="peachpuff" opacity={0.5} transparent/>
                </mesh>
            </group>
        </Canvas>
    )
}

export default Thing

  • Created a new page called page3.js under src/pages with the following code:
import React from "react"
import Loadable from "react-loadable"
import styled from "styled-components"
import AniLink from "gatsby-plugin-transition-link/AniLink"
// component to show something to the user while the actual component is loaded on the client side
const loader = () => <div>Loading threejs...</div>
//
// a component that will be defered to be rendered only on client side.
const MyLoadableThreejs = Loadable({
  loader: () => import("../components/Thing.js"), // imports the component with the three.js and allows use of it safely
  loading: loader,
})
//
const Container = styled.div`
  width: 100vw;
  height: 100vh;
  margin: 0;
  padding: 0;
  background: black;
  display: flex;
  flex-direction: column;
  justify-content: center;
  align-items: center;
  z-index: 800;
  color: white;
`

const Heading = styled.h1`
  font-family: "URWAccidalia";
  font-size: 50px;
  color: white;
  text-align: center;
  z-index: 805;
`

const HomeButton = styled(AniLink)`
  font-family: "URWAccidalia";
  font-size: 30px;
  color: white;
  text-align: center;
  margin-top: 50px;
  z-index: 806;
  background: none;
  border: none;
  text-decoration: none;
  opacity: 1;
`
export default () => (
  <Container>
    <Heading>This is a page with three js</Heading>
    <MyLoadableThreejs/>
    <HomeButton fade to="/">
      Go to a diferent page
    </HomeButton>
  </Container>
)

Basically what is happening here is this, the component that uses three.js and react-three-fiber render will be defered to the client side, when the client/user visits the page. When you visit the page with the component you'll probably see the text first and then the actual component.

  • Issued gatsby build && gatsby serve and no errors were generated.
  • Pushed the code to this repo and hooked it to netlify and waited for it to build and i'm presented with the following:
    not_brian2

A live version of the site is here.

Feel free to provide feedback so that we can close this issue and also #17396, or continue to work on it until we find a suitable solution.
Also @jevinsidhu see if this explanation and the code works on your case and provide feedback aswell.

For reference, here is also a working react-three-fiber / Canvas component: https://github.com/LekoArts/gatsby-themes/blob/master/www/src/components/3d-model.tsx

Hey @jonniebigodes @LekoArts, I rewrote my components to use react-loadable and everything seems to be working perfectly so far! Thanks so much for your help!

Was this page helpful?
0 / 5 - 0 ratings

Related issues

KyleAMathews picture KyleAMathews  Â·  3Comments

magicly picture magicly  Â·  3Comments

timbrandin picture timbrandin  Â·  3Comments

brandonmp picture brandonmp  Â·  3Comments

kalinchernev picture kalinchernev  Â·  3Comments