import.meta.glob 全量扫描的代价:一次大型 Vue3 前端工程的效率排查

ClassFactory 已经通过虚拟模块做了 classId 到 filePath 的精确映射,但 import.meta.glob 仍在扫全库------这类「有精确索引却仍全量扫描」的写法,是大型前端工程依赖图膨胀的常见来源。本文记录一次实际排查的过程与结论。

import.meta.glob 全量扫描的代价:一次大型 Vue3 前端工程的效率排查

效率问题分布在 开发构建、首屏加载、运行时交互、架构维护 四个层面,建议按优先级从以下方面入手。


一、最高优先级:缩小 import.meta.glob 扫描范围

当前多处使用全量 glob,是开发慢、构建慢、依赖图膨胀的核心原因:

位置 当前模式 影响
ClassFactory.ts /src/**/*.ts 2100+ 模块全部进入依赖图
useComponentLoader.ts /src/**/*.vue 898 个 Vue 文件
各类 ClassFactoryOf*.ts /src/**/GPN_*.ts 等 各自维护一套 glob

ClassFactory.ts 示例:

typescript 复制代码
const modules = import.meta.glob('/src/**/*.ts');

问题 :ClassFactory 已通过 virtual:entity-metadata 做了 classId → filePath 的精确映射,但 glob 仍扫描全库,造成 Vite 依赖图过大。

优化方向:

  • 由 metadata 生成精确 glob,或维护已加载模块的 Map 缓存
  • ClassFactoryOfGroupPageNew 中的 _en_gpn_map 已是好范例,应推广到所有 Factory 和 getObject
typescript 复制代码
// 方向示例
const moduleCache = new Map<string, any>();
// getObject 成功后 cache.set(fileSrc, dynamicModule)

预期收益 :Dev 冷启动 / HMR 明显加快,构建内存压力下降(当前 build 已配 max_old_space_size=8192,说明体积 / 图复杂度已很高)。


二、首屏与包体积:延迟加载重型依赖

main.ts 在 bootstrap 前同步引入了多项重型资源:

  • Monaco Editor Worker(setupMonacoWorker())
  • v-md-editor + highlight.js
  • Vant 全量 CSS
  • Ant Design Vue reset.css
  • 多套 icon / form 样式

建议:

  1. Monaco Editor :仅在表单设计器、脚本编辑等页面 import(),不要全局 setupMonacoWorker()
  2. v-md-editor + highlight.js:按需注册,知识库 / 预览页再加载
  3. Vant CSS:移动端路由 / 入口单独加载,PC 主入口不引入
  4. 三套 UI 库并存 (Ant Design Vue + Naive UI + Vant):Search.vue 等用 Naive,main.ts 又引 Ant Design --- 按场景拆入口或统一组件层,避免双份组件树
  5. lodash :多处 import { cloneDeep } from 'lodash',应统一改为 lodash-es 并按函数导入(tree-shaking 更好)

已有 advancedChunks 分包(wf-app、bp-core、antd、echarts 等),方向正确;下一步用 npm run report(rollup-plugin-visualizer)找实际大包,再针对性 lazy load。


三、运行时:Entity 页面与 API 层

1. 减少重复网络请求

  • Entity.GenerUAC() 每次实例化都可能请求后端
  • useDDLDataLoader 中每个 DDL 字段可能独立调 SFTable.GenerData() / DBAccess.RunSQLReturnTable
  • Tree.vue、Search.vue 等通用页体积大(Search 1800+ 行),初始化链路长

建议:

  • UAC / EnMap / DDL 数据 做 session 级缓存(bp/da/Cache.ts 已有基础,可扩展 TTL 和 key 策略)
  • 列表页 EnMap 与 UAC 并行请求,避免串行 waterfall
  • 同页多 DDL 用 Promise.all 批量拉取

2. 大列表 / 树表渲染

Tree.vue 用 Ant Design Table 渲染整棵树,pagination: false,大数据量会卡:

  • 虚拟滚动(virtual)或分页 / 懒加载子节点
  • 列定义、customRow 等用 computed + 稳定引用,避免每行重建函数
  • 项目里 shallowRef / markRaw 使用很少,大对象(表格 data、EnMap)可优先采用

3. Entity Proxy 开销

Entity 基类为每个实例包裹 Proxy,表单字段多时 get/set 开销可观。

热路径可考虑:

  • 表单绑定直接用 Row / record 对象
  • 或仅在开发环境启用 Proxy 校验

四、开发效率:构建、类型检查、HMR

1. 元数据插件成本

metadataGenerator.ts 启动时 fast-glob 扫描 + TypeScript AST 解析 全库 Entity / GPN / GL,HMR 时还会 debounce 全量合并。

可优化:

  • 增量更新:只重算变更文件,不全量 regenerateAndSaveAllMetadata
  • 生产构建用缓存 JSON,跳过 AST 扫描
  • 开发环境 debug: false 减少 I/O

2. 路由与 i18n 的 eager 加载

路由模块(router/routes/index.ts)、locales/lang/*.ts 均为 eager: true,启动时会解析全部路由 / 语言包。可改为 lazy glob,仅保留登录等核心路由 eager。

3. TypeScript 检查

  • 3032 个文件下 vue-tsc 很慢,可 CI 全量 + 本地 tsgo(package.json 已有 type:check:tsgo)
  • 大组件(Search.vue、Tree.vue)拆子组件,利于类型推断和 HMR

4. 重复 ClassFactory 模式

存在 10+ 个 ClassFactoryOf*(GPN、GL、TreeEns、Rpt2D...),逻辑高度相似。抽象统一 BaseClassFactory 可:

  • 减少 glob 注册点
  • 统一缓存、错误处理
  • 降低维护成本

五、建议的落地顺序(ROI 排序)

按 ROI 排序的落地路径:1. ClassFactory 模块缓存 + 缩小 glob → 2. main.ts 重型依赖按需加载 → 3. lodash-es 与 UI 库按场景拆分 → 4. UAC / EnMap / DDL 请求缓存与并行 → 5. 大列表虚拟滚动 → 6. 元数据插件增量扫描 → 7. ClassFactory 统一抽象与大组件拆分

阶段 动作 主要受益
第 1 周 ClassFactory 加缓存;glob 改为 metadata 驱动 Dev 启动、HMR、构建内存
第 2 周 Monaco / Vant / MD 编辑器移出 main;跑 bundle report 首屏 FCP / LCP
第 3 周 API 缓存 + 列表虚拟滚动 表单 / 树 / 搜索页交互
持续 Factory 统一、组件拆分、tsgo 本地检查 长期维护效率

六、可立即执行的度量基线

在改之前先建立数据,避免盲目优化:

bash 复制代码
# 构建体积分析
npm run report

# 构建耗时(PowerShell)
Measure-Command { npm run build }

# Dev 冷启动(清 cache 后)
npm run clean:cache
npm run dev

Chrome Performance 录一条典型路径:打开 Search 页 → 加载 EnMap → 渲染表格,看 Long Task 和网络 waterfall。


总结

这个项目的瓶颈不在某个 Vue 写法,而在 「3000+ 文件 + 全量 glob + 重型全局依赖 + Entity 运行时多次请求」 的组合。

优先做 ClassFactory 缓存与 glob 收窄 和 main.ts 按需加载 ,通常能同时改善开发体验和用户首屏;再针对 Search / Tree 等通用页做 请求合并与虚拟列表,运行时体验会有明显提升。


关键文件索引

文件 说明
Vue3/src/bp/da/ClassFactory.ts 实体类工厂,全量 glob
Vue3/src/main.ts 应用入口,重型依赖同步加载
Vue3/src/hooks/ens/useComponentLoader.ts 全量 Vue glob 动态组件
Vue3/src/bp/en/Entity.ts Entity 基类,Proxy 包装
Vue3/src/bp/da/Cache.ts 简单 Map 缓存,可扩展
Vue3/base/vite-config/src/config/application.ts 构建分包配置
Vue3/base/vite-config/src/plugins/metadataGenerator.ts 实体元数据 AST 扫描插件
Vue3/src/router/routes/index.ts 路由 eager 加载
Vue3/src/WF/Comm/Search.vue 大型通用搜索页
Vue3/src/WF/Comm/Tree.vue 树表编辑页
相关推荐
开源驰骋低代码_工作流6 天前
不手写 Vue 页面的前端开发:高代码模式与 14 种页面模式
bpmn-js
开源驰骋低代码_工作流7 天前
从评估维度到场景匹配:工作流引擎选型实践对照
bpmn-js
开源驰骋低代码_工作流10 天前
只做加法不重构:流程引擎的长期演进是怎么做到的
bpmn-js
开源驰骋低代码_工作流10 天前
前后端分离下的流程集成:一份 Toolkit 落地清单
bpmn-js
开源驰骋低代码_工作流17 天前
交互层是产品还是框架:四大菜单与三大处理器的对比视角
bpmn-js
开源驰骋低代码_工作流24 天前
不做甘特图控件:流程引擎之上的工程运行时怎么设计
bpmn-js
开源驰骋低代码_工作流24 天前
三类任务、一个工作台:把项目执行收进流程平台的产品设计
bpmn-js
开源驰骋低代码_工作流25 天前
同一道请假审批,六款 Java 工作流引擎的实现路径与成本对比
bpmn-js
开源驰骋低代码_工作流25 天前
把请假审批交给六款 .NET 引擎:实现路径、场景适配与相对打分
bpmn-js