动态 import() 是按需加载富文本编辑器的最优解——它在运行时触发、不增加首屏体积、支持错误捕获与 tree-shaking;普通 import 会在编译时打入主包,违背按需原则。

富文本编辑器这类重型依赖,体积大、初始化慢、使用频次低,直接在首屏加载会拖累性能。用动态 import() 按需加载是最直接有效的解法——用户点开编辑区域时才拉取代码,不点就不载。
为什么必须用动态 import,而不是普通 import
普通 import 是编译时静态引入,打包工具会把它打进主包,哪怕你整个页面从不触发编辑功能;而 import() 是运行时调用,返回 Promise,只在真正需要时发起网络请求,且浏览器自动去重、支持错误捕获、天然兼容 tree-shaking。
- 不增加首屏 JS 体积,白屏时间明显缩短
- 避免未使用模块长期驻留内存(比如用户只看内容,从不点“编辑”)
- 可配合预加载策略提升感知速度(如 hover 后提前 fetch)
实际写法:点击触发 + 加载状态 + 错误降级
不要把编辑器实例挂载逻辑写死在页面初始化里,而是封装成一个可调用函数:
async function initRichEditor(textarea) {
try {
// 动态加载编辑器模块(假设已打包为 ESM)
const { default: Quill } = await import('https://cdn.jsdelivr.net/npm/quill@2.0.0/dist/quill.esm.min.js');
// 初始化实例(注意:Quill 需要 DOM 节点,确保 textarea 已挂载)
return new Quill(textarea, {
theme: 'snow',
modules: { toolbar: true }
});
} catch (err) {
console.error('富文本编辑器加载失败', err);
// 降级方案:回退为纯 textarea + 提示
alert('编辑功能暂不可用,请使用基础文本框');
return null;
}
}
调用时只需绑定到按钮或链接的 click 事件即可,无需提前准备任何全局变量。
结合框架的推荐做法(Vue / React)
如果你在 Vue 或 React 项目中使用,更推荐用框架原生异步组件能力,语义清晰、加载状态可控:
-
Vue 3:用
defineAsyncComponent包裹,模板中配合<suspense></suspense>显示 loading 效果 -
React:用
React.lazy+Suspense,但注意它只支持默认导出,且不能直接放在事件回调里 —— 所以更适合“编辑页”这种整页切换场景;若只是弹窗内嵌编辑器,仍建议用原生import()
例如 Vue 中定义一个异步编辑器组件:
import { defineAsyncComponent } from 'vue';
const AsyncQuillEditor = defineAsyncComponent(() =>
import('./components/QuillEditor.vue')
);
预加载与体验优化技巧
如果用户行为有明确前兆(比如鼠标悬停“编辑”按钮 300ms 后大概率点击),可以提前触发 import(),但不 await:
let quillPreload = null;
editBtn.addEventListener('mouseenter', () => {
if (!quillPreload) {
quillPreload = import('quill');
}
});
editBtn.addEventListener('click', async () => {
try {
const { default: Quill } = await (quillPreload || import('quill'));
// 初始化...
} catch (err) {
// 处理失败
}
});
这样点击后几乎无等待感,又不会造成不必要的资源浪费。


















