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

Next.js构建时遇ReferenceError: navigator is not defined问题求助

在Next.js + TypeScript项目中解决TinyMCE构建时的navigator未定义问题

问题背景

我在TypeScript的Next.js项目中,实现了基于TinyMCE的BundledEditor组件:

// ** 参考TinyMCE官方文档实现 **//
import { Editor } from '@tinymce/tinymce-react'

// TinyMCE so the global var exists
// eslint-disable-next-line no-unused-vars
import tinymce from 'tinymce/tinymce'

// DOM model
import 'tinymce/models/dom/model'

// Theme
import 'tinymce/themes/silver'

// Toolbar icons
import 'tinymce/icons/default'

// Editor styles
import 'tinymce/skins/ui/oxide/skin.min.css'

// 导入所需插件
import 'tinymce/plugins/advlist'
import 'tinymce/plugins/anchor'
import 'tinymce/plugins/autolink'
import 'tinymce/plugins/autoresize'
import 'tinymce/plugins/autosave'
import 'tinymce/plugins/charmap'
import 'tinymce/plugins/code'
import 'tinymce/plugins/codesample'
import 'tinymce/plugins/directionality'
import 'tinymce/plugins/emoticons'
import 'tinymce/plugins/fullscreen'
import 'tinymce/plugins/help'
import 'tinymce/plugins/image'
import 'tinymce/plugins/importcss'
import 'tinymce/plugins/insertdatetime'
import 'tinymce/plugins/link'
import 'tinymce/plugins/lists'
import 'tinymce/plugins/media'
import 'tinymce/plugins/nonbreaking'
import 'tinymce/plugins/pagebreak'
import 'tinymce/plugins/preview'
import 'tinymce/plugins/quickbars'
import 'tinymce/plugins/save'
import 'tinymce/plugins/searchreplace'
import 'tinymce/plugins/table'
import 'tinymce/plugins/template'
import 'tinymce/plugins/visualblocks'
import 'tinymce/plugins/visualchars'
import 'tinymce/plugins/wordcount'

// 导入插件资源
import 'tinymce/plugins/emoticons/js/emojis'

// 内容样式
/* eslint import/no-webpack-loader-syntax: off */
import contentCss from '!!raw-loader!tinymce/skins/content/default/content.min.css'
import contentUiCss from '!!raw-loader!tinymce/skins/ui/oxide/content.min.css'

export default function BundledEditor(props) {
  const { init, ...rest } = props

  return (
    <Editor
      init={{
        ...init,
        skin: false,
        content_css: false,
        content_style: [contentCss, contentUiCss, init.content_style || ''].join('\n')
      }}
      {...rest}
    />
  )
}

最初直接通过import BundledEditor from './BundledEditor';引入时,页面可正常运行,但刷新时抛出:

ReferenceError: navigator is not defined

改用动态导入后解决了刷新问题:

const BundledEditor = dynamic(() => import('../BundledEditor'), {
  ssr: false
})

但执行yarn build时仍出现相同错误:

info  - Collecting page data ...ReferenceError: navigator is not defined
    at /Users/motogod19/4iDPS/Sphere/sphere-brand-dev/node_modules/tinymce/tinymce.js:961:23
    at Object.<anonymous> (/Users/motogod19/4iDPS/Sphere/sphere-brand-dev/node_modules/tinymce/tinymce.js:31525:3)
    at Module._compile (node:internal/modules/cjs/loader:1254:14)
    at Module._extensions..js (node:internal/modules/cjs/loader:1308:10)
    at Module.load (node:internal/modules/cjs/loader:1117:32)
    at Module._load (node:internal/modules/cjs/loader:958:12)
    at Module.require (node:internal/modules/cjs/loader:1141:19)
    at require (node:internal/modules/cjs/helpers:110:18)
    at 3868 (/Users/motogod19/4iDPS/Sphere/sphere-brand-dev/.next/server/pages/apps/campaign/BundledEditor.js:28:33)
    at __webpack_require__ (/Users/motogod19/4iDPS/Sphere/sphere-brand-dev/.next/server/webpack-runtime.js:25:42)

> Build error occurred
Error: Failed to collect page data for /apps/campaign/BundledEditor

解决方法

1. 调整组件存放目录

不要将BundledEditor组件放在pages目录下。Next.js会自动对pages目录下的所有文件执行SSR预渲染,即便使用了dynamic({ ssr: false }),构建时仍会解析模块内的静态导入,导致TinyMCE在服务端执行时访问navigator报错。

将BundledEditor移到components目录,再进行动态导入。

2. 使用Next.js客户端组件标记(Next.js 13+)

如果你的项目使用Next.js 13及以上版本,直接在BundledEditor组件顶部添加'use client'指令,标记其为客户端组件,跳过服务端渲染:

'use client'; // 添加这行
import { Editor } from '@tinymce/tinymce-react';
// ... 其余导入和组件代码保持不变

添加后无需再使用dynamic导入,直接正常引入组件即可:

import BundledEditor from '../components/BundledEditor';

3. 优化动态导入逻辑(兼容旧版Next.js)

如果使用Next.js 12及以下版本,确保动态导入时,组件内的TinyMCE相关代码仅在客户端执行。可以将TinyMCE的核心导入放在动态导入的回调中,或者在组件内部通过typeof window判断:

// 动态导入时直接加载客户端组件
const BundledEditor = dynamic(() => import('../components/BundledEditor'), {
  ssr: false,
  loading: () => <div>加载编辑器中...</div> // 可选加载态
});

同时在BundledEditor组件中,避免在模块顶层执行依赖浏览器环境的代码,确保所有TinyMCE相关逻辑在组件挂载后执行。

4. 验证修复

调整后执行yarn build,确认构建过程不再抛出navigator is not defined错误。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.11 09:44:51