news 2026/9/15 17:00:42

在 Electron 桌面应用中集成 CKEditor 5:基于 CDN 的完整实战指南

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
在 Electron 桌面应用中集成 CKEditor 5:基于 CDN 的完整实战指南

在 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.htmlsrc/是渲染进程的入口,正是我们要放置编辑器的地方。

第一步:创建 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与开源插件EssentialsBoldItalicFontParagraph
  • 从付费功能全局变量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()支持:

  1. 挂载到已有 DOM 元素(本指南用法):attachTo: document.querySelector( '#editor' ),元素内容会作为编辑器初始数据,元素随后被编辑器 UI 替换;
  2. 创建脱离文档的编辑器:不传attachTo,通过root: { initialData: '<p>Hello world!</p>' }提供初始数据,之后用document.body.appendChild( editor.ui.element )手动插入 DOM;
  3. 混合方式:同时提供attachToroot.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暴露全局变量CKEDITORckeditor5-premium-features.umd.js暴露全局变量CKEDITOR_PREMIUM_FEATURES,两者通过全局对象解构即可使用;
  • <div id="editor"></div>:编辑器的挂载占位符,其 ID 必须与editor.jsattachTo的查询选择器一致;
  • <script src="./src/editor.js">:负责把以上资源"串起来"并完成编辑器初始化;注意renderer.js仍以 ES Module 方式加载,二者互不冲突。

第三步:启动并验证

在应用根目录执行:

npm start

Electron 会自动打开一个窗口,其中即可看到一个可编辑的 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 插件,将ckeditor5ckeditor5-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),仅供参考

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/9/15 17:00:06

AI 资讯日报 | 2026年9月14日:AI减速论席卷全球,三大巨头罕见讨论研发节奏;智谱50亿美元融资、国产芯片增长与新一代模型密集升级,安全、算力与资本成为焦点

今日主题&#xff1a;"AI减速论"席卷全球——三大厂罕见共识&#xff0c;智谱斩获50亿美元巨额融资一、政策与治理三大AI巨头罕见"合体"呼吁放缓前沿模型研发 Anthropic CEO 达里奥阿莫迪 9月12日发表长文《我们必须为前沿定速》&#xff0c;提出第三方嵌入…

作者头像 李华
网站建设 2026/9/15 16:59:53

Zemax光机热集成分析:从FEA数据导入到像质评估全流程指南

1. 是什么在悄悄吃掉你的光学系统性能做光学设计的人应该都有过这种体会&#xff1a;仿真里MTF曲线漂亮得感人&#xff0c;分辨率接近衍射极限&#xff0c;但样机一测试&#xff0c;成像质量掉了好几个档次。如果排除了加工公差和装调误差&#xff0c;你大概率忽略了环境热载荷…

作者头像 李华
网站建设 2026/9/15 16:58:23

联邦学习安全聚合实战:Shamir门限秘密共享与FedSTSS方案实现

简介&#xff1a;面向联邦学习安全聚合研究的一套可运行代码实现&#xff0c;重点给出基于Shamir门限秘密共享的FedSTSS模型&#xff0c;并配套FedShare、Scotch、FedAvg等基线方法的对比实验。代码包含服务端与客户端Python脚本、秘密共享与模型聚合核心模块、多数据集加载处理…

作者头像 李华
网站建设 2026/9/15 16:57:18

微信小程序睡眠检测实战:从加速度计到状态机的完整拆解

简介&#xff1a;压缩包内是一款面向普通用户与轻度失眠人群的睡眠检测微信小程序&#xff0c;基于微信小程序原生框架开发&#xff0c;通过睡眠时长、深度、翻身次数等数据完成智能分析与可视化展示。资源共110个文件&#xff0c;主要包括53个png图标与界面素材、14个js逻辑脚…

作者头像 李华