Lexical
Meta 出品的可扩展、高性能富文本编辑器框架,驱动 Facebook、Instagram、WhatsApp 等产品的编辑体验。
Lexical 是 Meta 开发的下一代富文本编辑器框架,采用 TypeScript 编写和不可变状态模型,通过单向数据流确保状态可预测,支持四种核心节点类型灵活组合,已在 Facebook、Instagram、WhatsApp 等产品大规模验证。
Lexical
Meta 出品的可扩展、高性能富文本编辑器框架,驱动 Facebook、Instagram、WhatsApp 等产品的编辑体验。
技术简介说明
Lexical 是 Meta(Facebook)开发并开源的富文本编辑器框架。它诞生于 Meta 内部多个产品(Facebook、Instagram、Workplace、Messenger、WhatsApp)对编辑器的共同需求,是 Meta 在放弃 Draft.js 之后重新设计的下一代编辑器解决方案。
Lexical 的核心设计围绕可靠性、可访问性、性能和可扩展性四大原则。它使用 TypeScript 编写,采用不可变的编辑器状态模型,通过 EditorState → Update 的单向数据流确保状态的可预测性。其节点系统支持四种核心类型(RootNode、ElementNode、TextNode、DecoratorNode),可灵活组合构建任意复杂的文档结构。
作为 2025–2026 年增长最快的编辑器框架之一,Lexical 的 GitHub Stars 从 2024 年初的 ~15K 增长到 2026 年的 ~23K+,npm 周下载量达到 3.2M。Meta 自身的大规模生产验证赋予了 Lexical 独特的可信度。
基本信息
- 官网:https://lexical.dev/
- GitHub:https://github.com/facebook/lexical
- License:MIT
- 最新版本:v0.46.0(2026 年 6 月)
- 主要维护者/公司:Meta(Facebook)
- GitHub Stars:~23,300+
- npm 周下载量:~3.2M
- 框架支持:React(主要)/ iOS / 通用
快速上手
安装
# 核心包
npm install lexical
# React 集成
npm install @lexical/react
# 富文本编辑插件
npm install @lexical/rich-text
# 常用功能包
npm install @lexical/list # 列表
npm install @lexical/link # 链接
npm install @lexical/table # 表格
npm install @lexical/code # 代码块
npm install @lexical/history # 撤销/重做
npm install @lexical/clipboard # 剪贴板
npm install @lexical/markdown # Markdown 支持
npm install @lexical/utils # 工具函数基础配置
import { createEditor } from 'lexical'
import { RichTextPlugin } from '@lexical/react/LexicalRichTextPlugin'
import { ContentEditable } from '@lexical/react/LexicalContentEditable'
import { HistoryPlugin } from '@lexical/react/LexicalHistoryPlugin'
import { LexicalErrorBoundary } from '@lexical/react/LexicalErrorBoundary'最小示例(React)
import { LexicalComposer } from '@lexical/react/LexicalComposer'
import { RichTextPlugin } from '@lexical/react/LexicalRichTextPlugin'
import { ContentEditable } from '@lexical/react/LexicalContentEditable'
import { HistoryPlugin } from '@lexical/react/LexicalHistoryPlugin'
import { LexicalErrorBoundary } from '@lexical/react/LexicalErrorBoundary'
import { HeadingNode, QuoteNode } from '@lexical/rich-text'
import { ListNode, ListItemNode } from '@lexical/list'
const theme = {
heading: {
h1: 'editor-heading-h1',
h2: 'editor-heading-h2',
},
list: {
ol: 'editor-list-ol',
ul: 'editor-list-ul',
listitem: 'editor-listitem',
},
text: {
bold: 'editor-text-bold',
italic: 'editor-text-italic',
underline: 'editor-text-underline',
},
}
const editorConfig = {
namespace: 'MyEditor',
theme,
onError(error: Error) {
throw error
},
nodes: [HeadingNode, QuoteNode, ListNode, ListItemNode],
}
export default function Editor() {
return (
<LexicalComposer initialConfig={editorConfig}>
<RichTextPlugin
contentEditable={<ContentEditable className="editor-input" />}
placeholder={<div className="editor-placeholder">开始编辑...</div>}
ErrorBoundary={LexicalErrorBoundary}
/>
<HistoryPlugin />
</LexicalComposer>
)
}自定义节点
import {
DecoratorNode,
EditorConfig,
LexicalEditor,
LexicalNode,
NodeKey,
SerializedLexicalNode,
} from 'lexical'
export type SerializedImageNode = SerializedLexicalNode & {
src: string
altText: string
}
export class ImageNode extends DecoratorNode<JSX.Element> {
__src: string
__altText: string
static getType(): string {
return 'image'
}
static clone(node: ImageNode): ImageNode {
return new ImageNode(node.__src, node.__altText, node.__key)
}
constructor(src: string, altText: string, key?: NodeKey) {
super(key)
this.__src = src
this.__altText = altText
}
createDOM(_config: EditorConfig): HTMLElement {
const span = document.createElement('span')
span.setAttribute('data-lexical-image', 'true')
return span
}
decorate(): JSX.Element {
return (
<img
src={this.__src}
alt={this.__altText}
style={{ maxWidth: '100%' }}
/>
)
}
serialize(): SerializedImageNode {
return {
...super.serialize(),
type: 'image',
src: this.__src,
altText: this.__altText,
}
}
static importJSON(json: SerializedImageNode): ImageNode {
return $createImageNode(json.src, json.altText)
}
}
export function $createImageNode(src: string, altText: string): ImageNode {
return new ImageNode(src, altText)
}
export function $isImageNode(node: LexicalNode | null | undefined): node is ImageNode {
return node instanceof ImageNode
}核心概念与架构
架构设计
Lexical 的架构围绕以下核心原则:
- 不可变状态:EditorState 是不可变的快照,每次更新产生新的状态
- 单向数据流:用户输入 → Transaction → Update → 新 EditorState
- 节点系统:四种核心节点类型构成文档树
- 插件系统:通过 Composer 模式组合功能
- 框架无关核心:
lexical核心包不绑定任何框架
核心概念
- Editor:编辑器实例,管理状态和更新循环
- EditorState:不可变的编辑器状态快照,包含完整的节点树
- Node:文档树的节点,四种核心类型:
RootNode:根节点ElementNode:容器节点(段落、标题、列表等)TextNode:文本叶子节点DecoratorNode:装饰节点(嵌入 React 组件、图片等)
- Command:命令系统,通过优先级传播处理用户意图
- Transform:节点级别的自动转换规则
- Listener:监听编辑器事件(选择变化、内容变化等)
- Update:每次状态变更触发 Update 回调
Lexical Extensions(2026 新特性)
// Lexical Extensions 是模块化的配置和行为组合
import { createEditor } from 'lexical'
const editor = createEditor({
extensions: [
// 框架无关的功能组合
myRichTextExtension,
myCollaborationExtension,
],
})核心特性
- Meta 生产验证:驱动 Facebook、Instagram、Messenger、WhatsApp 等大规模产品
- TypeScript 原生:完整的 TypeScript 类型支持
- 不可变状态:函数式状态管理,确保可预测性
- 四种核心节点:Root、Element、Text、Decorator 灵活组合
- Named Slots(v0.46.0):实验性特性,让装饰节点管理多个子区域
- DOMImportExtension(v0.45.0):实验性 DOM 导入 API
- Lexical Extensions:模块化、框架无关的功能组合模式
- 协作编辑:通过 @lexical/react 的 CollaborationPlugin 支持
- Markdown 往返:支持 Markdown 的双向转换
- AI 演示:官方展示基于 WebAssembly 的浏览器内 AI(SmolLM2、BERT-NER)
- Headless SSR:@lexical/headless 支持服务端编辑
- LexKit:基于 Lexical 的上层 React 框架
生态图
核心包
| 包名 | 说明 |
|---|---|
lexical | 核心引擎 |
@lexical/react | React 集成(Composer、Plugin、Hook) |
@lexical/rich-text | 富文本编辑能力 |
@lexical/list | 列表支持 |
@lexical/link | 链接支持 |
@lexical/table | 表格支持 |
@lexical/code | 代码块支持 |
@lexical/history | 撤销/重做 |
@lexical/clipboard | 剪贴板处理 |
@lexical/markdown | Markdown 转换 |
@lexical/headless | 无头/服务端编辑 |
@lexical/utils | 工具函数 |
@lexical/extension | 扩展系统(2026 新增) |
@lexical/yjs | Yjs 协作集成 |
上层生态
- LexKit:基于 Lexical 的开源 React 编辑器框架
- 拖拽块、可扩展组件、简化 API
- https://lexkit.dev/
- Liveblocks:提供 Lexical 协作编辑集成
对比生态
Lexical 与 TipTap、Slate、Quill 是 2025–2026 年 React 富文本编辑器的四大选择。
适用场景
- 大规模社交/消息产品:Facebook、Instagram 级别的编辑需求(最佳选择)
- 高性能编辑器:对性能有严格要求的场景
- React 项目:@lexical/react 提供最成熟的集成
- React Native:支持 React Native 平台
- AI 驱动编辑:利用 WebAssembly 在浏览器内运行 AI 模型
- 复杂内容编辑:需要深度嵌套和自定义节点的场景
- CMS 内容管理:与 Payload CMS、Strapi、Webiny 等 Headless CMS 集成
开发与工程化
开发流程
# 克隆仓库
git clone https://github.com/facebook/lexical.git
cd lexical
# 安装依赖
npm install
# 构建
npm run build
# 运行开发服务器
npm run dev
# 测试
npm run test-unit
npm run test-e2e命令系统
import { useLexicalComposerContext } from '@lexical/react/LexicalComposerContext'
import { $getSelection, $createParagraphNode, $createTextNode } from 'lexical'
import { useEffect } from 'react'
function MyPlugin() {
const [editor] = useLexicalComposerContext()
useEffect(() => {
// 注册命令
return editor.registerCommand(
MY_COMMAND,
(payload) => {
editor.update(() => {
const selection = $getSelection()
// 处理命令...
})
return true // 已处理
},
// 命令优先级
COMMAND_PRIORITY_LOW
)
}, [editor])
return null
}Transform 系统
// Transform 在节点变化时自动运行
editor.registerNodeTransform(TextNode, (textNode) => {
// 自动将 ":)" 转换为表情
if (textNode.__text === ':)') {
textNode.replace($createEmojiNode('😊'))
}
})性能与安全
性能特点
- 高效更新:不可变状态 + diff 算法,最小化 DOM 更新
- 大文档支持:Lexical 的节点模型在大规模内容下表现良好
- Meta 验证:在 Facebook 等超大用户基数产品中经过生产验证
性能注意事项
- 包体积较大(核心包比 TipTap 和 Slate 更重)
- 避免在 Transform 中创建循环依赖
- 合理使用 DecoratorNode 减少重渲染范围
- 长文档考虑虚拟滚动
安全注意
- Meta 的安全审查流程确保代码质量
- 对用户输入的内容进行 HTML 消毒
- 自定义节点的
createDOM方法注意 XSS 防护 - 粘贴内容的 DOM 导入需经过验证
技术对比
| 特性 | Lexical | TipTap | Slate | Quill | CKEditor 5 |
|---|---|---|---|---|---|
| 底层 | 自研 | ProseMirror | 自研 | Parchment | 自研 MVC |
| 框架 | React/通用 | React/Vue/Svelte | React | 框架无关 | React/Vue/Angular |
| TypeScript | 原生 | 原生(3.0 增强) | 支持 | 2.0 重写 | TypeScript |
| 纯装饰 | ❌ | ✅ | ✅ | ❌ | ✅ |
| 协作编辑 | ✅ 支持 | ✅ 付费 | slate-yjs | 需自建 | ✅ 付费 |
| SSR | ✅ headless | ✅ 3.0 原生 | ❌ | ❌ | 有限 |
| Yjs 集成 | ✅ 但有限制 | ✅ y-tiptap | ✅ slate-yjs | 需自建 | ❌ 私有云 |
| 包体积 | 较大 | 较小 | 中等 | 较大 | 大 |
| 学习曲线 | 较陡 | 中等 | 较陡 | 低 | 中等 |
| AI 集成 | 实验性 | ✅ AI Toolkit | 需自建 | 需自建 | ✅ AI Assistant |
| Meta 验证 | ✅ | ❌ | Discord 等 | 广泛使用 | 企业广泛 |
Yjs 协作的限制
Lexical 的 Yjs 集成存在已知限制:
- Yjs 协作中硬编码了根节点名称,限制每个 Yjs 文档只能有一个编辑器
- 协作功能相比 TipTap 的 y-tiptap 不够成熟
最佳实践
- 使用 Composer 模式:通过
LexicalComposer包裹编辑器,统一管理配置 - 合理设计节点系统:自定义节点时注意
importJSON/exportJSON的对称性 - Command 优先级:合理使用
COMMAND_PRIORITY控制命令传播 - Transform 谨慎使用:Transform 在每次节点变化时运行,避免重计算
- 错误边界:始终使用
LexicalErrorBoundary包裹编辑器 - 主题系统:使用主题对象集中管理 CSS 类名
- 测试自定义节点:确保序列化/反序列化的正确性,这对协作编辑至关重要
技术局限与边界
- 学习曲线陡峭:节点系统、Command 系统、Transform 等概念较多
- 包体积较大:核心包比 TipTap、Slate 更重
- 无纯装饰:缺乏纯装饰(pure decorations)支持,协作光标等需要 DOM workaround
- Yjs 集成有限制:硬编码根节点名称,一个 Yjs 文档只能一个编辑器
- 框架支持不均:React 集成最成熟,其他框架支持有限
- 仍在 0.x 阶段:API 可能随版本更新有 breaking change
- 社区资源少于 TipTap:教程和第三方资源相对较少
- iOS 支持实验性:Lexical iOS 仍处于早期阶段
学习资源
- 官方文档:https://lexical.dev/docs/intro
- 概念指南:https://lexical.dev/docs/concepts/editor-state
- API 文档:https://lexical.dev/docs/api
- 示例:https://lexical.dev/docs/examples
- GitHub 仓库:https://github.com/facebook/lexical
- Changelog:https://github.com/facebook/lexical/blob/main/CHANGELOG.md
- LexKit:https://lexkit.dev/
- 社区 Discord:Lexical 官方 Discord 服务器
2026 年现状
最新版本
- v0.46.0(2026 年 6 月):Named Slots(实验性)
- v0.45.0(2026 年 5 月):DOMImportExtension(实验性)
- 发布频率:约每月一个版本
发展趋势
- Named Slots(v0.46.0):允许装饰节点在单个宿主元素中管理多个命名子区域
- DOMImportExtension(v0.45.0):全新的 DOM 导入 API,改进粘贴和剪贴板处理
- Lexical Extensions:模块化、框架无关的功能组合新模式
- AI 集成深化:基于 WebAssembly 的浏览器内 AI(SmolLM2 + BERT-NER)
- LexKit 生态:基于 Lexical 的上层框架持续完善
- 协作改进:持续改进 Yjs 集成和实时协作能力
社区活跃度
- GitHub Stars:~23,300+(2024 年初 ~15K,增长最快的编辑器框架)
- npm 周下载量:~3.2M
- Meta 内部持续投入,多个产品线依赖
- 月度版本发布节奏稳定
定位总结
Lexical 是 2026 年增长最快的富文本编辑器框架,Meta 的大规模生产验证是其最大背书。适合对性能、可靠性有严格要求的 React 项目。如果你需要跨框架支持(Vue/Svelte),TipTap 是更成熟的选择;如果需要极致的底层控制,Slate 可能更合适。