soda-x / blog

Here is my blog
753 stars 37 forks source link

吃一堑长一智系列:babel 之 semver #24

Open soda-x opened 3 years ago

soda-x commented 3 years ago

babel

困扰

作为工具开发者,我想最常收到的反馈就是 为啥昨天还好好的,今天就挂了

说实话这个问题同样也很困扰我。

背后的原因绝大部分都是依赖发生了不兼容的更新,这种问题非常让人头疼,主要牵扯出两个方面的问题:

举例我最近看到的三个因为 babel 升级引发的 bug

解法

要解这个问题的第一条出路:锁依赖。

目前云谦 @sorrycc 同学也在积极尝试锁依赖这条路。 具体可以参考下 https://github.com/umijs/deps https://github.com/umijs/umi/pull/6148

要解这个问题的第二条出路:走 PR。

今天我主要和大家分享下解决 issue babel 锁死 semver 7.0.0 导致 Gravity 无法浏览器实时编译 这个 PR 的由来,以及我在这个过程中感受到内容。

image

时间回到 2021/02/25 开始有同学和我反馈利用 Gravity 开发时,页面出现报错,报错信息如下:

1

起先我的怀疑是 babel preset 可能有变更,导致编译之后的内容出现其他第三方库的内容(比如 core-js)。排查了一会儿之后很快发现错误来源是 babel 自身引用的 semver 引起的,所以接下来我去查看 babel 官方仓库,想要找找 semver 的 blame 信息,果不其然,让我找到了这个升级的 PR

因为并不清楚 semver 被锁死在 7.0.0 的原因,所以第一时间,我给这个 PR 的作者留了言,PR 作者回复非常快,详细背景点这里 这边我大概和大家分享下原因。

祸因大佬 isaacs 发布了 semver@7.1.0,而该版本是个 breaking change 版本(不再支持 node-10 以下)。很多大佬纷纷追讨,为什么一个 breaking change 发生在 minor release 上,声讨作者知不知道该操作会害死一片开发者,因为大部分基础库都需要支持 node-8 极其以下,而很多库也已经升到 ^semver@7.0.0。可是 isaacs 态度也很强硬,他坚决不认为这个锅应该让他来背,他的出发点是发生在 EOL 软件平台的 breaking change 并不算 breaking change (因为他在 7.0 时就已经不再支持老的 node 版本,现在他只是做了个 engines 标记而已)。自此,大伙儿似乎都把这件事情当成一个笑话来看。

个人觉得 isaacs 的行为并不太负责。那么在了解了这个背景后,我大概看了下 semver 的历史代码

semver@5 semver@6 semver@7.0.0 semver@latest

其实发现 7.0.0 的代码初衷是好的,作者想要实现一个 lazy require 的效果,某种程度来提升执行效率,但是诸如 Gravity 作为构建,如果我需要打包 semver,这肯定就会出现问题,因为依赖的分析其实是静态化解析的过程,像 webpack 根本没法感知到这一层的逻辑(除非自写逻辑)。在翻看 smever 的历史 PR Remove the fancy preload logic in index.js #311 时也看到了作者对于这段 fancy logic (😹) 的无奈。

在明白了这些事情,以及看了 babel 历史版本对 semver 的诉求后,我提议能否把 semver 固定在 6.3.06.3.0 在是一个更为合理的选择。结果没想到,官方同意了这个提议,所以就有了这个 PR.

总结

简单盘一下

  1. 作为基础库开发者,对于自己的版本管理需要有更加严肃的对待,你的一举一动可能影响着几百万的开发者。(目前我写的一个工具库周下载量到达了 700w +,很难想象要是我发了一个不兼容版本会对整个社区有多么恶劣的影响)
  2. 作为 babel 这种影响力巨大的库,维护人员的压力可想而知,但是这次从问题反馈,到响应,到解决,都是分分钟的,这有点让我惊讶他们的效率(自己需要反思一下)
  3. 对反馈问题的人足够友好,会促进反馈方的积极性(自己需要反思一下)
  4. 作为开发者要敢于发表自己的声音,即使很可能是错的
  5. 各位大佬还是锁依赖吧,别争了,出门右拐找云谦。 o.o