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
相关产品推荐
相关产品推荐

