ARTICLE · INTELLIGENCE

战地情报 · 详情页

来自尧图项目组的一线实战观察与深度解析

如何为 Lexical Extension 做按需懒加载(register 中动态 import)?

如何为 Lexical Extension 做按需懒加载(register 中动态 import)? 如何为 Lexical Extension 做按需懒加载register 中动态 import【免费下载链接】lexicalLexical is an extensible text editor framework that provides excellent reliability, accessibility and performance.项目地址: https://gitcode.com/GitHub_Trending/le/lexicalLexical 编辑器由一组 Extension 通过buildEditorFromExtensions构建其中一些 Extension表格、代码高亮、AI 功能等实现体积不小用户未必使用。目标是把这些 Extension 的运行时实现推迟到真正需要时才加载而不是随编辑器主 bundle 一起加载。前提条件编辑器必须通过 Lexical Extension API 创建即buildEditorFromExtensions或使用它内部抽象的LexicalExtensionComposer。Legacy React Plugin 与 Lexical Extensions 兼容但懒加载机制依赖 Extension 的register/afterRegistration生命周期。register 阶段为什么可以异步 import官方 FAQpackages/lexical-website/docs/extensions/faq.mdx明确了懒加载的三条规则不需要框架层面的特殊支持。Extension 中你实现的所有函数必须是同步的但register或afterRegistration函数内部可以执行异步操作动态import()、网络请求等。必须管好清理。你从register返回的 dispose 函数要能正确管理清理也可以用 state 上的getSignal()拿到一个AbortSignal文档说这比在 dispose 里手写清理更方便。Extension 本身必须同步导入。在创建编辑器之前Extension 必须已经同步 import 完毕——Lexical 需要全部编辑器配置包括 nodes在创建前就绪。懒加载推迟的是register里的实现模块不是 Extension 定义本身。register与afterRegistration的时机说明见 packages/lexical-website/docs/extensions/defining-extensions.mdregister发生在编辑器构建完成之后适合注册命令、监听器等afterRegistration发生在所有 Extension 的register都调用完之后。两者返回的都是 dispose 函数。最小可运行的懒加载 Extension以下写法直接取自示例 examples/extension-vanilla-tailwind/src/main.ts 中的LazyExtension示例中的模块路径是./lazyLoadedimport {defineExtension} from lexical; const LazyExtension defineExtension({ name: lexical/extension-vanilla-tailwind-example/Lazy, register(editor, _config, state) { let dispose: undefined | (() void); import(./lazyLoaded).then(mod { if (!state.getSignal().aborted) { dispose mod.registerLazyLoaded(editor); } }); return () { if (dispose) { dispose(); } }; }, });逐段说明import(./lazyLoaded)是动态 import构建工具会把它拆成独立 chunk只有该 Promise 执行时才下载并运行目标模块state.getSignal().aborted用于处理竞争条件编辑器在模块加载完成前被销毁时signal 已 aborted此时不应再调用registerLazyLoaded否则会给已销毁的编辑器注册监听器registerLazyLoaded(editor)返回的清理函数存到disposeregister自身返回的 dispose 函数在编辑器销毁时调用它。LazyExtension作为普通 Extension 放入buildEditorFromExtensions的dependencies数组即可与同步 Extension 没有区别。被懒加载的模块怎么写参考 examples/extension-vanilla-tailwind/src/lazyLoaded.ts。它的完整逻辑是导出一个registerLazyLoaded(editor)函数函数内部创建一个触发按钮挂载到index.html中的#lazy-loaded容器并注册LAZY_LOADED_LOWERCASE_COMMAND命令命令处理逻辑是把编辑器内所有文本节点转为小写export function registerLazyLoaded(editor: LexicalEditor): () void { // 创建并挂载触发按钮示例中挂载到 index.html 的 #lazy-loaded 容器 // ... return editor.registerCommand( LAZY_LOADED_LOWERCASE_COMMAND, () { for (const node of $getRoot().getAllTextNodes()) { const text node.getTextContent(); const lower text.toLowerCase(); if (text ! lower) { node.setTextContent(lower); } } return true; }, COMMAND_PRIORITY_EDITOR, ); }COMMAND_PRIORITY_EDITOR与createCommand来自lexical包。你的实际场景里这个函数内部换成自己的命令注册、监听器或 DOM 操作即可只要返回值是可用于清理的 dispose 函数。这个文件只有被动态 import 时才执行不会进入编辑器初始 bundle。完整可运行示例是 examples/extension-vanilla-tailwind按 README 说明pnpm i pnpm run dev启动。如何验证懒加载生效启动后打开浏览器开发者工具的 Network 面板初始 HTML 加载列表中不应出现被懒加载模块的 JS 文件该 chunk 只应在编辑器实例化触发register后出现。触发功能在示例中点击按钮编辑器内文本全部变为小写说明命令注册成功、模块加载链路完整。清理路径卸载/销毁编辑器时register返回的 dispose 会执行被懒加载模块注册的命令、监听器应当随之移除不会残留引用。限制懒加载只覆盖register/afterRegistration阶段的运行时行为。Extension 的定义与配置——包括nodes、theme、html等——仍需在创建编辑器前同步导入因为 Lexical 要求所有编辑器配置包括 nodes在创建前就绪。官方 FAQ 的结论是这与不使用 Extension 时的情况没有区别Lexical 核心不允许运行时变更编辑器配置。这个机制与React.lazy的思路类似文档原文的类比Extension 定义先行实现推迟到使用时刻。【免费下载链接】lexicalLexical is an extensible text editor framework that provides excellent reliability, accessibility and performance.项目地址: https://gitcode.com/GitHub_Trending/le/lexical创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
RELATED READING

延伸阅读

更多一线实战笔记与深度复盘,助您持续精进