You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在聊天应用中优化使用Lexical作为输入组件?

聊天应用中Lexical消息列表渲染的优化方案

针对你提到的消息列表渲染性能问题,不用每条消息都实例化完整Lexical编辑器,也不需要预存HTML,这里有几个成熟的优化方案:

1. 使用Lexical轻量只读渲染器

Lexical官方提供了针对只读场景的轻量渲染组件,不需要加载全套编辑插件和状态管理逻辑,只负责解析保存的Lexical JSON内容并渲染成对应DOM。

实现示例

可以封装一个极简的MessageRenderer组件,只加载必要的只读插件:

import { LexicalComposer } from '@lexical/react/LexicalComposer';
import { RichTextPlugin } from '@lexical/react/LexicalRichTextPlugin';
import { ContentEditable } from '@lexical/react/LexicalContentEditable';

function MessageRenderer({ lexicalJson }) {
  const initialConfig = {
    namespace: 'chat-message-renderer',
    editorState: lexicalJson, // 传入从数据库取出的Lexical JSON状态
    editable: false,
    readOnly: true,
    // 仅保留解析富文本内容的必要插件,移除所有编辑相关插件(如UndoRedo、History)
    plugins: [
      {
        plugin: RichTextPlugin,
        options: {
          contentEditable: <ContentEditable readOnly />,
          placeholder: null,
        },
      },
      // 按需添加格式插件(如ListPlugin、LinkPlugin),仅保留消息中用到的格式
    ],
  };

  return <LexicalComposer initialConfig={initialConfig} />;
}

这个组件比完整编辑器实例轻量得多,同时复用Lexical的原生解析逻辑,既不会因为编辑器更新导致渲染失效,也能避免HTML渲染的XSS风险。

2. 结合虚拟滚动动态挂载

如果消息数量达到数百甚至上千条,虚拟滚动是必须的优化手段。通过react-window、react-virtualized这类库,只渲染视口内的消息项,并且仅当消息进入视口时才挂载MessageRenderer,离开视口时卸载。

核心思路

以react-window为例,列表项仅在进入可视区域时才渲染对应的Lexical只读组件:

import { FixedSizeList as List } from 'react-window';

function MessageList({ messages }) {
  const renderMessage = ({ index, style }) => {
    const message = messages[index];
    return (
      <div style={style}>
        <MessageRenderer lexicalJson={message.lexicalContent} />
      </div>
    );
  };

  return (
    <List
      height={600}
      itemCount={messages.length}
      itemSize={80}
      width="100%"
    >
      {renderMessage}
    </List>
  );
}

这种方式下,即使有上千条消息,实际渲染的Lexical实例只有视口内的十几条,完全不会有性能压力。

3. 简化保存的Lexical JSON结构

保存消息时,除了完整的Lexical状态,还可以生成一个简化版的JSON(移除编辑相关的元数据,比如选择状态、历史记录),这样渲染时解析更快、占用内存更少。

处理示例

在保存消息前,对编辑器状态做精简:

const editorState = editor.getEditorState();
const simplifiedJson = JSON.parse(JSON.stringify(editorState.toJSON(), (key, value) => {
  // 移除编辑相关的非内容字段
  if (['selection', 'history', 'pendingEditorState'].includes(key)) {
    return undefined;
  }
  return value;
}));
// 将simplifiedJson存入数据库

渲染时直接使用这个简化后的JSON,进一步降低解析成本。

方案对比

  • 若消息格式简单(纯文本、基础加粗/斜体),用轻量只读渲染器即可,成本最低。
  • 若消息包含复杂富文本格式(列表、链接、图片),用带必要格式插件的只读组件,兼顾功能和性能。
  • 若消息数量极大,必须结合虚拟滚动,彻底解决大量实例的性能问题。

绝对不推荐预存HTML:一方面Lexical的渲染逻辑可能随版本更新,旧HTML会出现样式或结构不一致;另一方面用户输入的内容若包含恶意HTML,直接渲染会有XSS风险,而Lexical从JSON渲染时会自动做安全过滤。

内容的提问来源于stack exchange,提问作者Andrew Rusinas

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.28 21:03:44