前言
最近在看自己的以前写的React项目脚手架,跑起来的时候报错了,去查了一下才知道是用的转译ts方法 awesome-typescript-loader 已经过时了,这个包也几年没有更新了
查了一下资料,现在流行的方案是
TypeScript 和 Babel 团队官方合作的成果@babel/preset-typescript,至少是有保障的。
回顾一下 awesome-typescript-loader 方案
谈@babel/preset-typescript的优越性之前,还是先说下awesome-typescript-loader方案是如何对TypeScript进行处理的。
首先我们需要知道TypeScript是一个将TypeScript转换为指定版本JS代码的编译器,而Babel同样是一个将新版本JS新语法转换为低版本JS代码的编译器。
所以我们之前的方案每次修改了一点代码,都会将TS代码传递给TypeScript转换为JS,然后再将这份JS代码传递给Babel转换为低版本JS代码。
因此我们需要配置两个编译器,并且每次做了一点更改,都会经过两次编译。
babel-loader + @babel/preset-typescript 转译
@babel/preset-typescript和@babel/preset-react类似,是将特殊的语法转换为JS。
但是有点区别的是,@babel/preset-typescript是直接移除TypeScript,转为JS,这使得它的编译速度飞快。并且只需要管理Babel一个编译器就行了,因为我将脚手架中的typescript库卸载后,依然可以完美运行。而且重要的是你写的TypeScript不会再进行类型检测,使得你改动代码后中断运行的页面。
- 这种方案,当
webpack编译的时候,babel-loader 会读取 .babelrc 里的配置, 不会调用typescript(所以本地项目无需安装 typescript),不会去检查类型 - 但是
tsconfig.json是需要配置的,因为需要在开发代码时,让 idea 提示错误信息 webpack.config,js
rules: [
{
test:/\.(tsx?|jsx?)$/,
// 默认会调用 @babel/core
use:'babel-loader'
}
]
.babelrc
{
"presets": [
"@babel/preset-env"
"@babel/preset-react",
"@babel/preset-typescript"
]
}
使用 @babel/preset-typescript 需要注意的地方
有四种语法在 babel 中是无法编译的
- namespace:不要再用了,已经过时了。改用标准的 ES6 module(
import/export),在推荐的 tslint 规则中也建议不要使用 namesapce。
namespace Person{
const name = 'abc';
}
- 类型断言:改用 as 来断言类型(但是在 demo 中试了下,好像没报错,不知道是不是可以正常编译了)。
interface Person {
name: string;
age: number
}
let p1 = {age: 18} as Person;
console.log(p2.name);
let p2 = <Person>{age: 18};
console.log(p3.name);
- 常量枚举
const enum Sex {
man,
woman
}
- 历史遗留风格的 import/export 语法:
import xxx= require(…)和export = xxx。
Typescript 官方转向 ESLint 的原因
- TSLint 执行规则的方式存在一些架构问题,从而影响了性能,而修复这些问题会破坏现有规则;
- ESLint 的性能更好并且使用者较多
使用了 TypeScript,为什么还需要 ESLint
- TS 主要是用来做类型检查和语言转换的,顺带一小部分的语法检查
- ESLint 主要是用来检查代码风格和语法错误的
如果在使用 babel-loader + @babel/preset-typescript 这种方案时,也想要类型检查,该怎么做
- 第一种方案(再开一个 npm 脚本自动检查类型,需要同时启动两个线程)
// package.json
{
"scripts": {
// 再开一个 npm 脚本自动检查类型
"type-check": "tsc --watch",
},
}
// tsconfig.json
{
"compilerOptions": {
// 不生成文件,只做类型检查
"noEmit": true, \
},
}
- 第二种方案,也是最完美的方案(fork-ts-checker-webpack-plugin + @babel/preset-typescript)
//使用 fork-ts-checker-webpack-plugin来做类型检查 ,开辟一个单独的进程去执行类型检查的任务,这样就不会影响 webpack 重新编译的速度
// webpack.config.js
const ForkTsCheckerWebpackPlugin = require('fork-ts-checker-webpack-plugin');
//...
plugins: [
new ForkTsCheckerWebpackPlugin({
formatter: 'codeframe',
async: true,
}),
],
优点
- @babel/preset-typescript 做语法转换,fork-ts-checker-webpack-plugin 做语法检查, 集成在了 webpack 中,只用一个命令就可以启动。
- 编译速度快。
- 代码转译的时候也能发现类型错误。
参考
[译] TypeScript 牵手 Babel:一场美丽的婚姻
使用@babel/preset-typescript取代awesome-typescript-loader和ts-loader