You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

React/Gatsby生产环境使用postscribe报window未定义如何解决

问题根因

你加的window !== undefined判断只覆盖了useEffect执行阶段的window访问,根本拦不住报错:Gatsby生产构建会在Node.js服务端渲染(SSR)环境执行模块的静态导入逻辑,而你在文件顶部写的import postscribe from 'postscribe'会在模块初始化阶段就加载postscribe库——这个库本身顶层代码就会直接访问window对象,Node环境没有这个对象,代码在导入阶段就直接抛错,根本等不到组件渲染、useEffect里的判断逻辑执行。
本地开发环境没报错是因为gatsby develop的SSR校验比生产构建宽松,不会提前触发这类第三方库的浏览器API访问,属于开发环境和生产环境行为不一致的典型场景。

修复方案

核心思路是把postscribe的加载逻辑完全挪到客户端侧,绕开SSR构建阶段,两种改动量很小的实现方式:

方案1:useEffect内动态导入(推荐)

删掉文件顶部对postscribe的静态导入,把导入逻辑移到useEffect里用动态import实现,动态导入只会在客户端执行副作用时触发,完全不会在SSR阶段运行:

import { useEffect, useRef } from 'react'
// 删掉顶部静态导入:import postscribe from 'postscribe'

const FormEmbed = () => {
  const advRef = useRef(null)

  useEffect(() => {
    if (!advRef.current) return
    // 客户端侧才加载postscribe
    import('postscribe').then(({ default: postscribe }) => {
      postscribe(
        advRef.current,
        "<script src='...替换为你的Formstack表单地址...'><\/script>"
      )
    })
  }, [advRef])

  return <div id="adv" ref={advRef}></div>
}

export default FormEmbed

方案2:标记组件为仅客户端渲染

如果动态导入后仍有兼容问题,可以直接把整个表单嵌入组件标记为仅在客户端渲染,从根源上避免SSR执行该组件的任何代码:

  1. 把上面写的表单嵌入组件单独存为src/components/FormstackForm.js
  2. 在需要引入表单的页面/组件中,用Gatsby默认支持的loadable做客户端懒加载:
import loadable from '@loadable/component'
// SSR阶段完全跳过该组件的加载和渲染
const FormstackForm = loadable(() => import('../components/FormstackForm'))

const TargetPage = () => {
  return (
    <main>
      {/* 其他页面内容 */}
      <FormstackForm />
    </main>
  )
}
避坑提示

所有依赖浏览器全局API(window、document等)的第三方库,都不要在Gatsby/Next这类支持SSR的框架里用顶层静态import引入,只要导入语句在模块顶层,构建阶段就会在Node环境执行库的初始化代码,很容易触发这类window is not defined报错。

内容的提问来源于stack exchange,提问作者yankeedoodle

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.27 12:09:47