Tiptap React 编辑器:我们如何让 PageBuilder HTML 区块变得简单
Tech
Tiptap
React
Next.js
E-commerce

Tiptap React 编辑器:我们如何让 PageBuilder HTML 区块变得简单

我们在电商 PageBuilder 中加入了 Tiptap React 编辑器,让商家无需接触原始标记即可创建 HTML 区块。

Uygar DuzgunUUygar Duzgun
Jun 17, 2026
更新於 2026年8月23日
8 min read

最好的编辑器升级,是让内容工作不再令人畏惧。

我们在电商 PageBuilder 中加入了 Tiptap React 编辑器,因为原始 HTML 区块的编辑成本已经变得过高。它们确实能正常工作,但只适合那些熟悉标记语言的人。商家应该能够添加标题、图片、按钮、列、标签页或 Instagram 嵌入,而不必担心破坏商品页布局,或发布不安全的 HTML。

这项工作最终落在电商主题的 `codex/htmlblock-wysiwyg-editor` 分支上。首次实现的提交 `08692e2e` 加入了 HTML 区块 WYSIWYG 编辑器。后续提交完善了交互,将标签移入翻译系统,加强了媒体处理,并通过 ID 对媒体库图片进行去重。

Tiptap 很适合这个项目,因为它没有强迫我们采用封闭的 CMS 结构。我们保留了现有的 PageBuilder HTML 契约,并将 Tiptap 用作编辑引擎。

我们构建了什么

从用户可见的角度看,这项功能很简单:PageBuilder HTML 区块现在拥有真正的编辑器,而不再只是原始 HTML 文本框。

但实现内容比这句话听起来更丰富。编辑器支持:

H2 到 H6 标题
段落、粗体、斜体、下划线、删除线、代码、引用、列表、高亮和链接
文本对齐和基于 class 的字号
渲染为可抓取锚点的 CTA 按钮
响应式列布局
带有 alt 文本、标题、延迟加载和媒体选择器的图片
不将 script 标签带入已保存内容的 Instagram 嵌入
用于控制布局节奏的间隔块
包含两个到二十个面板的标签页
表格,以及在旧内容仍需保留时使用的旧版 CMS 标记

最后一点非常重要。这不是一个从零开始的编辑器。电商前端已经存在 Bootstrap 风格的内容、旧版 CMS 片段、PageBuilder 区域、PrestaShop 媒体路径和 SEO 规则。我们需要的是一个能够编辑内容、同时不扁平化网站现有 HTML 模型的 WYSIWYG 层。

为什么 Tiptap 让事情变得简单

Tiptap 的 React 配置很小:`useEditor`、`EditorContent` 和扩展数组。StarterKit 提供基础编辑能力,然后你可以加入产品所需的功能。

在我们的项目中,依赖集合仍然清晰易懂:

`@tiptap/core`
`@tiptap/react`
`@tiptap/starter-kit`
`@tiptap/extension-link`
`@tiptap/extension-highlight`

这些已经足够构建编辑器界面,然后在其上叠加我们自己的电商区块。我们使用 `StarterKit.configure()` 配置标准编辑器行为,在需要自定义规则的地方禁用了默认链接处理,然后显式配置 Link 和 Highlight。

简单之处并不在于 Tiptap 解决了所有电商问题。它并没有。简单之处在于它的扩展模型。我们可以直接描述自己的内容节点:按钮、图片、旧版图片、Instagram 嵌入、列、标签页、间隔块、表格、字号、列表样式和文本对齐。

这与 PageBuilder 的结构非常匹配。按钮不只是带样式的文本。图片也不只是一个 `img` 标签。标签页组件包含标签、面板、ID、活动状态和可访问角色。Tiptap 让我们能够将这些内容建模为编辑器内容,而不是事后试图从文本框中推断它们。

HTML 往返转换才是关键

许多 WYSIWYG 迁移失败,是因为编辑器需要一种格式,而网站渲染的是另一种格式。

我们不希望这样。前端已经在商品页、内容页、首页区块、结账相关位置以及其他 PageBuilder 区域中渲染 HTML 区块。编辑器需要加载现有 HTML,让管理员修改它,并保存公共店面能够安全渲染的 HTML。

Tiptap 为此提供了转换工具。对于标签页面板,我们使用 `generateJSON()` 将现有 HTML 转换为编辑器内容,再使用 `generateHTML()` 将面板内容转换回 HTML。这样既能保持编辑界面的结构化,又能保留网站公开输出的 HTML。

这对 SEO 也很重要。CTA 仍然是锚点。标题仍然是标题。图片仍然是带有 alt 文本和标题的语义化 figure。标签页仍然保留可抓取的面板内容。我们没有把电商文案埋进一个只能由客户端运行的组件中,让搜索引擎或辅助技术去猜测其内容。

对商家来说简单,对代码来说严格

管理后台 UI 隐藏了大部分复杂性。

编辑者看到的是工具栏按钮、对话框、布局卡片、图片字段和媒体选择器。他们可以选中文本,并使用浮动 BubbleMenu 进行格式设置。他们可以选择两列或三列布局,而不必记住 Bootstrap class。他们可以添加标签页,并在保存前预览第一个面板。

而底层代码保持严格:

链接只接受允许的协议
图片 URL 在插入前会被规范化
Instagram 嵌入会被简化为允许的永久链接数据
标签页数量会限制在 2 到 20 之间
生成的 ID 会被规范化为稳定且安全的字符
通过 Tiptap 的 editable 标志遵循禁用状态
粘贴的 Instagram 嵌入会被转换为编辑器节点,而不是 script 内容块

这正是我喜欢这个实现的原因。UI 体验足够宽容,但保存的输出受到控制。

安全性不是可选项

当保存路径信任浏览器返回的任何内容时,富文本编辑器就会变得危险。

我们围绕公共渲染添加了专用的富文本清理层。它使用 DOMPurify,并明确列出允许的标签和属性。在内容进入 React 原始 HTML 接收点之前,它会移除可执行脚本和可执行标记。它还会规范化 Instagram 嵌入数据,并从 URL 属性中移除被阻止的 URL 协议。

渲染测试覆盖了电商页面构建器中真正重要的场景:

响应式列保持完整
编辑器创建的按钮仍然可抓取
图片以延迟加载的语义化 figure 形式渲染
间隔块和字号 class 在渲染后仍然保留
安全的 Instagram 嵌入保留永久链接并移除 script 标签
标签页保留 `tablist` 和 `tabpanel` 语义
旧版 CMS 图片网格在标签页中仍能正常工作
可执行标记会在公共渲染前被移除

这就是“我们加入了一个 WYSIWYG 编辑器”和“我们可以在生产环境中让人们使用它”之间的区别。

分支历史讲述了真实过程

首次提交规模很大:修改了 18 个文件,新增 6,282 行,删除 187 行。它为两个店面应用加入了 Tiptap 依赖、一个 3,000 行的编辑器组件、超过 1,100 行的编辑器 SCSS、渲染测试、管理后台控件、布局处理以及清理路径。

接下来是完善阶段。`d092141d` 改进了 HTML 区块编辑器和导航交互。`320591ec` 增加了英语、瑞典语和法语翻译覆盖,移除了一个媒体选择器 hook,加强了编辑器行为,并让标签页更加灵活。`2c7928b9` 通过 ID 对媒体库图片进行去重。

这就是编辑器开发的真实规律。第一个版本证明编辑器可以存在。后续提交则让它真正可用。

Tiptap 帮助最大的地方

Tiptap 在三个方面提供了很大帮助。

首先,它让编辑器核心变得平淡可靠。我们不需要自行发明选区、命令、撤销/重做、键盘行为或浮动菜单。React 集成和 StarterKit 为我们提供了稳定基础。

其次,它让我们能够对电商专属区块进行建模,而不必将它们隐藏在脆弱的字符串操作中。自定义节点和命令让按钮、图片、列、标签页和嵌入拥有真正的结构。

第三,它让我们能够保留现有的渲染契约。由于公共店面已经依赖 HTML 区块,我们可以继续存储和渲染 HTML,同时在合适的地方于内部使用结构化编辑器内容。

这种组合很少见。许多编辑器在需要自定义输出之前都很容易使用。许多自定义编辑器在需要正常的写作体验之前都很灵活。Tiptap 处于两者之间一个非常实用的位置。

权衡

Tiptap 并不会替你做出产品决策。

你仍然需要决定允许哪些内容类型、哪些 HTML 可以保留、如何选择图片、如何验证链接、粘贴内容应如何处理、翻译如何工作、公共渲染路径如何清理内容,以及应该给予商家多大的自由度。

对于博客编辑器来说,Tiptap 可以快速上手。对于电商 PageBuilder 来说,大部分工作都围绕 Tiptap 展开:旧版兼容性、渲染测试、媒体工作流、可访问性、SEO、翻译和防护规则。

这没有问题。一个优秀的无头编辑器应该提供基础能力,而不是假装你的业务规则不存在。

我的结论

对于这类工作,我还会再次使用 Tiptap。

这个实现让我们获得了一个实用的 Tiptap React 编辑器,同时没有抛弃现有的 PageBuilder 系统。商家获得了更安全的编辑界面。开发者保留了可预测的 HTML。SEO 关键内容仍然可抓取。店面不依赖脆弱的、只能由客户端完成的渲染技巧。

这就是我希望电商管理工具达到的标准:表面简单,输出严格,并且足够平淡可靠,让人们在首次上线后也敢于信任它。

来源