WebpackError: ReferenceError: document is not defined - netlify build

时间:2021-03-12 15:35:32

标签: reactjs build gatsby

我在 netlify 上构建我的项目时遇到错误(WebpackError: ReferenceError: document is not defined)。在开发中工作正常!

我看到可以用 JSDOM 解决这个问题,但我已经尝试过,但我无法做到。

    import React from "react";
    import "../css/DarkMode.css";
    
    const DarkMode = () => {
      let clickedClass = "clicked";
      const body = document.body;
      const lightTheme = "light";
      const darkTheme = "dark";
      let theme;
    
      if (localStorage) {
        theme = localStorage.getItem("theme");
      }
    
      if (theme === lightTheme || theme === darkTheme) {
        body.classList.add(theme);
      } else {
        body.classList.add(lightTheme);
      }
    
      const switchTheme = (e) => {
        if (theme === darkTheme) {
          body.classList.replace(darkTheme, lightTheme);
          e.target.classList.remove(clickedClass);
          localStorage.setItem("theme", "light");
          theme = lightTheme;
        } else {
          body.classList.replace(lightTheme, darkTheme);
          e.target.classList.add(clickedClass);
          localStorage.setItem("theme", "dark");
          theme = darkTheme;
        }
      };
    
      return (
        <button
          className={theme === "dark" ? clickedClass : ""}
          id="darkMode"
          className={"btnDarkMode"}
          onClick={(e) => switchTheme(e)}
        ></button>
      );
    };
    
    export default DarkMode;

2 个答案:

答案 0 :(得分:1)

你想实现主题切换完全错误。

  1. React 使用虚拟 DOM 而不是真正的 DOM。 (虚拟 DOM 是 HTML 树的对象版本) 这就是为什么在页面初始化之前没有定义文档的原因。如果您想获取文档,最好在 useEffect() 钩子中使用它。 (在页面初始化之后)
  2. 在您的情况下,您有很多选择来实现多主题,我建议您使用样式组件

答案 1 :(得分:1)

扩展@mirik999's answer

这与jsdom 本身无关。如前所述,使用 React,您正在创建和操作虚拟 DOM (vDOM),而使用您的代码段,您直接指向真实 DOM(document.body 等)。此外,这些操作会极大地降低代码/应用程序的性能,因为它们会给浏览器带来巨大的成本,这就是 React 如此之快的原因(除其他外)。

在 React 应用程序中操作真实 DOM 可能会导致严重的警告和警告,可能会阻止 hydration of React(按需刷新/重新呈现新内容)。

总结一下,您的代码在 gatsby develop 下而不是 gatsby build 下工作的事实是,因为 gatsby develop 由浏览器 where there are global objects (such as window or document) 处理。 gatsby build id 在 Node 服务器中编译,其中显然没有 windowdocument,因为它们甚至还没有被创建。

简单的解决方法是在这种情况下包装您的代码(您使用全局对象的地方):

if (typeof window !== `undefined`) { // or typeof document !== 'undefined'
  // your code that uses global objects here
}

但正如我所说,它可能会阻止 React 的水合作用。

要在 Gatsby 中添加主题,您有很多选择,例如使用插件 (gatsby-plugin-dark-mode) 或使用基于 React 的方法。

有用的资源: