从 PolyRepo 迁移到 MonoRepo 的光怪陆离 (dayjs, momentjs, webpack)

从 PolyRepo 迁移到 MonoRepo 的光怪陆离 (dayjs, momentjs, webpack)

在我将一批仓库从 PolyRepo 迁移到 MonoRepo 之后, 有一个项目通过 build 和相关类型检查, 但是最终生产运行环境出现 bug.

抛错现场 moment__webpack_imported_module_0__.isMoment is not a function

很常见的错误, 某个引用的变量不存在, 看起来是 Momentjs 这个包导致的. Take it easy.

  1. 先回滚生产镜像, 锁定版本发布.
  2. 本地复现, 定位到代码.

发现代码来自于, 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, 通过 dayjsplugin 实现了替换 momentjs 的目的.

🥷 Ninja Trick !!!

接下来的问题变成了, 为什么会出问题.....

--------- > one hour later

请教了这个代码曾经的作者, 他说可能是存在 dayjs 指向的示例不一致导致的问题......

这下一切都说得通了:

  1. 通过 webpack plugin 的方式给 dayjs 装上了各种插件, 让它提供 momentjs 的功能, 用来替换 momentjs
  2. 但是 [email protected] 能引用到的 dayjs 又和我本地的不一样, 理论上它用到的应该是在 node_modules/.pnpm/node_modules 下面的依赖, 因为它本身没有声明支持 dayjs.
  3. 先通过 packageExtensions, 将 dayjsantd-vue pin 到一起, 然后看看. .... 可行 ✅
  4. 但是会担心影响其他项目的依赖, 毕竟现在还在合并阶段, 依赖统一还是很困难的...
  5. 老司机推荐我使用 webpackaliasdayjs 解析到项目本身的 dayjs, 这样既解决了依赖实例不一致的问题, 又限制了影响访问.....

整个记录非常离谱和诡异, 最终解决的问题.

  • 幸运的是, 暂时不会被 AI 替代了, AI 根本想不到这个问题的原因.
  • 不幸的是, 浪费了我一个工作日.....
  • Loading...
  • Loading...
  • Loading...
  • Loading...
  • Loading...