如何修复Gatsby开发中出现window is not defined报错的问题
问题原因
Gatsby的服务端渲染(SSR)和构建阶段运行在Node.js环境中,该环境不存在window、document等浏览器专属的全局对象。你的代码中直接访问window.location.pathname,服务端执行时就会抛出ReferenceError: window is not defined报错。
解决方案
你可以根据实际使用场景选择以下任意一种方案:
- 方案1:执行前判断window是否存在
改动最小,适合函数直接调用的场景,修改后的代码如下:const activeIndex = () => { // SSR阶段直接返回默认值,客户端执行时才走正常计算逻辑 if (typeof window === 'undefined') return false const found = routes.indexOf( routes.filter( ({ node: { name, link } }) => (link || `/${name.toLowerCase()}`) === window.location.pathname )[0] ) return found === -1 ? false : found } - 方案2:将逻辑放到客户端生命周期中执行
如果该函数是在React组件内调用,更推荐把计算逻辑放到useEffect中,useEffect只会在客户端hydrate完成后执行,不会触发SSR报错,示例代码如下:import { useState, useEffect } from 'react' const YourComponent = () => { const [activeIndex, setActiveIndex] = useState(false) useEffect(() => { const found = routes.indexOf( routes.filter( ({ node: { name, link } }) => (link || `/${name.toLowerCase()}`) === window.location.pathname )[0] ) setActiveIndex(found === -1 ? false : found) }, [routes]) // 依赖项可根据实际业务调整 // 后续业务逻辑直接使用activeIndex变量即可 } - 方案3:禁用对应组件的SSR
如果组件内有大量依赖浏览器环境的逻辑,可以将组件设置为不参与SSR,仅在客户端加载执行:
首先安装@loadable/component,之后按如下方式导入组件:
后续直接使用import loadable from '@loadable/component' const ComponentWithWindowLogic = loadable(() => import('./ComponentWithWindowLogic'), { ssr: false })<ComponentWithWindowLogic />即可,组件内所有代码都不会在SSR阶段运行。
内容的提问来源于stack exchange,提问作者Drilon Sulejmani
相关产品推荐
相关产品推荐

