前言
最近在进行Monorepo架构调整,需要将一个现有的Vue 3(Vite)项目作为一个子应用 (apps/wj) 迁移到由Vue 2(Webpack)主导的大仓中。本以为只是简单的"文件夹移动",结果在依赖管理、网络代理和端口映射上踩了一圈坑。
本文记录了从迁移到跑通全流程遇到的4个典型问题及解决方案。
坑点一:pnpm 严格模式下的"幽灵依赖"
💥 现象
将项目移入大仓后,执行 dev 脚本报错:
Bash
'vite' 不是内部或外部命令,也不是可运行的程序
或者启动后报错找不到 unplugin-auto-import、vue-request 等插件。
🔍 原因
原项目可能使用 npm/yarn,存在依赖提升 (Hoisting) ,即 devDependencies 即使没写在 package.json 里,依靠根目录 node_modules 也能跑。 但迁移到 pnpm Monorepo 后,pnpm 的严格机制要求所有使用的包必须显式声明。
✅ 解决
在根目录通过 --filter 为子应用补全依赖:
Bash
# 补全构建工具
pnpm add vite @vitejs/plugin-vue vue-tsc -D --filter wj
# 补全缺失的业务/构建插件
pnpm add unplugin-auto-import unplugin-vue-components -D --filter wj
pnpm add vue-request --filter wj
坑点二:Workspace 内部包的正确引用
💥 现象
Vite 启动报错:
Bash
Error [ERR_MODULE_NOT_FOUND]: Cannot find package 'configs' imported from ...
子应用试图引用大仓共享的配置包(packages/configs),但找不到模块。
🔍 原因
子应用虽然物理上在 monorepo 里,但 package.json 里没有声明对内部包的依赖,导致软链接未建立。
✅ 解决
使用 --workspace 协议建立软链:
Bash
# 将内部包链接给子应用
pnpm add configs --workspace --filter wj
注意:如果共享包内部也用了某些插件(如 @vitejs/plugin-vue),共享包自己也必须安装该插件,否则会报"父级依赖缺失"。
坑点三:Node 高版本 localhost 解析陷阱 (IPv6)
💥 现象
主应用配置了代理转发到子应用,但在浏览器访问时报 HTTP 500,终端报错:
Bash
Error: connect EACCES ::1:5192
🔍 原因
- 环境: Node.js v17+
- 机制: 主应用代理配置写了
target: 'http://localhost:5192'。Node 默认将localhost解析为 IPv6 地址::1。 - 冲突: 子应用 (Vite) 默认只监听 IPv4 (
127.0.0.1)。主应用去 IPv6 端口找人,自然连不上。
✅ 解决
方案A(推荐): 修改主应用代理配置,强制使用 IPv4 IP。
JavaScript
// 主应用 vite.config.ts / vue.config.js
proxy: {
'/wj': {
target: 'http://127.0.0.1:5192', // 👈 不要写 localhost
changeOrigin: true
}
}
方案B: 让子应用监听所有地址。启动命令改为 vite --host。
坑点四:主应用代理"漏气" (接口返回 HTML)
💥 现象
页面加载成功,但业务接口(如 /cmisp/api/xxx)报 304 或 200 ,查看 Response 内容竟然是 index.html 的代码,导致 JSON 解析失败。
🔍 原因
主应用只代理了页面路由 /wj,但子应用发出的 API 请求是 /cmisp 开头的。 主应用不认识 /cmisp,将其当成了前端路由处理,直接返回了 index.html。
✅ 解决
在主应用中补全 API 的代理转发规则:
JavaScript
// 主应用 vite.config.ts
server: {
proxy: {
// 1. 子应用页面资源
'/wj': {
target: 'http://127.0.0.1:5192',
changeOrigin: true
},
// 2. 子应用 API 请求 (新增)
'/cmisp': {
target: 'http://127.0.0.1:5192', // 如果是 mock 数据走这里;如果是真实后端填后端 IP
changeOrigin: true
}
}
}
总结
Monorepo 迁移不仅仅是文件搬运,核心在于:
- 依赖边界:pnpm 下必须"谁用谁装"。
- 网络互通 :Node 高版本下
localhost的 IPv6 坑需要格外注意。 - 路由接管:主应用作为网关,必须接管子应用的所有请求(包括静态资源和 API)。