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

Laravel10+Inertia+Vue3环境自托管TinyMCE报错及编辑器推荐咨询

Laravel 10 + Inertia + Vue3 + Vite 环境下自托管 TinyMCE 部署问题及替代方案请求
  • 按官方文档操作后,TinyMCE 无法以自托管模式加载,仍提示输入密钥
  • 启动 SSR 服务时抛出 ReferenceError: window is not defined 错误,已困扰两天
  • 若无法解决,希望推荐 Quill 以外的富文本编辑器

错误控制台输出

php artisan inertia:start-ssr
Starting SSR server on port 13714...
Inertia SSR server started.
ReferenceError: window is not defined
    at mediaMatch (/Applications/XAMPP/xamppfiles/htdocs/W/INERTIA/node_modules/tinymce/tinymce.js:957:57)
    at DeviceType (/Applications/XAMPP/xamppfiles/htdocs/W/INERTIA/node_modules/tinymce/tinymce.js:615:35)
    at Object.detect$3 [as detect] (/Applications/XAMPP/xamppfiles/htdocs/W/INERTIA/node_modules/tinymce/tinymce.js:948:26)
    at /Applications/XAMPP/xamppfiles/htdocs/W/INERTIA/node_modules/tinymce/tinymce.js:958:53)
    at /Applications/XAMPP/xamppfiles/htdocs/W/INERTIA/node_modules/tinymce/tinymce.js:605:17)
    at detect$2 (/Applications/XAMPP/xamppfiles/htdocs/W/INERTIA/node_modules/tinymce/tinymce.js:959:28)
    at /Applications/XAMPP/xamppfiles/htdocs/W/INERTIA/node_modules/tinymce/tinymce.js:962:24)
    at Object.<anonymous> (/Applications/XAMPP/xamppfiles/htdocs/W/INERTIA/node_modules/tinymce/tinymce.js:31756:3)
    at Module._compile (node:internal/modules/cjs/loader:1378:14)
    at Module._extensions..js (node:internal/modules/cjs/loader:1437:10)
node:internal/process/promises:289
            triggerUncaughtException(err, true /* fromPromise */);
            ^

ReferenceError: window is not defined
    at mediaMatch (/Applications/XAMPP/xamppfiles/htdocs/W/INERTIA/node_modules/tinymce/tinymce.js:957:57)
    at DeviceType (/Applications/XAMPP/xamppfiles/htdocs/W/INERTIA/node_modules/tinymce/tinymce.js:615:35)
    at Object.detect$3 [as detect] (/Applications/XAMPP/xamppfiles/htdocs/W/INERTIA/node_modules/tinymce/tinymce.js:948:26)
    at /Applications/XAMPP/xamppfiles/htdocs/W/INERTIA/node_modules/tinymce/tinymce.js:958:53)
    at /Applications/XAMPP/xamppfiles/htdocs/W/INERTIA/node_modules/tinymce/tinymce.js:605:17)
    at detect$2 (/Applications/XAMPP/xamppfiles/htdocs/W/INERTIA/node_modules/tinymce/tinymce.js:959:28)
    at /Applications/XAMPP/xamppfiles/htdocs/W/INERTIA/node_modules/tinymce/tinymce.js:962:24)
    at Object.<anonymous> (/Applications/XAMPP/xamppfiles/htdocs/W/INERTIA/node_modules/tinymce/tinymce.js:31756:3)
    at Module._compile (node:internal/modules/cjs/loader:1378:14)
    at Module._extensions..js (node:internal/modules/cjs/loader:1437:10)

Node.js v21.6.2

Editor.vue 组件代码

<template>
    <editor
        api-key="no-api-key"
        v-model="model" model-events="" @selectionChange="changes"
        :init="init"
    />
</template>

<script>
import { defineComponent } from 'vue'

//TinyMCE
import tinymce from 'tinymce';
import 'tinymce/icons/default/icons'
import 'tinymce/themes/silver/theme'
import 'tinymce/models/dom/model'
import 'tinymce/skins/ui/oxide/skin.css'
//import {contentUiCss} from 'tinymce/skins/ui/oxide/content.css';

//TinyMCE plugins
//https://www.tiny.cloud/docs/tinymce/6/plugins/
import 'tinymce/plugins/lists/plugin'
import 'tinymce/plugins/link/plugin'
import 'tinymce/plugins/image/plugin'
import 'tinymce/plugins/table/plugin'
import 'tinymce/plugins/code/plugin'
import 'tinymce/plugins/wordcount/plugin'

import 'tinymce/langs/tr'

import Editor from '@tinymce/tinymce-vue'

export default defineComponent({
    props: ['modelValue'],

    components: {'editor':Editor},

    emits: ['update:modelValue'],
    data() {
        return {
            model: this.modelValue,
            init: {
                entities : "Ü = Ü ü = ü Ç = Ç ç = ç Ö = Ö ö = ö Ş = Ş ş = ş Ğ = Ğ ğ = ğ İ = İ ı = ı",
                valid_elements: "*[*]",
                skin: false,
                plugins: 'lists link image table code wordcount',
                content_css: false,
                //content_style: contentUiCss.toString(),
                language: 'tr',
                promotion: false,
                convert_urls: false,
            }
        }
    },
    methods: {
        changes(event,editor){
            this.$emit('update:modelValue', editor.getContent())
        }

    }
})
</script>

问题解决思路

1. 修复 SSR 环境下 window is not defined 错误

TinyMCE 依赖浏览器环境的 window 对象,而 Inertia SSR 运行在 Node.js 环境,没有该对象。需修改组件,仅在客户端加载编辑器:

<template>
    <client-only>
        <editor
            api-key="no-api-key"
            v-model="model" model-events="" @selectionChange="changes"
            :init="init"
        />
    </client-only>
</template>

<script>
import { defineComponent, defineAsyncComponent } from 'vue'

export default defineComponent({
    props: ['modelValue'],

    components: {
        // 仅在客户端异步加载编辑器组件
        editor: defineAsyncComponent(() => {
            if (process.client) {
                return import('@tinymce/tinymce-vue').then(module => ({ default: module.Editor }))
            }
            return Promise.resolve({ default: () => null })
        })
    },

    emits: ['update:modelValue'],
    data() {
        return {
            model: this.modelValue,
            init: {
                entities : "Ü = Ü ü = ü Ç = Ç ç = ç Ö = Ö ö = ö Ş = Ş ş = ş Ğ = Ğ ğ = ğ İ = İ ı = ı",
                valid_elements: "*[*]",
                skin: false,
                plugins: 'lists link image table code wordcount',
                content_css: false,
                language: 'tr',
                promotion: false,
                convert_urls: false,
                // 明确指定自托管资源路径
                base_url: '/tinymce',
                suffix: '.min'
            }
        }
    },
    methods: {
        changes(event,editor){
            this.$emit('update:modelValue', editor.getContent())
        }
    }
})
</script>

2. 配置自托管模式

  • 将 node_modules/tinymce 目录下的 skins、themes、plugins 等静态资源复制到 Laravel 的 public/tinymce 目录
  • 通过 base_url: '/tinymce' 让编辑器从本地加载资源,避免云请求
  • 移除组件中直接导入 tinymce 核心的代码,防止 SSR 时加载

3. 消除密钥提示

确保 api-key="no-api-key" 配置正确,同时保留 promotion: false 禁用推广提示,自托管模式下无需有效密钥即可正常使用。


替代编辑器推荐(Quill 以外)

  • CKEditor 5:功能全面,支持自托管,Vue3 集成友好,提供多种预设版本
  • Slate.js:高度可定制,适合需要自定义编辑逻辑的复杂场景
  • ProseMirror:模块化架构,扩展性强,可构建定制化编辑器
  • Froala Editor:轻量易用,Vue3 组件完善,支持自托管

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.28 09:07:03