最近换了一个部门,接手了一个react写的中小型项目,想着如果想长久维护几年,必须引入一些标准化的东西,于是就先从接入ts开始吧
接入ts的三种方案
网上看了一下,项目中引入ts共有三种方案
- awesome-typescript-loader
这个方案已经过时了,也很早就不维护了,而且效率极差,每次修改了一点代码,都会将TS代码转换为JS,然后再将JS代码给Babel转为低版本JS代码。
- ts-loader + babel-loader + fork-ts-checker-webpack-plugin
这个方案跟上面的差不多,当前的ts老项目使用的较多。
问题是ts-loader每当文件改动时,都会重新去转换和类型检查,当文件很多的时候,就会特别慢。所以还需要分配给 fork-ts-checker-webpack-plugin一个线程去执行类型检查。但是配置webpack使用多线程并行构建(thread-loader/happypack),对于 webpack 2/3 的性能提升明显,但使用 webpack 4+时,编译速度还是上不去
- @babel/preset-typescript的babel预设方案
看了一下,这种应该是接近完美的方案,@babel/preset-typescript这个库也被create-react-app脚手架所集成,这种方案的话只用babel插件把ts文件直接替换成js,不做任何额外的工作,这样我们只依赖vscode自带的ts类型检查即可,编译速度跟之前基本没有差别
安装相对应的包
项目中引入typescript这个库和部分types的包
"typescript": "^4.2.3",
"@types/react": "^16.13.1",
"@types/react-dom": "^16.0.0"
"@types/react-redux": "5.0.21",
目前大部分常用包都是自带.d.ts的解释不用额外安装对应的types包,如 antd 、axios之类
少数没有自带类型提示的可以用该网址查询有无其types包 www.typescriptlang.org/dt/search?s…
另外,使用redux的需要安装@types/react-redux包,来对connect方法提供支持
@babel/preset-typescript
这个react项目是用cra脚手架创建的,查了一下,脚手架自带安装babel-preset-react-app
库
而他的babel预设就是用的babel-preset-react-app
这个库
看了一下这个库,babel-preset-react-app
已经包含了 @babel/preset-typescript
,所以我们在项目的babel中不用再引入preset-typescript
预设
其实原理 preset-typescript
中含有 plugin-transform-typescript
这个babel插件,这个插件在babel-core的调度下把ts转成js文件
多说一句: 有些项目在babelrc文件中配置了"@babel/preset-react"这个babel官方预设,这个预设当前不包含ts插件,我们可以用react官方出品的的"babel-preset-react-app"预设来直接替换它
加上tsconfig.json
在根目录下新建一个加上tsconfig文件
没啥好说的,参考配置
{
"compilerOptions": {
"allowJs": true,
"target": "es5",
"sourceMap": true,
"emitDecoratorMetadata": true,
"experimentalDecorators": true,
"allowSyntheticDefaultImports": true,
"removeComments": true,
"noImplicitAny": false,
"moduleResolution": "node",
"jsx": "react",
"outDir": "dist",
"lib": [
"dom",
"es5",
"scripthost",
"es6"
],
"downlevelIteration": true,
},
"include": [
"src"
]
}
注意如果要逐步过渡,请把allowJs设为true
可以在这个网址下查tsconfig的配置 www.tslang.cn/docs/handbo…
去掉create-react-app开发时编译的类型检查
cra默认会开启编译的类型检查,比较多余,更改配置去掉
-
首先如果没有eject的,我们先暴露出cra脚手架的webpack打包配置 执行命令
yarn eject
或者npm run eject
-
webpack.config.js中处理
编译时我们可以优化几个地方
1)检查babel-loader的预设
2)如果不用eslint做团队风格的统一,那么可以去掉,ts校验插件ForkTsCheckerWebpackPlugin完全替代eslint
- 在devServer中也去掉ts的检查(重要)
在scripts文件夹中的 start.js 脚本中(如果是用npm start启动的话)
找到useTypeScript这个属性直接改为false
这个useTypeScript属性会传递给createCompiler方法,从而执行类型的校验
找到这个属性 手动改为false
const useTypeScript = false
这样我们开发态使用ts仅仅依靠vscode编辑器自带的强大ts校验功能即可
同步webpack设置的一些别名
有的项目webpack会设置一些module的别名alias,ts也得配一下防止找不到,基本就是复制粘贴进tsconfig文件中
redux类型改造
待完成...
引入"@types/react-redux"
需先引入"@types/react-redux": "5.0.21"这个库,redux的type库不用引,因为redux是用ts写的,自带ts定义
props匹配
主要处理connect包裹后的原生组件的props和引入该组件的父组件传参定义的协同
store
action/types等
一些方案导致的特殊类型处理
css modules方案解决
在根目录的src文件夹下建一个declaration.d.ts文件 名字随意起,也可以叫xx.d.ts
// 不检查cssmodule的定义,当然也可以引用webpack插件来检查它
declare module "*.css"
静态资源(png svg文件等)import处理
总结
这样改造后就可以逐步的把js和jsx文件转换为ts和tsx了.
重点是:
-
注意在js/ts文件检查时加入babel-preset的ts预设
-
去掉ts-loader/awesome-typescript-loader和ForkTsCheckerWebpackPlugin等其他转义和类型检查的插件
-
开发模式下也要去掉这些插件
转移后一些ts语法初学者可以慢慢熟悉,提几点建议吧:
-
可以先改造最基础的业务组件
-
不熟悉的或者经常改动的可以先写any
-
前人挖的坑,如在原生对象的原型上加方法之类,可以先用//@ts-ignore 忽略
-
快速熟悉后可以在一些公共组件里实验高阶语法,练练泛型什么的
如果配置上还有问题,欢迎评论区提出!