优化ts-loader的使用
在熟悉项目的过程中发现项目使用 ts-loader 处理 TypeScript,存在优化空间,首先说明问题原因,其次给出几种优化方式。
1. 为什么使用 ts-loader 启动/热更新/构建会慢
ts-loader(ts-loader 使用的是 tsc)对 ts 文件进行处理时会进行类型检查,在开发/启动/热更新的过程中类型检查是比较耗时的,通过将 ts-loader 的 transpileOnly 默认设置为 true(不进行类型检查)进行对比可以查看 ts-loader 的类型检查耗时。
进行类型检查 | 不进行类型检查 | |
---|---|---|
analyze 命令查看 ts-loader 耗时 | 48.21s | 28.76s |
build 命令查看构建总耗时 | 71.91s | 47.83s |
类型有问题影响构建时 | 报 error,退出 | 不报 error,不退出 |
可以看到类型检查的耗时,除构建外,每次启动、热更新时ts-loader都会进行类型检查,直至检查完毕后,才算完成。
2. 优化方案
目前有几种处理方案个人认为优于当前纯ts-loader方案,考虑项目成熟度,选择fork-ts-checker-webpack-plugin是综合考虑对原有项目执行方式较合适的方案,而使用babel-loader处理TypeScript更适合脚手架生成的新项目。
2.1 使用fork-ts-checker-webpack-plugin分离类型检查和打包
插件介绍见GitHub:fork-ts-checker-webpack-plugin
概括一下,就是ts-loader关闭类型检查功能,让此插件开辟一条新的进程进行类型检查,以起到加快打包速度的作用。
在项目中的使用方式,先关闭ts-loader的类型检查,配置完成后,fork-ts-checker-webpack-plugin就会根据tsconfig.json进行类型检查了
|
|
相比ts-loader,使用插件后如果类型错误,打包不会受到影响,会在控制台进行提示
查看使用后的速度结果,与上面表格对比
fork-ts-checker-webpack-plugin | |
---|---|
analyze命令查看ts-loader耗时 | ts-loader的耗时结果与关闭检查一致 28.98s |
build命令查看构建总耗时 | |
类型有问题影响构建时 | 报error |
使用插件后启动/热更新速度也会加快。
总结:fork-ts-checker-webpack-plugin可以提升打包速度,同时兼顾类型检查
2.2 直接关闭ts-loader的类型检查,开发时利用vscode的静态类型检查,自行进行tsc的类型检查
这种方式如标题,只有在我们需要时使用tsc进行类型检查时才检查
检查指令
|
|
除此之外,我们build时也不进行类型检查,检查的步骤可以放到commit时,这样未通过检查的代码无法commit,需要用到husky和pre-commit
|
|
总结: 相较上述插件方案,类型检查不够自动,而且使用该方案时,最好的ts打包工具不应是ts-loader,而是babel-loader
2.3 使用babel-loader是更好的方案
使用babel-loader打包TypeScript可以查看这篇文章:TypeScript With Babel: A Beautiful Marriage,掘金上也有很多类似的文章。
概括下,就是从babel 7版本开始,babel支持了TypeScript的处理,但是babel本身不会对TypeScript进行检查,需要配合tsc或者eslint进行类型检查(方式可以参考2.2,或者可以使用2.1的插件)。
总结:
使用babel-loader的优点
- 构建体积更小
- 构建速度更快
- 构建目标更精确(可以指定支持百分之多少的浏览器),而ts-loader只支持构建出何种es标准的代码
- babel丰富的插件体系,更易拓展
使用babel-loader的缺点
- 不支持某些特定语法,如const enum {}
- 对于成熟项目有迁移成本,适合从零开始
3. 方案选取
- 在我们的项目中,使用2.1方案成本低、快、有效,之后的话完全迁移到babel-loader会更好。(目前还有babel-loader和ts-loader处理ts文件混用,用于处理特殊场景)
- 脚手架可以使用babel-loader代替ts-loader
总之,纯ts-loader不是最好的选择