在 Electron 桌面应用中集成 CKEditor 5:基于 CDN 的完整实战指南
【免费下载链接】ckeditor5Powerful rich text editor framework with a modular architecture, modern integrations, and features like collaborative editing.项目地址: https://gitcode.com/GitHub_Trending/ck/ckeditor5
导读
本指南以当前仓库(CKEditor 5 富文本编辑器框架)中的 CDN 集成文档 为主线,讲解如何把 CKEditor 5 通过 CDN 方式集成进 Electron 桌面应用:因为 Electron 窗口由 Chromium 渲染,CKEditor 5 的 HTML 编辑器在 Electron 渲染进程中运行方式与浏览器完全一致,你可以像在网页中一样,用几行<script>标签把编辑器"搬"进桌面窗口。读完本文,你将掌握从零搭建 Electron + Vite 项目、通过 CDN 引入开源与付费(premium)功能、用attachTo初始化编辑器实例的完整流程,并理解其底层实现原理。
为什么 Electron 项目可以复用 CDN 集成方式
Electron 应用由两个进程组成:主进程(main process)负责管理应用生命周期与系统窗口,渲染进程(renderer process)则运行着 Chromium 浏览器内核。CKEditor 5 是标准的 HTML 富文本编辑器,它的 UI 与编辑区都构建在 DOM 之上,因此在 Electron 渲染进程中,编辑器就像在 Chrome 浏览器里一样正常工作,无需任何 Node.js 特定适配。
这一点与"把编辑器加载到普通网页"完全等价——这也是 quick-start.md 中 CDN 安装方式能够无缝复用的根本原因:你只需要在 Electron 渲染进程的 HTML 页面里,像普通网页一样引入 CSS 与 JS 资源即可。
快速开始:搭建 Electron 项目
官方推荐的脚手架是 Electron Forge 的create-electron-app命令。在终端执行:
npx create-electron-app@latest my-app执行时你会被提示选择打包器(bundler)与语言。本指南(与官方文档一致)选择Vite+Vanilla JavaScript。由于 Vite 是 Electron Forge 的渲染进程打包方案,后文会专门说明它与 CDN/ESM 引入方式的配合问题。
搭建完成后,进入应用目录并启动:
cd my-app npm start此时应用应能正常打开一个 Electron 窗口。若你是第一次接触 Electron,建议先阅读其官方入门教程了解基本概念。
集成 CKEditor 5 到 Electron:逐步实现
最终项目结构
完成全部步骤后,应用目录结构应类似:
├── forge.config.js ├── index.html ├── node_modules/ ├── package-lock.json ├── package.json ├── src/ │ ├── index.css │ ├── main.js │ ├── preload.js │ └── renderer.js ├── vite.main.config.mjs ├── vite.preload.config.mjs └── vite.renderer.config.mjs其中index.html与src/是渲染进程的入口,正是我们要放置编辑器的地方。
第一步:创建 editor.js 并初始化编辑器
在src/目录下新建文件editor.js,写入以下内容:
const { ClassicEditor, Essentials, Bold, Italic, Font, Paragraph } = CKEDITOR; const { FormatPainter } = CKEDITOR_PREMIUM_FEATURES; ClassicEditor .create( { attachTo: document.querySelector( '#editor' ), licenseKey: '<YOUR_LICENSE_KEY>', plugins: [ Essentials, Bold, Italic, Font, Paragraph, FormatPainter ], toolbar: [ 'undo', 'redo', '|', 'bold', 'italic', '|', 'fontSize', 'fontFamily', 'fontColor', 'fontBackgroundColor', '|', 'formatPainter' ] } ) .then( /* ... */ ) .catch( /* ... */ );这段代码做了三件事:
- 从 CDN 暴露的全局变量
CKEDITOR中解构出经典编辑器类ClassicEditor与开源插件Essentials、Bold、Italic、Font、Paragraph; - 从付费功能全局变量
CKEDITOR_PREMIUM_FEATURES中取出FormatPainter(格式刷); - 调用
ClassicEditor.create()创建编辑器实例,并挂载到#editor元素上。
关于attachTo配置项:这是经典编辑器(ClassicEditor)特有的配置,用于指定编辑器要替换的 DOM 元素。从源码看,classiceditor.ts 的构造函数会调用normalizeRootsConfig()对配置做归一化,再通过this.config.get( 'attachTo' )读取该元素作为sourceElement;而 normalizerootsconfig.ts 中的separateAttachTo参数专门处理了经典编辑器的这种"外部指定挂载元素"模式——attachTo只被当作数据来源和挂载目标,而不会被当作可编辑根元素(经典编辑器会用自带的 UI 盒子替换掉该元素)。同时要注意:attachTo仅适用于 ClassicEditor,其它编辑器类型(如 inline、balloon、decoupled)在根元素内部直接渲染,配置attachTo会触发editor-create-attachto-ignored错误。
关于create()的三种初始化形态:根据 classiceditor.ts 的文档注释,create()支持:
- 挂载到已有 DOM 元素(本指南用法):
attachTo: document.querySelector( '#editor' ),元素内容会作为编辑器初始数据,元素随后被编辑器 UI 替换; - 创建脱离文档的编辑器:不传
attachTo,通过root: { initialData: '<p>Hello world!</p>' }提供初始数据,之后用document.body.appendChild( editor.ui.element )手动插入 DOM; - 混合方式:同时提供
attachTo与root.initialData,适合难以预先设置源元素内容的情形。
create()返回 Promise,then中拿到可用的编辑器实例,catch中可捕获初始化错误(如密钥无效、元素未挂载到 DOM 会抛editor-source-element-not-attached)。
第二步:改写 index.html 引入 CDN 资源
把index.html修改为:
<!doctype html> <html> <head> <meta charset="UTF-8" /> <title>Hello World!</title> <link rel="stylesheet" href="https://cdn.ckeditor.com/ckeditor5/{@var ckeditor5-version}/ckeditor5.css" /> <link rel="stylesheet" href="https://cdn.ckeditor.com/ckeditor5-premium-features/{@var ckeditor5-version}/ckeditor5-premium-features.css" /> <script src="https://cdn.ckeditor.com/ckeditor5/{@var ckeditor5-version}/ckeditor5.umd.js"></script> <script src="https://cdn.ckeditor.com/ckeditor5-premium-features/{@var ckeditor5-version}/ckeditor5-premium-features.umd.js"></script> </head> <body> <h1>Hello Electron and CKEditor 5!</h1> <p>Welcome to your Electron application. Below you should see a working instance of CKEditor 5:</p> <div id="editor"></div> <script src="./src/editor.js"></script> <script type="module" src="/src/renderer.js"></script> </body> </html>其中{@var ckeditor5-version}是文档占位符,实际使用时应替换为具体版本号(例如44.0.0)。这段 HTML 的关键改动:
- 两个
<link>样式表:ckeditor5.css包含编辑器 UI 与内容的全部样式;ckeditor5-premium-features.css则是付费插件(如 FormatPainter)的独立样式表,只有使用付费功能时才需要; - 两个
<script>资源:ckeditor5.umd.js暴露全局变量CKEDITOR,ckeditor5-premium-features.umd.js暴露全局变量CKEDITOR_PREMIUM_FEATURES,两者通过全局对象解构即可使用; <div id="editor"></div>:编辑器的挂载占位符,其 ID 必须与editor.js中attachTo的查询选择器一致;<script src="./src/editor.js">:负责把以上资源"串起来"并完成编辑器初始化;注意renderer.js仍以 ES Module 方式加载,二者互不冲突。
第三步:启动并验证
在应用根目录执行:
npm startElectron 会自动打开一个窗口,其中即可看到一个可编辑的 CKEditor 5 实例:
深入:CDN 两种引入方式的取舍
上文使用 UMD 全局变量方式,零打包、开箱即用,是最快路径。但对于依赖构建工具(尤其是 Electron Forge 默认采用的 Vite)的项目,还可以选择更工程化的import maps(ESM)方式,详见 quick-start.md 的进阶章节。
import map 允许用简短标识符映射 CDN 上的完整 URL,并让开源与付费插件共享同一份引擎代码:
<script type="importmap"> { "imports": { "ckeditor5": "https://cdn.ckeditor.com/ckeditor5/{@var ckeditor5-version}/ckeditor5.js", "ckeditor5/": "https://cdn.ckeditor.com/ckeditor5/{@var ckeditor5-version}/", "ckeditor5-premium-features": "https://cdn.ckeditor.com/ckeditor5-premium-features/{@var ckeditor5-version}/ckeditor5-premium-features.js", "ckeditor5-premium-features/": "https://cdn.ckeditor.com/ckeditor5-premium-features/{@var ckeditor5-version}/" } } </script>之后即可用标准 ESM 语法导入:
<script type="module"> import { ClassicEditor, Essentials, Bold, Italic, Font, Paragraph } from 'ckeditor5'; import { FormatPainter } from 'ckeditor5-premium-features'; ClassicEditor .create( { attachTo: document.querySelector( '#editor' ), licenseKey: '<YOUR_LICENSE_KEY>', plugins: [ Essentials, Bold, Italic, Font, Paragraph, FormatPainter ], toolbar: [ 'undo', 'redo', '|', 'bold', 'italic', '|', 'fontSize', 'fontFamily', 'fontColor', 'fontBackgroundColor', '|', 'formatPainter' ] } ) .then( /* ... */ ) .catch( /* ... */ ); </script>使用 import maps 有两点必须注意:
- 必须通过本地服务器(HTTP/HTTPS)访问页面,直接双击打开 HTML 会因浏览器 CORS 安全策略导致模块加载失败;
- Vite 需要额外配置。Vite 对原生 import map 与外部 ESM 模块支持不完整(构建期解析导入),直接使用 ESM 语法可能导致回退到 UMD 包或直接报错。官方给出的解决方案是编写一个自定义 Vite 插件,将
ckeditor5与ckeditor5-premium-features及其子路径声明为 external,交由浏览器运行时通过 import map 解析:
export function viteCKEditorExternalize() { return { name: 'ckeditor5-externalize', enforce: 'pre', config: ( config ) => { config.optimizeDeps ??= {}; config.optimizeDeps.exclude = [ ...( config.optimizeDeps.exclude ?? [] ), 'ckeditor5', 'ckeditor5-premium-features' ]; config.build ??= {}; config.build.rollupOptions ??= {}; config.build.rollupOptions.external = [ ...( config.build.rollupOptions.external ?? [] ), 'ckeditor5', 'ckeditor5-premium-features', /^ckeditor5\/.*/, /^ckeditor5-premium-features\/.*/ ]; }, configResolved: ( resolvedConfig ) => { ( resolvedConfig.plugins ).push( { name: 'remove-id-prefix', transform: ( code ) => { if ( typeof code === 'string' ) { return code.replace( /\/@id\/ckeditor5/g, 'ckeditor5' ); } return null; } } ); }, resolveId: ( id ) => { if ( id === 'ckeditor5' || id === 'ckeditor5-premium-features' || id.startsWith( 'ckeditor5/' ) || id.startsWith( 'ckeditor5-premium-features/' ) ) { return { id, external: true }; } return null; } }; }然后在 Vite 配置中启用:
// vite.config.js import { viteCKEditorExternalize } from './plugins/vite-ckeditor-externalize.js'; export default { plugins: [ viteCKEditorExternalize() ] };小提示:本指南演示的 UMD 方式不依赖任何打包器,因此在 Electron Forge + Vite 模板中开箱即用,无需上述插件。
获取付费功能(Premium Features)的许可证密钥
示例配置中的licenseKey: '<YOUR_LICENSE_KEY>'是激活付费功能(如 FormatPainter)的必要参数。要获得密钥:
- 注册 CKEditor Premium Features 14 天免费试用,即可快速获得商用许可证;
- 如需定制方案,可直接联系官方销售团队获取报价。
拿到激活密钥后,请按 许可证密钥与激活指南 完成激活流程。若使用开源免费功能而不需要付费插件,可移除licenseKey配置与CKEDITOR_PREMIUM_FEATURES相关的引用。
其它安装方式对照与进阶阅读
如果你不希望依赖 CDN(例如要求完全离线的桌面应用),仓库中还提供了对应的 ZIP 离线包集成指南:在 Online Builder 中选择 "Vanilla JavaScript" + "Self-hosted (ZIP)" 下载自定义构建,将其解压到应用目录,并把index.html中的 CDN 链接替换为./ckeditor5-builder/...形式的本地相对路径,其余初始化代码与本文完全一致。
在此基础上,可继续深入:
- 掌握 获取与设置编辑器数据,实现桌面应用内内容的读取与回填;
- 查看 编辑器配置指南 与 工具栏配置,按需定制 UI 与行为;
- 浏览 功能索引,了解可选的编辑器功能模块;
- 参考 CDN 资源加载说明 与 编辑器类型选择,选择合适的编辑器形态与加载策略。
小结
本指南完整覆盖了 Electron 桌面应用通过 CDN 集成 CKEditor 5 的路径:从 Electron Forge 脚手架、双样式表/双脚本的资源引入、ClassicEditor.create()的三种初始化方式与attachTo的底层归一化逻辑,到 import maps 与 Vite 外部化的工程化进阶,再到付费密钥获取与离线 ZIP 方案对照。这套方案不需要任何打包器参与即可在 Electron 渲染进程中获得完整可用的富文本编辑能力,是桌面端嵌入 CKEditor 5 最快、最直接的途径。
【免费下载链接】ckeditor5Powerful rich text editor framework with a modular architecture, modern integrations, and features like collaborative editing.项目地址: https://gitcode.com/GitHub_Trending/ck/ckeditor5
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考