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

NextJS出现ReferenceError: document is not defined错误求助

解决Next.js中ReferenceError: document is not defined错误(使用react-quill时)

错误原因

你碰到的ReferenceError: document is not defined是因为Next.js默认的服务端渲染(SSR)环境里不存在浏览器专属的document对象。你的代码里直接在顶层导入了Quill(import { Quill } from "react-quill"),这部分代码会在服务端执行,而Quill初始化时依赖浏览器的DOM环境,所以触发了错误。虽然你用dynamic导入ReactQuill时关闭了SSR,但Quill的导入和后续的主题注册代码还是在服务端运行了,这才是问题根源。

解决方案

核心思路是:所有依赖浏览器DOM的代码,必须确保只在客户端环境执行,避开服务端渲染阶段。下面提供两种可行的修改方式:

方式一:在useEffect中封装Quill主题逻辑

把Quill的导入、主题扩展和注册逻辑放到useEffect钩子中,利用typeof window !== 'undefined'判断确保只在浏览器端执行:

import { useEffect } from "react";
import dynamic from 'next/dynamic';
import toolbarOptions from "./toolbar";

import 'react-quill/dist/quill.bubble.css';
import styles from '../styles/Home.module.css'

const ReactQuill = dynamic(() => import("react-quill"), { ssr: false });

export default function Home() {
  useEffect(() => {
    // 仅在客户端环境执行Quill相关操作
    if (typeof window !== 'undefined') {
      const { Quill } = require("react-quill");
      const BubbleTheme = Quill.import("themes/bubble");

      class ExtendBubbleTheme extends BubbleTheme {
        constructor(quill, options) {
          super(quill, options);

          quill.on("selection-change", (range) => {
            if (range) {
              quill.theme.tooltip.show();
              quill.theme.tooltip.position(quill.getBounds(range));
            }
          });
        }
      }

      Quill.register("themes/bubble", ExtendBubbleTheme);
    }
  }, []);

  return (
    <div className={styles.container}>
      <h1>Quill Editor</h1>
      <ReactQuill
        theme="bubble"
        placeholder="Compose an epic..."
        modules={{ toolbar: toolbarOptions }}
      />
    </div>
  )
}

方式二:封装Quill主题模块并动态导入

  1. 新建quill-theme.js文件,把主题扩展逻辑单独封装:
import { Quill } from "react-quill";

const BubbleTheme = Quill.import("themes/bubble");

class ExtendBubbleTheme extends BubbleTheme {
  constructor(quill, options) {
    super(quill, options);

    quill.on("selection-change", (range) => {
      if (range) {
        quill.theme.tooltip.show();
        quill.theme.tooltip.position(quill.getBounds(range));
      }
    });
  }
}

Quill.register("themes/bubble", ExtendBubbleTheme);
  1. 在页面组件中动态导入该模块:
import { useEffect } from "react";
import dynamic from 'next/dynamic';
import toolbarOptions from "./toolbar";

import 'react-quill/dist/quill.bubble.css';
import styles from '../styles/Home.module.css'

const ReactQuill = dynamic(() => import("react-quill"), { ssr: false });

export default function Home() {
  useEffect(() => {
    // 动态加载Quill主题模块,确保只在客户端执行
    const loadTheme = async () => {
      await import('./quill-theme');
    };
    loadTheme();
  }, []);

  return (
    <div className={styles.container}>
      <h1>Quill Editor</h1>
      <ReactQuill
        theme="bubble"
        placeholder="Compose an epic..."
        modules={{ toolbar: toolbarOptions }}
      />
    </div>
  )
}

关键说明

两种方式本质都是让Quill相关的DOM依赖代码避开服务端渲染阶段,只在浏览器环境中运行,这样就不会再触发document is not defined的错误了。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.25 08:30:24