You need to enable JavaScript to run this app.
最新活动
大模型
产品
解决方案
定价
生态与合作
支持与服务
开发者
了解我们

Next.js导入JS文件报错:ReferenceError: navigator is not defined

解决Next.js中导入CodeMirror Python模式时navigator is not defined的问题

这个问题我之前在Next.js项目里踩过坑!根源在于Next.js默认的服务端渲染(SSR)机制codemirror/mode/python/python.js内部直接使用了浏览器专属的navigator对象,但SSR阶段是在服务器环境运行的,根本没有这个浏览器API,所以就抛出了ReferenceError

下面给你两种靠谱的解决办法,亲测有效:

方法1:用next/dynamic动态导入(推荐)

通过next/dynamic把依赖浏览器环境的CodeMirror组件和Python模式都设置为仅客户端渲染,这样就能避开SSR阶段的环境差异。

修改你的组件代码如下:

import Link from "next/link";
import dynamic from "next/dynamic";
import "../node_modules/codemirror/lib/codemirror.css";
import "../node_modules/codemirror/theme/material.css";
import styled from "styled-components";

// 动态导入CodeMirror,同时在客户端加载Python模式
const CodeMirror = dynamic(
  () => {
    // 仅在客户端环境执行此导入,此时navigator已存在
    import("../node_modules/codemirror/mode/python/python.js");
    return import("react-codemirror2").then(mod => mod.UnControlled);
  },
  { ssr: false } // 禁用服务端渲染
);

const CodeContainer = styled.div`
  position: absolute;
  width: 600px;
  left: 600px;
  height: 100%;
  overflow-y: auto;
  z-index: 1;
`;

const Code = () => (
  <CodeContainer>
    <CodeMirror
      value="print('Hello Python!')" // 换成Python代码测试
      options={{ mode: "python", theme: "material", lineNumbers: true }}
      onChange={(editor, data, value) => {}}
    />
  </CodeContainer>
);

export default Code;

方法2:在useEffect中延迟导入

useEffect是React仅在客户端渲染阶段执行的钩子,把Python模式的导入放在这里,就能确保只在浏览器环境下加载:

import Link from "next/link";
import { UnControlled as CodeMirror } from "react-codemirror2";
import { useEffect } from "react";
import "../node_modules/codemirror/lib/codemirror.css";
import "../node_modules/codemirror/theme/material.css";
import styled from "styled-components";

const CodeContainer = styled.div`
  position: absolute;
  width: 600px;
  left: 600px;
  height: 100%;
  overflow-y: auto;
  z-index: 1;
`;

const Code = () => {
  // 客户端渲染时才加载Python模式
  useEffect(() => {
    import("../node_modules/codemirror/mode/python/python.js");
  }, []);

  return (
    <CodeContainer>
      <CodeMirror
        value="print('Hello Python!')"
        options={{ mode: "python", theme: "material", lineNumbers: true }}
        onChange={(editor, data, value) => {}}
      />
    </CodeContainer>
  );
};

export default Code;

原理说明

两种方法的核心都是让Python模式的代码只在客户端环境执行

  • 方法1通过next/dynamicssr: false选项,直接把整个CodeMirror相关逻辑排除在SSR之外;
  • 方法2利用useEffect的执行时机,延迟导入需要浏览器API的模块。

这样修改后,你就能正常使用CodeMirror渲染Python代码,不会再碰到navigator is not defined的错误了。

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

火山引擎 最新活动