项目:运营搭建平台(vue3-course) | 版本:v1.2 | 生成日期:2026-10-06 | 依据:源码分析
本篇逐包解析 monorepo 的第三方依赖。口径先说清楚:版本以各 package.json 的声明为准(实际安装版本由 pnpm-lock.yaml 锁定,本篇不逐个核对 lockfile,⚠️ 待确认 仅在版本声明与文中其他证据冲突时标注);用途与使用位置以源码 grep 消费点为准,每条给出可复核的文件路径;选型理由/替代方案/升级风险是本篇的判断层,依据源码注释、文档(00/01/06/14 篇)与依赖间的耦合关系推断,无法从源码确认的标 ⚠️ 待确认。各包的职责与包间依赖图(@my/* workspace 依赖)见《01-系统架构》第 2 节与《07-模块详解》第 11 节,本篇只讲第三方依赖,不重复包职责。
先给一张全仓依赖的"面积图"帮助定位:全仓第三方依赖约 60 个直接声明(不含传递依赖),按包分布极不均匀——work-front 承担前端 UI 全家桶(13 个运行时依赖),work-server 承担后端框架与数据访问(20 个),portal-server 刻意比 work-server 少一半(无 jsonwebtoken/bcryptjs/mysql 之外的查询驱动,访客面不做口令校验、不执行业务查询);共享包(shared/business)运行时零第三方依赖(只有 peer 与 devDependencies),这是"宪法包不引入漂移"的刻意设计。版本策略上全仓有两个全局约束:pnpm-workspace.yaml 的 overrides 把 vue 锁为 ^3.5.42、@types/koa 锁为 ^3.0.3(防 Vue 多实例——Vue 是全局单例敏感库,多实例会导致 provide/inject 断链),publicHoistPattern: '*' 全量提升(vite-node/ts-node 直跑脚本需要)。
@my/shared(packages/shared/package.json):dependencies 为空。devDependencies 仅 typescript ^5.9.3 与 vite ^7.3.6(构建用)。运行时零依赖是刻意设计——它被前端、渲染端、两个服务端三方消费,任何一个第三方依赖都会随它扩散到全仓(01 篇称它为"宪法")。产物 ESM/CJS 双格式(scripts/build-module.ts 构建)。
@my/business(packages/business/package.json):dependencies 为空对象,vue ^3.5.42 同时出现在 devDependencies 与 peerDependencies——拖拽引擎(packages/business/src/drag/drag.vue)与 home 组件都是 Vue 组件,peer 声明把"宿主提供 Vue"写成契约。exports 字段细到 ./esm/*、./cjs/*、./css/* 三分支,对应构建产物 ESM/CJS/CSS 三形态(build:module 与 build:css 必须成对跑的原因见 06 篇第 5 节)。
@my/vite-config(packages/build/vite-config/package.json):无 dependencies,main 直接指向 ./index.ts——它不是发布包而是构建期被 import 的 TS 源码模块(scripts/build-work-front.ts 以相对路径引用,borrow-plan 任务 7 记录了为何暂不注册进 workspace)。
| 依赖 | 版本 | 用途 | 使用位置(grep 证据) |
|---|---|---|---|
| @my/shared | workspace:* | Schema 类型与协议 | packages/charts/src/meta/*.ts 的 type import |
| echarts | ^5.5.1 | 图表渲染引擎 | packages/charts/src/components/LineChart.vue 等 4 个图表组件 |
| vue-echarts | ^6.7.3 | ECharts 的 Vue3 封装 | 同上,<v-chart> 声明式用法 |
| numeral | ^2.0.6 | 数字格式化(MetricCard 指标卡) | packages/charts/src/components/MetricCard.vue |
| vxe-table | ^4.7.0 | 大数据量表格(DataTable 物料) | packages/charts/src/components/DataTable.vue |
| element-plus | ^2.14.5(peer) | el-* 物料的运行时组件源 | ElementPlusRenderer.vue 不直接 import,由宿主 app.use(ElementPlus) 注册(文件头注释) |
| vue | ^3.5.42(peer) | 框架 | 全部 .vue 组件 |
选型展开:echarts + vue-echarts 的组合是"引擎 + 薄封装"的经典分工——echarts 负责 option 协议与画布,vue-echarts 把 option 变成响应式 prop。本项目在两者之上又包了一层(packages/charts/src/composables/useChartData.ts 把 fieldMap 换算成 ECharts 数据结构),所以替换图表引擎时受影响面被压缩在 charts 包内。升级风险:echarts 5 → 6 若发布,option 协议与 tree-shaking API(本项目未做按需注册,全量引入)变化是主要风险;@my/charts 源码被 dashboard-codegen 整体 vendor(ADR-012),charts 的依赖变化会连带改变出码产物的依赖清单。vxe-table 选它而非 element-plus 自带表格的理由是大数据量虚拟滚动场景(00 篇技术栈表注明);风险是 vxe-table 4.x 小版本间 peer 结构漂移已经有实际教训——borrow-plan 任务 6 记录 ^4.7.0 浮动解析到 4.21.x 导致出码工程构建失败,因此出码依赖全部钉死。numeral 是轻量格式化(仅 MetricCard 一处消费),替换成本低。
| 依赖 | 版本 | 用途 | 使用位置(grep 证据) |
|---|---|---|---|
| vue / vue-router | ^3.5.42 / ^4.1.6 | 框架与路由 | packages/work-front/src/router.ts(createWebHistory('/page')) |
| element-plus | ^2.14.5 | 管理台/编辑器 UI 组件库 | packages/work-front/src/index.ts(app.use(ElementPlus),同时服务 EP 物料渲染) |
| @my/charts / @my/shared / @my/business | workspace:* | 渲染运行时/协议/拖拽引擎 | 编辑器与页面线编辑器 |
| grid-layout-plus | ^1.0.5 | 看板画布 24 列栅格拖拽/缩放 | packages/work-front/src/pages/dashboard-canvas/app.vue |
| codemirror + @codemirror/* | ^6.0.2(state ^6.7.4、view ^6.43.11、lang-javascript ^6.2.5、lang-json ^6.0.2) | Schema/JS 面板代码编辑器 | packages/work-front/src/pages/dashboard-editor/modules/designer-ui/CodeEditor.vue |
| echarts / vue-echarts / vxe-table | 同 charts | 直连消费(与 charts 同版本声明) | packages/work-front/src/index.ts(vxe-table 的 CSS 与类型 src/types/vxe-table.d.ts) |
| dayjs | ^1.11.7 | 日期格式化 | packages/work-front/src/utils/format-date.ts、pages/manage/log-row.ts 等 |
| uuid | ^9.0.0 | 组件实例 id 生成 | useDashboardEditor.ts(v4 as uuidv4)、pages/manage/utils/page-data.ts |
四点展开:grid-layout-plus 是看板线布局模型(ADR-011)的物理载体,编辑器画布的拖拽/缩放/吸附全由它承担;风险在于它只服务画布一处,但 API 与 Vue 响应式深度耦合(layout 数组受控),升级需要回归整个画布交互(09 篇 840 行的 useDashboardEditor.test.ts 与 overlay-geometry.test.ts 是现成的回归网)。CodeMirror 6 采用模块化包组(core + state + view + 两种语言包),这是 CM6 的推荐姿势;选它而非 Monaco 的理由是体积(编辑器只需轻量 JSON/JS 编辑),替代方案 Monaco 功能强但重一个数量级。dayjs 同时出现在 work-front 与 mock-logger——mock-logger 用它打日志时间戳,属于测试基建复用生产依赖的例子。uuid ^9:已核实 work-server 里 uuid 与 @types/uuid 都在 devDependencies(util/file-upload.ts 运行时 import { v4 } 消费)——语义上应移入 dependencies;当前能工作是因为 rollup 打 CJS 单文件 dist/index.cjs 时把依赖内联进产物。另有一个幽灵依赖要单独点名:copyVueRuntimeLib 在构建末尾从 packages/work-front/node_modules/vue-router/dist/ 硬拷 global 产物,即使访客端源码零引用也不能删(12 篇第 7 节的 ENOENT 条目)——这是 vue-router 在"依赖声明之外"的第二个消费点。
| 依赖 | 版本 | 用途 | 使用位置(grep 证据) |
|---|---|---|---|
| koa | ^3.2.1 | HTTP 框架 | packages/work-server/src/index.ts(app 组装) |
| @koa/router | ^15.7.0 | 路由 | packages/work-server/src/router.ts(565 行路由表) |
| koa-bodyparser / koa-body | ^4.3.0 / ^8.0.0 | JSON 体解析 / multipart(CSV 上传) | router.ts 66 行(koa-body 注释:v8 是 ESM 包,rollup 打 CJS 产物时的处理见该注释) |
| koa-compress | ^5.2.2 | gzip 压缩(阈值 1KB,AI SSE 绕过) | packages/work-server/src/index.ts 54-57 行 |
| koa-mount / koa-static | ^4.0.0 / ^5.0.0 | 静态托管 | 两个服务端 index.ts(/public/** 三层缓存策略) |
| mysql2 | ^3.6.0 | 主库 + MySQL 数据源驱动 | packages/server-kit/src/db.ts、util/data-query/mysql-pool.ts |
| pg | ^8.22.0 | PostgreSQL 数据源驱动(仅查询) | util/data-query/postgresql-pool.ts、service/db-connection.ts |
| jsonwebtoken | ^9.0.0 | JWT 签发/校验 | packages/work-server/src/controller/user.ts |
| bcryptjs | ^3.0.3 | 口令哈希(逐用户盐) | packages/work-server/src/util/password.ts |
| jszip | ^3.10.1 | 出码工程打包 | packages/work-server/src/controller/codegen.ts |
| semver | ^7.3.8 | 页面版本号比较 | service/page-info-ready.ts、page-revert.ts 等 |
| @babel/parser + @babel/generator | ^7.20.7 | 页面线 ESTree 变换(layout → JS 代码) | packages/work-server/src/util/transform.ts |
| vite | ^7.3.6 | 运行时构建页面产物 | packages/work-server/src/service/page-static.ts(await vite.build) |
| vue | ^3.5.42 | 页面产物构建时的框架依赖 | 同上(vite 构建入口需要解析 vue) |
| dotenv | ^16.0.3 | .env 加载 | config.ts |
| @my/server-kit / mock-cdn / mock-logger / work-front | workspace:* | 基建/CDN/日志/静态产物 | 各 service 与构建脚本 |
三个值得展开的点。其一,vite 作为服务端运行时依赖是本项目最非常规的依赖决策:页面线发布(prod 阶段)在请求路径内调用 vite.build 真实构建产物(05 篇流程二),这让 work-server 的部署体积显著变大(vite 及其 esbuild/rollup 依赖全量进入 node_modules),换来的是"发布产物与本地构建完全同构"。替代方案是自研模板拼接(页面线历史上有 transformESTreeToJS 的痕迹,保留在 util/transform.ts),但纯字符串拼页面代码的可维护性已被放弃。升级风险:vite 大版本(7)的 lib 模式 API 变化直接打在发布链路上(cssFileName 显式声明就是 vite 7 的要求),升级 vite 必须回归页面线发布。其二,koa 3 + @koa/router 15:koa 3 是 2025 年后的大版本(异步中间件模型未变,主要是 Node 版本基线与内部清理),两个服务端统一用它;@koa/router 是 koa 官方生态认可的 router 分支。风险点:koa-body@8 是 ESM 包(router.ts 66-117 行注释记载了 rollup 打 CJS 产物时的互操作处理),这类 ESM/CJS 边界问题是 koa 生态升级的主要摩擦面。其三,@babel/parser + generator 只服务页面线的 ESTree 变换(util/transform.ts 把 layout 编译为页面代码再交给 vite),选 Babel 家族而非 acumen/estraverse 的理由是 parser+generator 配套齐全且 AST 规范稳定;这是 devTools 依赖进生产 dependencies 的少数例子(合法:它在请求路径运行)。
dependencies:koa/@koa/router/koa-body/koa-bodyparser/koa-compress/koa-mount/koa-static(与 work-server 同版本)、mysql2 ^3.6.0、dotenv、vue ^3.5.42、@my/server-kit/@my/mock-cdn/@my/mock-logger/@my/work-front。
对比 work-server 少了什么比多了什么更重要:没有 jsonwebtoken/bcryptjs(访客面不校验口令,令牌是 timingSafeEqual 常量时间比对明文,packages/portal-server/src/service/dashboard.ts)、没有 pg/任何查询驱动(访客取数一律转发 work-server,ADR-005)、没有 jszip/vite/babel(访客面不构建任何东西)。mysql2 在这里是 server-kit 连接池的传递需求(portal 也读库——prod 行、实时 access 行、PV 埋点写入)。vue ^3.5.42 出现在服务端依赖里看着奇怪,实际是 workspace 拓扑使然:portal-server 依赖 @my/work-front(静态产物拷贝),声明 vue 保证 peer 解析不报错(已核实:portal-server/src 对 vue 的 import 全部处于注释状态,是 SSR 遗留,运行时确不消费,属保守声明)。这个精简是 ADR-009"匿名面隔离"的依赖侧体现:依赖面 = 攻击面的近似,portal 的 node_modules 里不存在能直接连业务库执行任意查询的驱动组合。
@my/server-kit:dependencies 仅 @my/mock-cdn(workspace,sync-cdn 回源需要)、dotenv、mysql2 ^3.6.0(连接池 db.ts);devDependencies 有 koa 与 @types/koa(已核实:两者确在 devDependencies、未写 peerDependencies——http-security.ts/security-headers.ts 仅类型引用,宿主包必然自带 koa,实际无碍)。作为门面包它的依赖纪律与 shared 一致:不引入任何新的第三方运行时依赖。
@my/init-database:bcryptjs ^3.0.3(种子账号 hashPassword,packages/init-database/src/util.ts)、dotenv、mysql2 ^3.6.0(不含库名的独立连接池)。devDependencies 的 @types/node ^18.11.17 与全仓 node22 基线(@tsconfig/node22)不一致(已核实声明);typecheck 覆盖问题已核实:根 tsconfig.node.json 的 include 含 packages/init-database/src/,CLI 包随 typecheck:node 线检查(extends 的是 @tsconfig/node22,偏差仅在包内 devDep 的类型版本声明)。
@my/mock-cdn / @my/mock-logger:两个 mock 包的依赖形状相同——requirejs 2.3.6(钉死精确版本)、vue 3.5.42(精确版本,无 ^)、vue-router 4.1.6(精确版本),devDependencies 是 http-server ^14.1.1(pnpm serve 起独立 CDN 服务用)。精确版本钉死是刻意的:这两个包把 vue/vue-router 作为文件资产随产物分发给 AMD 物料运行时消费(物料 external 的 vue 由 CDN 提供),浮动版本会让"编辑器里的 Vue"与"CDN 里的 Vue"漂移——与 pnpm overrides 锁单版本是同一防线的两道锁。requirejs 2.3.6 是页面线 AMD 物料加载器(packages/work-front/src/pages/manage/modules/page-editor.tsx 的 initAMDEnv 注入 AMD 定义),选它是 AMD 事实标准的历史惯性,替代方案(ESM import map)是页面线重写时的事(ADR-010 冻结后不再投入)。
materials 两包:零 dependencies,vue 进 peerDependencies——物料包把 vue 完全 external 化(SOP 二的"物料包内不要引 element-plus"约束即源于此:页面线产物自治,依赖必须打进包内或走 CDN 白名单)。
根 devDependencies 是全仓工具链的单一声明点(子包不重复声明版本,靠 pnpm workspace 提升共享):构建族 vite ^7.3.6 / vite-node ^5.3.0 / rollup ^3.8.1 + 三个 rollup 插件(commonjs/json/node-resolve)/ rollup-plugin-esbuild / @vitejs/plugin-vue / @vitejs/plugin-vue-jsx / unplugin-vue-macros ^1.1.1;类型族 typescript ^5.9.3 / @types/node ^22.5.0 / @tsconfig/node22 / @vue/tsconfig ^0.1.3 / tslib / ts-morph ^28.0.0(scripts/build-dts.ts 生成声明);质量族 vitest ^4.1.11 / @vitest/coverage-v8 / jsdom ^30.1.0 / eslint ^8.30.0 + @vue/eslint-config-typescript + eslint-plugin-vue + prettier;杂项 dotenv / fast-glob ^3.2.12 / kill-port / node-fetch ^3.3.0 / nodemon / ts-node / less / @types/less / typescript-json-schema ^0.68.0。
展开三处。vite-node 直跑 TS 脚本是脚本体系的统一执行器(14 篇第 2 节:所有 scripts/*.ts 与 db:init 都经它运行),好处是脚本与业务代码同一套 TS 配置、可 import workspace 源码(migrate-secrets.ts 直接 import work-server 的 secret-box);替代方案 tsx/ts-node 各有局限(ts-node 仍被 dev:work-server 用于服务端直跑,两者并存)。typescript-json-schema 只有一个消费点(scripts/build-materials.ts 第 9 行 import * as TJS),从物料的 types.ts 生成 props.schema.json——页面线属性表单的数据契约;升级风险是它对 TS 版本敏感(TS 5.x 内部 API 变化曾屡次打断该项目维护节奏)。vitest 4 + jsdom 30 + 分线配置(vitest.config.js)的组合已经在 09 篇完整展开,这里只补依赖视角:@vitest/coverage-v8 与 vitest 严格同版本发布,升级必须成对;unplugin-vue-macros 的消费点已核实(不在 vite 配置而在构建脚本):scripts/build-module.ts 第 5 行 import VueMacros from 'unplugin-vue-macros/rollup'(business/shared 的 rollup 构建消费),另有三份 tsconfig 把 unplugin-vue-macros/macros-global 声明为全局类型来源。
包间依赖(各 package.json 汇总):work-front → shared/charts/business;charts → shared;work-server → server-kit/work-front/mock-cdn/mock-logger;portal-server → server-kit/work-front/mock-cdn/mock-logger;server-kit → mock-cdn;dashboard-codegen → (无 package.json,脚本型包,vendor charts 源码)。无循环依赖——最接近环的是 work-server → work-front(服务端依赖前端包,但只消费 dist 产物拷贝,不 import 源码),这是"服务端托管静态产物"的构建期形态,07 篇第 11 节称为"构建期产物依赖"以区别于源码依赖。dashboard-codegen 没有 package.json(grep 确认),它以纯函数被 work-server 源码直接 import、随服务端一起打包——这解释了 13 篇说的"它不依赖 shared 也能工作"(当前靠本地白名单副本解耦),也意味着给这个目录补 package.json + workspace 依赖即可完成 13 篇第一阶段的止血项。
总体判断:依赖治理处于良好水平,主要风险集中在"运行时大依赖"与"版本声明的三处不一致"。
做得好的四点。其一,零依赖的宪法包:shared/business 运行时无第三方依赖,切断了"工具库顺带拖进一个框架"最常见的腐化路径。其二,框架单版本强制(overrides)+ mock 包精确钉版,双锁防 Vue 漂移——大多数 Vue 项目死于多实例与版本漂移,这里两道都上了保险。其三,portal 依赖面刻意最小化,匿名面的攻击面与依赖面同步收敛(第 5 节)。其四,出码依赖钉死工作区版本(ADR-012),有真实失败案例背书而非教条。
需要记账的三点。第一,vite 进服务端运行时依赖(work-server)是全仓最重的运行时决定,部署体积、升级风险(lib 模式 API)、安全面(构建器在请求路径运行)三者都因它放大;可行的中期方案是把页面构建异步化并拆到独立 worker 进程(10 篇第 4 节已建议异步化),依赖本身建议冻结在 7.x 并在升级前列入发布回归清单。第二,版本声明不一致三处:work-server 的 uuid 在 devDependencies(运行时消费)、server-kit 的 koa 缺 peerDependencies 声明、init-database 的 @types/node 落后基线——均不影响当前构建(hoist + 打包策略兜底),但都是"下一个人会困惑"级别的噪声,建议随 13 篇第一阶段止血顺手清理。第三,echarts 全量引入:charts 与 work-front 都直接依赖 echarts 而未做按需注册,访客首屏体积的大头(10 篇第 2 节);resolveRenderer 已是集中解析点,改 defineAsyncComponent 按需加载是已预留的优化路径。仍开放的一项 ⚠️ 待确认:pnpm-lock.yaml 与各声明 ^ 范围的实际解析版本(本篇未逐包核对);unplugin-vue-macros 的消费点已在第 7 节核实结案(scripts/build-module.ts 的 rollup 插件)。
升级优先级建议(结合 09 篇的回归网现状):可随时升——dayjs/numeral/uuid/semver(低耦合、有单测兜底);需跑全量测试再升——koa 系(ESM 边界)、mysql2(连接池行为)、element-plus(EP 物料渲染回归)、vxe-table(出码 peer 教训);列入专项再动——vite(页面发布链路)、vue 大版本(全仓 override + 双桶产物 + AMD CDN 三处联动)、echarts/vxe-table(vendor 契约)。每类升级的回归入口见 09 篇第 3 节的守护用例索引。