Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

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

Tags:

gatsby

netlify

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

I've tried removing the 404 page but the same error appears on the next page in the list.

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;

This is the error from Netlify

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
like image 419
notbrian Avatar asked Sep 03 '19 18:09

notbrian


1 Answers

Short answer: Gatsby pre-renders components on build to serve them statically (mimics Server-side Rendering). Be sure to access browser context variables, such as document, only when your component is mounted (client-side). You can use a combination of useState and useEffect hooks to achieve this.

Gatsby is trying to build your page to serve it statically but it lacks of the document global variable on build time, which is only available in browser context.

In your case, I think the problem may be triggered by the AniLink component at build time, as it uses the document variable, as you can see here. Try to delay the instantiation of your AniLink or parent component.

For example:

const ErrorPage = () => {
  const [canRender, setCanRender] = useState(false);

  useEffect(() => setCanRender(true));

  return (
    <Container>
      {
        canRender ?
          <div>
            <Heading>Page Not Found</Heading>
            <HomeButton fade to="/">
              Go Back to Home
            </HomeButton>
          </div>
        : null
    }
    </Container>
  );
}

Also, If you need to use the document browser context variable within a component that is being statically rendered, you can replace it with react hooks to avoid issues at build time.

For instance, if you have something like this:

const Page = () => {
  return (
    <div>
      { 
        document.querySelector('nav')
          ? `This is page has a nav tag`
          : `This page doesn't have a nav tag` 
      }
    </div>
  );
}

You can solve your issue with these changes:

const Page = () => 

  const [hasNavTag, setHasNavTag] = useState(false);

  useEffect(() => setHasNavTag(document.querySelector('nav') != null) );

  return (
    <div>
      { 
        hasNavTag
          ? `This is page has a nav tag`
          : `This page doesn't have a nav tag` 
      }
    </div>
  );
}

Better late than never :)

like image 139
Ary Pablo Batista Avatar answered Nov 24 '22 00:11

Ary Pablo Batista