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

在Next.js中使用ketcher-react遇window未定义错误求解决

在Next.js中集成ketcher-react解决"window is not defined"错误的方案

问题根源

ketcher-react和ketcher-standalone的部分代码依赖浏览器环境的window对象,即便你用了dynamic({ ssr: false })导入组件,模块顶层的初始化代码(比如实例化StandaloneStructServiceProvider)仍会在SSR阶段被执行,这就是报错的核心原因。

解决方案一:将依赖浏览器的逻辑移到客户端生命周期中

把模块导入和初始化逻辑放在useEffect里,确保只在浏览器环境执行:

修改KetcherEditorReact.tsx:

import { useEffect, useState } from "react";
import "ketcher-react/dist/index.css";

export default function KetcherEditorReact() {
  const [Editor, setEditor] = useState<React.ComponentType<any> | null>(null);
  const [structService, setStructService] = useState<any>(null);

  useEffect(() => {
    const initKetcher = async () => {
      // 动态导入依赖,避免SSR解析时触发window调用
      const { StandaloneStructServiceProvider } = await import("ketcher-standalone");
      const { Editor } = await import("ketcher-react");

      setStructService(new StandaloneStructServiceProvider());
      setEditor(Editor);
    };

    initKetcher();
  }, []);

  // 加载完成前显示占位内容
  if (!Editor || !structService) {
    return <p>Loading editor...</p>;
  }

  return (
    <Editor
      staticResourcesUrl=""
      structServiceProvider={structService}
      errorHandler={(err) => console.log(err)}
    />
  );
}

Page.tsx保持原有动态导入逻辑即可:

import dynamic from "next/dynamic";

import "ketcher-react/dist/index.css";
const KetcherEditorReact = dynamic(() => import("./KetcherEditorReact"), {
  ssr: false,
  loading: () => <p>Loading editor...</p>,
});

export default function Home() {
  return <KetcherEditorReact />;
}

解决方案二:用环境判断包裹顶层初始化代码

如果你不想用useEffect,可以通过typeof window !== 'undefined'判断环境,仅在客户端初始化服务:

import { Editor } from "ketcher-react";
import "ketcher-react/dist/index.css";

let structServiceProvider: any = null;

// 仅在浏览器环境初始化
if (typeof window !== 'undefined') {
  const { StandaloneStructServiceProvider } = require("ketcher-standalone");
  structServiceProvider = new StandaloneStructServiceProvider();
}

export default function KetcherEditorReact() {
  if (!structServiceProvider) {
    return <p>Loading editor...</p>;
  }

  return (
    <Editor
      staticResourcesUrl=""
      structServiceProvider={structServiceProvider}
      errorHandler={(err) => console.log(err)}
    />
  );
}

注意:此方案依赖require而非ES模块导入,在TypeScript项目中可能需要调整tsconfig.json的moduleResolution配置。

关键说明

  • 不要在模块顶层直接导入或初始化依赖window的代码,因为Next.js在SSR阶段会解析所有模块的顶层代码。
  • dynamic({ ssr: false })仅能阻止组件的渲染逻辑在SSR执行,但无法阻止模块顶层代码的解析。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.21 14:40:15