React工程接入TypeScript实践

3,371 阅读5分钟

最近换了一个部门,接手了一个react写的中小型项目,想着如果想长久维护几年,必须引入一些标准化的东西,于是就先从接入ts开始吧

接入ts的三种方案

网上看了一下,项目中引入ts共有三种方案

  1. awesome-typescript-loader

这个方案已经过时了,也很早就不维护了,而且效率极差,每次修改了一点代码,都会将TS代码转换为JS,然后再将JS代码给Babel转为低版本JS代码。

  1. 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+时,编译速度还是上不去

  1. @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 这个库

Process appLication S with Babel.png

看了一下这个库,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默认会开启编译的类型检查,比较多余,更改配置去掉

  1. 首先如果没有eject的,我们先暴露出cra脚手架的webpack打包配置 执行命令yarn eject或者npm run eject

  2. webpack.config.js中处理

编译时我们可以优化几个地方

1)检查babel-loader的预设

image.png

2)如果不用eslint做团队风格的统一,那么可以去掉,ts校验插件ForkTsCheckerWebpackPlugin完全替代eslint

  1. 在devServer中也去掉ts的检查(重要)

在scripts文件夹中的 start.js 脚本中(如果是用npm start启动的话)

找到useTypeScript这个属性直接改为false

这个useTypeScript属性会传递给createCompiler方法,从而执行类型的校验

找到这个属性 手动改为false

const useTypeScript = false

这样我们开发态使用ts仅仅依靠vscode编辑器自带的强大ts校验功能即可

同步webpack设置的一些别名

有的项目webpack会设置一些module的别名alias,ts也得配一下防止找不到,基本就是复制粘贴进tsconfig文件中

image.png

redux类型改造

待完成...

image.png

引入"@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了.

重点是:

  1. 注意在js/ts文件检查时加入babel-preset的ts预设

  2. 去掉ts-loader/awesome-typescript-loader和ForkTsCheckerWebpackPlugin等其他转义和类型检查的插件

  3. 开发模式下也要去掉这些插件

转移后一些ts语法初学者可以慢慢熟悉,提几点建议吧:

  1. 可以先改造最基础的业务组件

  2. 不熟悉的或者经常改动的可以先写any

  3. 前人挖的坑,如在原生对象的原型上加方法之类,可以先用//@ts-ignore 忽略

  4. 快速熟悉后可以在一些公共组件里实验高阶语法,练练泛型什么的

如果配置上还有问题,欢迎评论区提出!