Swagger-typescript-api与Typescript的兼容问题

最近工作中遇到一个问题,当时用很tricky的方式解决了,但是没彻底搞清楚root case,于是它像一根刺一样扎我到现在,索性利用假期彻底把它搞定。
具体是什么问题呢?
我的项目用到一个包:swagger-typescript-ap, 它可以帮助我们从swagger接口文档自动生成一些TS类型定义和请求函数。一直以来它都能正常工作,但是突然有一天,当我尝试用这个包时,控制台弹出报错信息:

host.fileExists is not a function

发现问题后,我做了以下分析和尝试:

  1. 排除了自己的代码的问题,我检查了了自己写的调用函数,非常简单,简单几行而已,bug没有生存空间;
  2. 找包里的Bug,于是尝试进入包的源码debug的时候发现try-catch包裹的范围太大了, 因此很难精准定位错误;
  3. 全局搜索host.fileIsExist之类的关键字, 但是发现搜不到;
  4. 继续在包的源代码里debug, 使用二分法逐步运行每一行,最终定位到问题存在于:https://github.com/acacode/swagger-typescript-api/blob/master/src/formatFileContent.js#L50
image.png

根据官方文档的例子, LanguageServiceHost 类应该指定fileExists,但是源码里没有指定,于是我把这个函数加了进去:

class LanguageServiceHost {
  ...
  fileExists(path){
    return ts.sys.fileExists(path)
  }
}

不出意外,修改之后一切又正常了。由于orgnizeImport函数来自typescript源码,所以我高度怀疑是当前typescript版本和swagger-typescript-api版本产生了冲突。
我将项目重新clone了一份存放在另一个文件夹,并且回退到了一个历史版本,这个版本是我最初成功引入swagger-typescript-api的commit,它是可以正常工作的,我想通过比较这个版本和最新版本之间的差异,来找到问题所在。

很快,我便有了新发现:


image.png

如上图所示,两个版本中:

  1. APP依赖typescript, package.json中指定版本范围为~4.1.5, 根据semver规则可得知范围是>=4.1.5 且 <5.0.0, 左右两边最终安装的具体版本都是4.1.6;
  2. APP依赖Swagger-typescript-api,这个包也依赖typescript, 但是它要求的版本范围是^4.2.4,根据semver规则可知范围是>=4.2.4且<5.0.0,但是!左边不可运行的版本最终安装的版本是4.8.4,而右边可运行的版本安装的是4.7.4;

那么很明显,ts4.7.4是和swagger-typescript-api兼容的,4.8.4不兼容。

问题是,为什么产生了这种差异呢?是我不小心自动升级了版本吗?
一开始,我全部的火力对准了package.json. 反复对比左右两个版本的package.json文件,反复尝试重装依赖,但是并没有什么收获,但是我发现一个奇怪的现象:可运行版本中,如果删除node_module重装全部依赖,是正常的,但是如果卸载Swagger-typescript-api后单独安装它,就不正常了。

联系这个线索,思来想去,才最终想起来,有package-lock.json的约束啊!
破案了破案了!通过翻提交记录,我发现我在之前不小心把package-lock.json删掉了然后重新运行了npm install, 而就是此时,恰好ts已经发布了新版本4.8.4,由于swagger-typescript-api以来的ts范围是^4.3.4,所以自动升级了!而删掉package-lock.json重装,会重新生成一份新的package-lock.json,所以自此之后我再怎么重装,都会安装4.8.4的ts, 而4.8.4ts和swagger-typescript-api不兼容,所以才产生了这个错误!

因此,我麻溜儿修改了package-lock.json, 然后再重装依赖,一切就恢复正常了。

在分析这个问题的过程中,找到了一篇很好的文章,解释了我一直存在的一个疑问:
如果出现多个包依赖同一个包的不同版本,NPM如何确定安装的版本,以及位置,以在确保能够正确运行的前提下减少冗余?
正解在此:https://npm.github.io/npm-like-im-5/npm3/duplication.html

最后,我还是打算好好研究下swagger-typescript-api这个包,确认bug,并尝试给它提PR。

============>
刚刚发现有好些人已经发现这个问题了,但是还没人提PR解决它
https://github.com/acacode/swagger-typescript-api/issues/404

============>
有人提到了一种方法,是我之前想到过的但是不知道具体怎么实施,那就是强行指定swagger-typescript-api中用到的typescript的版本号:
https://docs.npmjs.com/cli/v8/configuring-npm/package-json#overrides

============>
梦碎一地,已经有人提PR了,并且解法和我想的一致,https://github.com/acacode/swagger-typescript-api/pull/405/commits/8fba36a790fae21ef073154dab2c9da79908de17
看来下次遇到包的问题,手脚要快!

============>
更合理的解法在这里:https://github.com/acacode/swagger-typescript-api/pull/415 突然心里就平衡了,因为我还不知道为什么要这么写才更好。

你可能感兴趣的:(Swagger-typescript-api与Typescript的兼容问题)