- Published on
记一次 qiankun 引发的 bug
- Authors
- Name
- Eric Yuan
- @EricYuansz
Question
我们的业务与财税相关, 其中有一个功能点是对 ofd
版式文件的预览, 经常开发票的人对这个可能熟悉点. 对我来说这是个新的知识点, 毫无疑问, 咱先去万能的 github 上寻找是否有开源的库可以采用. 经过一番寻找和比对后, 选择了 ofd-tools 这个开源库进行开发.
一切都很顺利, ofd
文件也能顺利渲染, 但前提是在 qiankun
子应用单独启动的时候, 一旦通过主应用打开这个页面预览 ofd
文件时, 就莫名的空白了, 啥也没有, 连控制台的报错信息都没得, 郁闷...
定位
还能怎么办? debug 呗...
我把 github 的仓库克隆到本地, 然后通过 npm link
的方式去调试, 经过半个小时多的努力, 总算让我找到了罪魁祸首!
一路跟踪到了 ofd-tools
的一个叫 jszip
的依赖, 其中有个方法是这么写的:
var onGlobalMessage = function(event) {
if (event.source === global && // 👈
typeof event.data === "string" &&
event.data.indexOf(messagePrefix) === 0) {
runIfPresent(+event.data.slice(messagePrefix.length));
}
};
有一点经验的朋友应该一眼就能扫到问题所在了吧, 就是 event.source === global
这里, 如果在乾坤下, global
始终都不会等于 event.source
. 以为 qiankun 下的 global
是被 proxy
包了一层代理的, 这也是 qiankun 的沙箱特性1. 找到问题所在, 那剩下的就好办啦.
解决
通常修改这种源码的 bug 有很多方式, 比如直接给原仓库提 pr
, 或者直接修改本地的 node_modules
里的代码等.
多方均衡之下, 使用打补丁的方式去处理更加符合现在的项目情况. 由于我们使用的是 pnpm
, 直接使用 pnpm patch
和 pnpm patch-commit
命令即可实现. (如果你使用的是 npm, 可以参考 patch-package).
pnpm patch [email protected]
, 复制一个临时目录, 可以使用--edit-dir <dir name>
指定- 去临时目录中修改文件
var onGlobalMessage = function(event) {
if ((event.source === global || global.__POWERED_BY_QIANKUN__) &&
typeof event.data === "string" &&
event.data.indexOf(messagePrefix) === 0) {
runIfPresent(+event.data.slice(messagePrefix.length));
}
};
- 最后, 执行第一步返回的命令:
pnpm patch-commit '/private/var/folders/0w/3bs237hx0_5bb5pk_tfqq5140000gn/T/1803a7b5a7b556da907c1199e582b295'
即可,
此时, 在项目目录下就会新增一个 patches
文件夹, 里面有 [email protected]
文件, package.json
中也会增加以下内容:
"pnpm": {
"patchedDependencies": {
"[email protected]": "patches/[email protected]"
}
}
这样, 在后续的安装中, 都会自动安装这个补丁了, bug 也就随之完美解决🎉.
总结
纸上得来终觉浅, 绝知此事要躬行. 说一百遍沙箱, 都不如实实在在的改一次 bug 😂.
额外分享两个打补丁的经验:
- 对于
Vite
, 打完补丁后重启去要添加--force
命令, 因为 Vite 预构建,node_modules
下的.vite
文件会把加载的依赖做一个缓存. - 撤销补丁仅仅删除
patches
文件夹是没有用的, 需要npx patch-package <pkgName@x>
再重启.