从 PolyRepo 迁移到 MonoRepo 的光怪陆离 (dayjs, momentjs, webpack)
在我将一批仓库从 PolyRepo 迁移到 MonoRepo 之后, 有一个项目通过 build 和相关类型检查, 但是最终生产运行环境出现 bug.
抛错现场
moment__webpack_imported_module_0__.isMoment is not a function
很常见的错误, 某个引用的变量不存在, 看起来是 Momentjs 这个包导致的. Take it easy.
- 先回滚生产镜像, 锁定版本发布.
- 本地复现, 定位到代码.
发现代码来自于, antd-vue 的 1.x 版本, 代码示例如下:
import * as moment from 'momont';
//......... some code
function(n) {
moment.isMomment(n);
}
也是很常见的问题, 在 esm 中兼容 CommonJS 模块, 没有开启 esModuleInterop
的时候就需要这样写.
moment
也没有在 package.json
中申明对 esm
的支持, 最多有 typescript
的支持, 但是这部分是 js, 并不会过 ts.
而理论 node_modules
的依赖并不会过本地的 transform , 也就没有 esm, 所以这样应该不会有问题, 所以我的 debug 方向就是, 是不是因为 babel
不小心配置了处理 node_modules
的依赖.
one hour later
试了很多方案, 并没有找到问题所在, 也没有修复. 于是切换思路, 看看运行时能不能找到问题, 断点到报错的地方, 手动看看此时的 moment
的结构是什么.
多亏了 Chrome Dev Tools
的强大, 我发现这个 moment
示例居然最终指向了 [email protected]
?????
WTF, 差点世界观崩塌了.......
然后全局搜 dayjs
发现, 在 webpack 配置中有一个手写的 Plugin, 通过 webpack alias 将 moment
解析到 dayjs
, 通过 dayjs
的 plugin
实现了替换 momentjs
的目的.
🥷 Ninja Trick !!!
接下来的问题变成了, 为什么会出问题.....
--------- > one hour later
请教了这个代码曾经的作者, 他说可能是存在 dayjs
指向的示例不一致导致的问题......
这下一切都说得通了:
- 通过 webpack plugin 的方式给 dayjs 装上了各种插件, 让它提供
momentjs
的功能, 用来替换momentjs
- 但是
[email protected]
能引用到的dayjs
又和我本地的不一样, 理论上它用到的应该是在node_modules/.pnpm/node_modules
下面的依赖, 因为它本身没有声明支持dayjs
. - 先通过
packageExtensions
, 将dayjs
和antd-vue
pin 到一起, 然后看看. .... 可行 ✅ - 但是会担心影响其他项目的依赖, 毕竟现在还在合并阶段, 依赖统一还是很困难的...
- 老司机推荐我使用
webpack
的alias
将dayjs
解析到项目本身的dayjs
, 这样既解决了依赖实例不一致的问题, 又限制了影响访问.....
整个记录非常离谱和诡异, 最终解决的问题.
- 幸运的是, 暂时不会被 AI 替代了, AI 根本想不到这个问题的原因.
- 不幸的是, 浪费了我一个工作日.....