Payload 与 Lexical 富文本编辑器完全指南:@payloadcms/richtext-lexical 的安装、配置与功能扩展
2026/9/10 13:58:02 网站建设 项目流程

Payload 与 Lexical 富文本编辑器完全指南:@payloadcms/richtext-lexical 的安装、配置与功能扩展

【免费下载链接】payloadPayload is the open-source, fullstack Next.js framework, giving you instant backend superpowers. Get a full TypeScript backend and admin panel instantly. Use Payload as a headless CMS or for building powerful applications.项目地址: https://gitcode.com/GitHub_Trending/pa/payload

@payloadcms/richtext-lexical 是 Payload 官方为 Lexical(Meta 开源的富文本框架)开发的富文本编辑器适配器,为 Payload CMS 的richText字段提供编辑与序列化能力。本文以该包的 README 为骨架,结合仓库内的源码、类型定义与配套文档,系统讲解它的安装方式、接入 Payload 配置的两种写法、lexicalEditor的四个核心参数、基于 Feature 的扩展模型、默认启用的功能清单,以及客户端/服务端渲染与内容转换的使用要点,帮助你把一个默认可用的富文本编辑器逐步改造成贴合业务需求的定制化编辑器。

一、包定位:Payload 官方的 Lexical 富文本适配器

在 Payload 体系中,富文本能力并不内置在核心包里,而是通过「编辑器适配器」的形式提供。@payloadcms/richtext-lexical就是官方维护的那一个,它的package.jsondescription字段写得很直白:“The officially supported Lexical richtext adapter for Payload”。查看 packages/richtext-lexical/package.json 可以看到:

  • 包名:@payloadcms/richtext-lexical(仓库内当前版本为4.0.0-canary.14
  • 许可证:MIT
  • 与 Lexical 相关依赖锁定在0.48.0lexical@lexical/headless@lexical/html@lexical/link@lexical/list@lexical/markdown@lexical/react@lexical/rich-text@lexical/table@lexical/utils等均为同一版本)
  • peerDependencies要求:payload、React^19.0.1 || ^19.1.2 || ^19.2.1react-dom同版本,以及 UI 相关的@faceless-ui/modal@faceless-ui/scroll-info
  • engines.node要求:>= 24.15.0

在仓库根目录的 docs/getting-started/concepts.mdx 与 docs/migration-guide/v4.mdx 中同样印证了它在 Payload 生态中的地位:从 Payload 4.0 起,@payloadcms/richtext-lexical是唯一受官方支持的富文本编辑器,旧的@payloadcms/richtext-slate包已被移除。

说明:本仓库是一个包含packages/richtext-lexical源码、docs/文档与test/测试在内的 Payload monorepo。下文提到的配置示例、功能清单与代码路径均来自仓库当前状态,适用时以仓库实际代码为准。

二、安装与依赖环境

README 给出了最简安装命令(npm):

npm install @payloadcms/richtext-lexical

由于本仓库使用 pnpm workspace 管理,docs/rich-text/overview.mdx 也提供了 pnpm 与“常用编辑器周边包一并安装”的写法:

# 使用 pnpm 安装 pnpm install @payloadcms/richtext-lexical # 安装富文本编辑器 + 图片处理 + GraphQL(如果用到) pnpm i @payloadcms/richtext-lexical sharp graphql

getting-started/installation.mdx 还提醒:如果你完全不使用富文本,也可以不安装本包。

安装时需要留意几个由 packages/richtext-lexical/package.json 明示的运行前提:

项目要求
Node.js>= 24.15.0
Payload作为 peer dependency(仓库中以workspace:*关联)
React / React DOM^19.0.1 || ^19.1.2 || ^19.2.1
Lexical 系列依赖统一为0.48.0(由包自身带齐,无需手动安装)

三、接入 Payload:根配置与逐字段配置

README 中的 Usage 展示了最核心的接入方式——在buildConfig中把lexicalEditor()赋给顶层的editor字段:

import { buildConfig } from 'payload' import { lexicalEditor } from '@payloadcms/richtext-lexical' export default buildConfig({ editor: lexicalEditor({}), // ...rest of config })

editor一旦在根配置中声明,所有type: 'richText'字段默认都会使用这个编辑器。官方文档 docs/rich-text/overview.mdx 补充了两个实用细节:

  1. 一个配置就够了,不需要为每个字段重复声明——顶层配置中的编辑器会作为全局默认。
  2. 你可以按字段覆盖设置。例如在某个 Collection 里给content字段单独传入另一个lexicalEditor(...),字段级配置会覆盖(而不是合并)全局配置:
import type { CollectionConfig } from 'payload' import { lexicalEditor } from '@payloadcms/richtext-lexical' export const Pages: CollectionConfig = { slug: 'pages', fields: [ { name: 'content', type: 'richText', // 在此字段上使用(可以覆盖顶层设置的)Lexical 编辑器 editor: lexicalEditor({}), }, ], }

为什么字段级配置的覆盖能力这么强?因为从源码结构看,richText字段本身就只是一个普通字段类型,它的editor属性可以指向任意实现了 PayloadRichTextAdapter接口的对象。lexicalEditor()返回的正是一个这样的适配器 Provider(见 packages/richtext-lexical/src/types/index.ts 中LexicalRichTextAdapterProvider的定义),Payload 在配置净化(sanitization)阶段会调用它并注入净化后的全局config,从而得到包含editorConfigfeaturesLexicalRichTextAdapter(该调用链可在 packages/richtext-lexical/src/index.ts 看到)。

另外要提醒的是:如果整个项目的富文本统一使用同一套设置,直接在根editor配置即可;只有像“内容区用全功能编辑器、摘要区只允许纯段落”这类差异化诉求,才适合在字段级单独配置。

四、lexicalEditor 的可配置参数

lexicalEditor接受一个可选的LexicalEditorProps参数对象。从 packages/richtext-lexical/src/types/index.ts 可以看到它的完整形状:

export type LexicalEditorProps = { admin?: LexicalFieldAdminProps features?: FeaturesInput lexical?: LexicalEditorConfig views?: PayloadComponent }

admin:管理后台表现

admin用来控制编辑器在 Admin Panel 中的界面表现。对应类型LexicalFieldAdminProps(见 packages/richtext-lexical/src/types/index.ts)提供了如下选项:

属性默认值作用
placeholder-编辑器为空时显示的占位文案(LabelFunction或静态文本)
hideGutterfalse隐藏编辑器左侧的沟槽(灰色竖线与内边距区域)
hideInsertParagraphAtEndfalse隐藏编辑器末尾出现的“+”按钮(快速插入段落)
hideDraggableBlockElementfalse隐藏悬停节点时出现的拖拽手柄
hideAddBlockButtonfalse隐藏悬停节点时出现的“添加块”按钮

官方文档 docs/rich-text/overview.mdx 给出了两个最常见的用法示例:

{ name: 'richText', type: 'richText', editor: lexicalEditor({ admin: { hideGutter: true, // 关闭左侧沟槽,让内容更贴近页面边缘 }, }), }
{ name: 'richText', type: 'richText', editor: lexicalEditor({ admin: { placeholder: 'Type your content here...', // 自定义空状态占位文案 }, }), }

features:扩展与裁剪能力

features是本包最重要的扩展点。它既可以是一个 Feature 数组,也可以是一个接收{ defaultFeatures, rootFeatures }并返回数组的函数(对应类型FeaturesInput,见 packages/richtext-lexical/src/types/index.ts):

editor: lexicalEditor({ features: ({ defaultFeatures }) => [...defaultFeatures, FixedToolbarFeature()], })

两个回调参数的语义:

参数含义
defaultFeatures官方推荐的“默认功能”数组。展开它们可以得到一个功能完整的开箱即用编辑器;也可以从中删掉某些功能实现精简
rootFeatures根富文本编辑器(在根payload.config.ts中定义的那个)已启用的功能数组。如果当前字段就是根编辑器,或根编辑器不是 Lexical,则该数组为空

lexical:底层 Lexical 配置

lexical可以直接覆盖 Lexical 引擎本身的EditorConfig(主题theme、节点注册等)。如果你想在改一小点的同时又保留默认配置,最稳妥的方式是用“接收默认配置并返回新配置”的函数写法。文档 packages/richtext-lexical/src/types/index.ts 中的类型注释给出了示例:

lexical: (defaultConfig) => ({ ...defaultConfig, theme: { ...defaultConfig.theme, paragraph: 'my-paragraph' }, })

views:多视图渲染

views允许为同一批 Lexical 节点定义多套渲染逻辑(如defaultpreviewdebug等命名视图),在编辑器与 JSX 转换器之间保持一致渲染。它以带#exportName的导入路径字符串指定视图映射文件,例如文档 docs/rich-text/overview.mdx 中:

editor: lexicalEditor({ // 使用 ./views.js 中导出的 postViews 视图映射 views: './views.js#postViews', }),

五、Feature 机制:默认能力与自定义扩展

默认包含哪些 Feature

调用lexicalEditor({})且不传features时,源码会直接使用defaultEditorFeatures(见 packages/richtext-lexical/src/index.ts,它来自 packages/richtext-lexical/src/lexical/config/server/default.ts)。该默认数组在当前仓库中包含:

类别Feature
行内格式BoldFeature()ItalicFeature()UnderlineFeature()StrikethroughFeature()SubscriptFeature()SuperscriptFeature()InlineCodeFeature()
块结构ParagraphFeature()HeadingFeature()AlignFeature()IndentFeature()BlockquoteFeature()HorizontalRuleFeature()
列表UnorderedListFeature()OrderedListFeature()ChecklistFeature()
内容引用LinkFeature()RelationshipFeature()UploadFeature()
工具栏InlineToolbarFeature()

从源码的默认列表看,仓库并未把FixedToolbarFeature()计入默认——也就是说默认是行内浮动工具栏。如果你习惯固定在顶部的工具栏,需要手动追加:

import { FixedToolbarFeature, lexicalEditor } from '@payloadcms/richtext-lexical' editor: lexicalEditor({ features: ({ defaultFeatures }) => [...defaultFeatures, FixedToolbarFeature()], })

若把defaultFeatures整个清空,得到的就是一个近乎空白的编辑器——这正是 Feature 模型的意义:需要什么就加什么,甚至可以从零构建自定义 Feature(官方仓库中featurestoolbars等目录的源码结构可作为自行实现的参考,见 packages/richtext-lexical/src/features)。

用官方 Feature 组装复杂编辑器

在根编辑器上扩展能力时,最典型的做法是把BlocksFeature(复用 Payload Block 作为富文本块)、LinkFeatureUploadFeature一起组合进去。仓库文档 docs/rich-text/overview.mdx 给出了一个完整的例子:

import { BlocksFeature, LinkFeature, UploadFeature, lexicalEditor, } from '@payloadcms/richtext-lexical' import { Banner } from '../blocks/Banner' import { CallToAction } from '../blocks/CallToAction' { editor: lexicalEditor({ features: ({ defaultFeatures, rootFeatures }) => [ ...defaultFeatures, LinkFeature({ // 演示如何给 LinkFeature 内置的字段追加自定义字段 fields: ({ defaultFields }) => [ ...defaultFields, { name: 'rel', label: 'Rel Attribute', type: 'select', hasMany: true, options: ['noopener', 'noreferrer', 'nofollow'], admin: { description: 'The rel attribute defines the relationship between a linked resource and the current document.', }, }, ], }), UploadFeature({ collections: { uploads: { // 演示如何给上传节点追加字段 fields: [ { name: 'caption', type: 'richText', editor: lexicalEditor(), }, ], }, }, }), // 直接复用 Payload 的 Block 作为富文本内容块 BlocksFeature({ blocks: [Banner, CallToAction], }), ], }) }

提示:将BlocksFeature纳入编辑器后,前端渲染时仍会按 Payload Block 的模式读取字段数据。官方功能的全量介绍见仓库内的 docs/rich-text/official-features.mdx,自定义 Feature 的开发指引见 docs/rich-text/custom-features.mdx。

六、源码视角:lexicalEditor 运行时做了什么

深入阅读入口 packages/richtext-lexical/src/index.ts 可以帮助你理解这套配置体系背后的机制:

  1. 版本一致性检查。非生产环境且未设置环境变量PAYLOAD_DISABLE_DEPENDENCY_CHECKER=true时,首次调用lexicalEditor会执行checkDependencies,将lexical与各@lexical/*包的版本统一约束到lexicalTargetVersion = '0.48.0'(见index.tslexicalTargetVersion常量与相关逻辑)。如果项目中残留多个不同版本的 lexical,会在开发期得到明确告警。

  2. 配置净化(sanitization)。若未传args或既没传features也没传lexical,则直接采用缓存过的getDefaultSanitizedEditorConfigdefaultEditorFeatures;否则进入featuresInputToEditorConfig,把函数式/数组式的features输入解析成按依赖排序的 feature 列表与去重的解析结果映射(相关实现见 packages/richtext-lexical/src/utilities/editorConfigFactory.ts)。

  3. i18n 注入。每个 Feature 可以携带自己的多语言词条。lexicalEditor会把它们按当前 config 支持的语言合并进全局config.i18n.translations(通过deepMergeSimple),保证管理后台出现的新按钮文案随语言切换(index.ts中可见featureI18nsupportedLanguagesToMerge等处理逻辑)。

  4. 返回一套完整适配器。最终返回的对象同时提供服务端渲染所需的editorConfigfeatures,管理后台的字段/单元格组件(如RscEntryLexicalFieldRscEntryLexicalCell,通过@payloadcms/richtext-lexical/rsc子路径引用)、GraphQL 关联数据填充逻辑graphQLPopulationPromises、字段 hooks、JSON Schema 以及验证函数richTextValidateHOC。也就是说,编辑、存储校验、GraphQL 查询和类型生成全都在适配器层被串联起来了。

  5. 公开的类型与工具index.ts还导出了大量序列化节点类型、Feature 类型与实用函数,例如convertHTMLToLexicalconvertLexicalToMarkdownconvertMarkdownToLexicalbuildEditorStatehasText等,供上层按需引入。

七、数据格式、类型与前端渲染

存储与读取格式

富文本内容在数据库中保存的是 Lexical 序列化 JSON,而不是 HTML。要交给浏览器渲染时,需要走转换器。README 所指的“更详细用法见官方文档”,在仓库里对应的是 docs/rich-text/overview.mdx、docs/rich-text/converting-html.mdx、docs/rich-text/converting-markdown.mdx 与 docs/rich-text/rendering-on-demand.mdx 等页面。

类型安全

包为每一个节点都导出了以Serialized前缀命名的类型,例如SerializedParagraphNodeSerializedTextNodeSerializedLinkNodeSerializedUploadNodeSerializedBlockNode。类型化的编辑器状态可以这样构造(示例见 docs/rich-text/overview.mdx):

import type { TypedEditorState, SerializedParagraphNode, SerializedTextNode } from '@payloadcms/richtext-lexical' const state: TypedEditorState<SerializedParagraphNode | SerializedTextNode> = { root: { type: 'root', direction: 'ltr', format: '', indent: 0, version: 1, children: [ { children: [ { detail: 0, format: 0, mode: 'normal', style: '', text: 'Some text. Every property here is fully-typed', type: 'text', version: 1, }, ], direction: 'ltr', format: '', indent: 0, type: 'paragraph', textFormat: 0, version: 1, }, ], }, }

如果你启用了类型生成(payload generate:types),那么每个richText字段的类型会被自动按该编辑器实际启用的功能收敛成精确的节点联合,例如Post['richText'],配合buildEditorState<Post['richText']>({ text: 'Hello world' })即可类型安全地构造初始状态;而无需手工拼一个巨大的节点联合。相关辅助类型(DefaultTypedEditorStateRichTextNodes等)都从@payloadcms/richtext-lexical主入口导出。

判空工具

一个容易踩的坑是:内容被清空后,字段值不是null,而是一个“只含空段落”的 JSON 对象。文档 docs/rich-text/overview.mdx 推荐使用专门的判空工具:

import { hasText } from '@payloadcms/richtext-lexical/shared' hasText(richtextData)

渲染到 HTML

服务端按需渲染最直接的方式是用 HTML 转换器(子路径@payloadcms/richtext-lexical/html):

import { convertLexicalToHTML } from '@payloadcms/richtext-lexical/html' const html = convertLexicalToHTML({ data: post.richText })

八、子路径导出一览

与 Payload 的管理后台和前端渲染架构相匹配,本包提供了非常细化的 package exports。参考 packages/richtext-lexical/package.json,常用的子路径如下:

子路径用途
@payloadcms/richtext-lexical主入口:lexicalEditor、全部 Feature、序列化类型与核心工具
@payloadcms/richtext-lexical/client管理后台可用的客户端组件与 Hooks(如块组件 UI 原语)
@payloadcms/richtext-lexical/reactReact 渲染相关导出
@payloadcms/richtext-lexical/rscReact Server Components 入口(RSC 字段/单元格组件)
@payloadcms/richtext-lexical/htmlHTML 转换(convertLexicalToHTML
@payloadcms/richtext-lexical/html-async异步 HTML 转换(含lexicalHTMLField同步字段等)
@payloadcms/richtext-lexical/plaintext纯文本转换
@payloadcms/richtext-lexical/lexical直通lexical@lexical/*各子包(linklistmarkdownreact/*插件等)
@payloadcms/richtext-lexical/ast/mdxMDX/AST 相关服务端能力
@payloadcms/richtext-lexical/shared前后端共享工具(如hasText

九、更进一步:仓库内的学习资料

本仓库同时包含该包的完整文档、源码与测试,建议按以下顺序深入:

  • 包级使用文档与官方功能索引:docs/rich-text/overview.mdx、docs/rich-text/official-features.mdx、docs/fields/rich-text.mdx(字段级配置项与editor参数)
  • 块、关系、上传等官方 Feature 的深入用法:docs/rich-text/blocks.mdx、docs/rich-text/converters.mdx、docs/rich-text/views.mdx
  • 自定义 Feature 的完整开发指南:docs/rich-text/custom-features.mdx、docs/rich-text/converting-jsx.mdx
  • 序列化节点类型与接口定义:packages/richtext-lexical/src/types、packages/richtext-lexical/src/features(可对照每个 Feature 的 server/client 目录了解实现结构)

小结

从一次npm install @payloadcms/richtext-lexical和一行editor: lexicalEditor({})开始,你便为 Payload 的richText字段接入了基于 Lexical 的富文本引擎;随后通过featuresadminlexicalviews四个参数,以及覆盖全部内置格式、列表、链接、关系、上传、Block 等能力的官方 Feature 体系,可以按字段粒度裁剪或增强编辑器能力。存储上它产出强类型的序列化 JSON,渲染上通过rsc/html/plaintext等子路径与转换器在服务端、管理后台与前端之间自由切换。若需要在此基础上构建自己的富文本节点,仓库内的 docs/rich-text/custom-features.mdx 与 packages/richtext-lexical/src/features 的源码结构就是最直接的参照。

【免费下载链接】payloadPayload is the open-source, fullstack Next.js framework, giving you instant backend superpowers. Get a full TypeScript backend and admin panel instantly. Use Payload as a headless CMS or for building powerful applications.项目地址: https://gitcode.com/GitHub_Trending/pa/payload

创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询