perf(frontend): RichEditor 异步化拆分 Admin chunk(1021 kB → 232 kB)(BACKLOG C6)
定性:Admin-*.js 达单 chunk 1,021 kB(gzip 340 kB),而其中约 800 kB 是**进入管理端
根本用不到**的富文本编辑器。
- Admin.vue 静态 import RichEditor.vue,后者静态 import @wangeditor/editor
(dist/index.esm.js = 818,777 B)⇒ 编辑器全量并进 Admin chunk。
- 实测三处使用点(446 大题题干 / 1384 新闻 / 1476 轮播)**全部位于 el-dialog 内**,
而 el-dialog 初始 rendered=false 不渲染内容 ⇒ 首屏不该付这份成本。
- 全仓反证:RichEditor 只被 Admin.vue 引用;@wangeditor 特征串在入口 chunk 0 命中。
处置:改为 defineAsyncComponent 按需加载(最小改动 16+/2−,只动 Admin.vue)
- src/views/Admin.vue: import RichEditor → defineAsyncComponent({ loader: () => import(...) })
- 加 loadingComponent:用 **render 函数**而非 template 字符串 —— 本工程为 runtime-only
构建,字符串模板需要运行时编译器,会直接报错。
- vue import 列表补 defineAsyncComponent 与 h。
- 无需 manualChunks:唯一引用点 + 动态 import ⇒ Vite 自动分片。
实测(真 chromium + 静态服务 + /api 反代真实后端):
Admin-*.js 1,045,614 B → 231,715 B(−77.8%)
RichEditor-*.js 新增 810,862 B(按需加载;gzip 281,958 B)
首屏 JS 合计 1,684,778 B → 872,736 B(−48.1%)
首屏最大单 chunk 1,045,614 B → 283,833 B(−72.9%)
验证:
- 新增 perf-r34/c6-chunk-split-check.mjs:21/21 全绿(首屏不含 wangeditor;打开新闻与
轮播两个弹窗后编辑器 chunk 按需请求且渲染成功;0 pageerror / 0 Failed to resolve)
- 🔴 判别力(变异测试):对**拆分前**的 dist 跑同一脚本,恰好 5 项判红(A4 首屏含
wangeditor / A5a 1,684,778 B 超预算 / A5b 1,045,614 B 超 500 kB / B2·B3 无按需请求)
—— 证明断言真的在守,而非「守卫根本没跑」。
- 回归:perf-r34/dist-admin-check.mjs 9/9(el-table 20 行 / 分页中文 / ElMessageBox
中文按钮 / 零 Failed to resolve)⇒ 管理端功能零回归。
- TDZ 扫描 37 文件 PASS · vite build exit 0 · .gz 预压缩 70 个(含 RichEditor.js.gz)
This commit is contained in:
@@ -1533,7 +1533,7 @@
|
||||
* 7. 新闻管理 - CRUD + 置顶/分组
|
||||
* 8. 轮播管理 - 添加/删除/排序/启用
|
||||
*/
|
||||
import { ref, reactive, onMounted, watch, computed, nextTick } from 'vue'
|
||||
import { ref, reactive, onMounted, watch, computed, nextTick, defineAsyncComponent, h } from 'vue'
|
||||
import { ElMessage, ElMessageBox } from 'element-plus'
|
||||
import {
|
||||
DataAnalysis, User, EditPen, FolderOpened,
|
||||
@@ -1546,7 +1546,21 @@ import * as carouselApi from '@/api/carousel'
|
||||
import { formatFileSize, normalizeImageUrl } from '@/utils/upload'
|
||||
import { safeDownload, fetchBlobGuarded } from '@/utils/download'
|
||||
import { sanitizeHtml, isRichTextEmpty } from '@/utils/richtext'
|
||||
import RichEditor from '@/components/RichEditor.vue'
|
||||
// 🔴 富文本编辑器**异步加载**(2026-09-29 R41 · BACKLOG C6):
|
||||
// RichEditor.vue 静态 import 了 @wangeditor/editor(dist 主文件 818,777 B ≈ 800 kB),
|
||||
// 此前经静态 import 全量并进 Admin chunk ⇒ Admin-*.js 达 1021 kB(gzip 340 kB)。
|
||||
// 实测三处使用点(446 大题题干 / 1384 新闻 / 1476 轮播)**全部在 el-dialog 内**,
|
||||
// 而 el-dialog 初始 rendered=false 不渲染内容 ⇒ 进入管理端时本编辑器根本用不到。
|
||||
// 改为异步后 wangeditor 被剥离为独立 chunk,仅在首次打开这三个弹窗时才按需下载。
|
||||
// 注意:loadingComponent 用 render 函数而非 template 字符串 —— 本工程为 runtime-only
|
||||
// 构建,字符串模板需要运行时编译器,会直接报错。
|
||||
const RichEditor = defineAsyncComponent({
|
||||
loader: () => import('@/components/RichEditor.vue'),
|
||||
loadingComponent: {
|
||||
render: () => h('div', { style: 'padding:24px;color:#909399;font-size:13px;text-align:center' }, '富文本编辑器加载中…'),
|
||||
},
|
||||
delay: 120,
|
||||
})
|
||||
|
||||
const authStore = useAuthStore()
|
||||
|
||||
|
||||
Reference in New Issue
Block a user