当前位置: 首页 > 科技观察

Nest.js这么大的项目,是如何优化ts编译性能的?

时间:2023-03-12 18:22:02 科技观察

Nest.js是一个流行的node服务端框架,最近发现它有一个很大的PR。本次PR涉及50多个文件,800多行代码改动:同学们肯定会认为这么多代码改动一定是大版本升级。但是并没有更新版本号:可以看到Nest从gulp编译切换到了tsc编译,但是版本号还是9.1.2。为什么这么大的PR版本号不改?看看PR的内容:这个PR从gulp切换到tsc的ProjectReference,优化了编译性能,启动更简单。只是构建相关的优化,不更新版本号也很正常。可能有同学会问,什么是ProjectReference?为什么能提高tsc编译性能?我们先看看Nest是如何编译nest源码的:通过gulp的build命令,将产品输出到node_modules/@nestjs。gulp记录下项目中每个包的tsconfig.json:然后用tsc读取每个tsconfig.json编译ts代码:这个过程很容易理解,就是通过tsc根据每个tsconfig.json编译ts代码,并输出到不同的目录,gulp只是组织了这个过程。那么现在tsc是怎么编译的呢?首先,现在不用gulp组织流程了,直接执行tsc就可以了,加-b就可以了,这个是用来开启项目引用的:所谓项目引用就是这个东西:image.png就是要通过tsconfig中的引用引用其他项目。如果其他项目也依赖于其他项目,可以再次引用:编译的时候会一起编译。这和单独运行tsc不一样吗?有区别吗?差别很大。现在执行tsc-b后,每个项目下都会生成这样一个tsconfig.build.tsbuildinfo文件:每个项目都有:那么这个文件有什么用呢?看一下内容:记录了本项目所有编译的文件名:和hash的版本号,是否访问全局作用域:再编译的时候有没有区别?肯定是编译完了,就不用再编译了。相当于做了一层缓存。每次比较变化文件的hash,只有有变化,才会编译。不同的项目分别缓存。如果一个项目发生变化,只需要单独编译那个项目,其他的可以跳过。这自然会提高编译性能。不过只是提高了二次编译的性能,第一次编译还是需要全编译。这就是为什么在PR中提到更快的重建:我们知道为什么我们从gulp切换到tsc项目参考。新版nest如何调试?我们可以直接使用nest工程自带的案例调试。Nest提供了一个示例目录,下面有很多示例项目:我们新建一个.vscode/launch.josn调试配置文件:image.png添加这个调试配置:{"name":"LaunchviaNPM","request":“启动”,“runtimeArgs”:[“运行脚本”,“开始”],“runtimeExecutable”:“npm”,“控制台”:“integratedTerminal”,“cwd”:“${workspaceFolder}/sample/01-cats-app/","skipFiles":["/**"],"type":"node"}这个配置很好理解,就是在目录01-cats-下执行npmrun应用程序启动。控制台被指定为integratedTerminal是什么意思?运行一下就知道:运行服务,打断点,访问localhost:3000/cats,你会发现调试控制台打印的日志:没有颜色,自然不习惯。指定console为integratedTerminal,然后重新调试:现在log打印在terminal中,是不是比较顺眼?这就是调试嵌套项目的方式。那么如何调试nest源码呢?现在调用堆栈中的嵌套代码已编译:如果要调试源代码,则需要sourcemap。默认情况下,嵌套编译不生成sourcemap,我们需要更改编译配置:更改packages/tsconfig.build.json,添加这两个配置。sourceMap为true表示生成sourcemap,inlineSources是将源代码保存在sources中,默认生成的sourcemap不包含源代码。执行npm运行构建。你会发现生成了sourcemap:但是在node_modules/@nestjs下还是没有sourcemap,因为还少了一步:nest的build命令有个post命令:每次build完成,这些文件都会会自动复制到node_modules/下@nestjs:sourcemap默认是不编译的,自然也就没有move文件了。补上这块,再次执行npmrunbuild:然后去node_modules看一下:现在有sourcemap了,完美!然后运行nest项目的调试:为什么不是源码?这真的很棘手,因为在node_modules下有一个默认的配置是禁止sourcemap搜索的:去掉就行了:然后再运行调试:这时候你会发现调试的是nest的ts源码!总结Nest最近通过一个大PR,将构建方式从gulp+tsc切换为项目参考方式tsc-b,可以大大提升tsc编译性能。原理是项目引用模式会生成一个缓存文件,记录每个项目编译了哪些文件,hash是多少,这样重新编译时可以跳过没有更新的文件。新版nest源码的调试也需要生成sourcemap,修改编译配置,生成sourcemap的代码(只是注意VSCodeNodeDebugger中的一个坑,不搜索sourcemap默认情况下在node_modules下)。然后就可以愉快的调试nest的ts源码了!像nest这样大的项目都是使用tscprojectreference来优化编译性能的,所以我们的项目自然可以通过projectreference进行优化。我们在优化ts编译性能的时候可能会考虑到这个方面。