今年国庆前(2019),终于把我司的一个老项目重构完成(his前端重构经验),开发体验和效率上都有了质的飞越。不过由于一些不可抗原因(可用于重构时间不够充裕、历史代码量较大),还是没能将项目由 JavaScript 迁移到 TypeScript。
动机
对于喜欢ts好久好久的我来说(没错,我就是馋ts的类型系统,我下贱😝),不用ts我浑身难受。这周也是抽了些时间,让该系统支持ts与js混用了。当然并不是出于个人偏爱ts才做这样的改动,主要的动机有如下几点:
- 该项目属于中大型的后台项目,确实需要类型系统来提升代码的可维护性和可读性
- 在多人协作开发中,有类型提示可以减去很多不必要的沟通成本
- 我司的小程序已经采用ts,未来ts也是我们团队的主要方向之一
如果读者也想对项目进行升级,一定要先确定是否真的有必要,切莫为了满足个人爱好,从而给整个团队带来额外的成本。
项目介绍
需要改造的项目是通过 vue-cli3 生成的模板项目,开启了eslint。
升级过程
安装 typescript , ts-loader
npm i typescript ts-loader -D |
修改 webpack 配置
由于 vue-cli3 将 webpack 的配置全部隐藏起来了,只能通过在项目根目录下建立 vue.config.js
来修改配置,这里有两种方式来编写配置
- 通过直接修改
configureWebpack
选项,该方式和写webpack配置一样,在编译的时候,这份配置会通过 webpack-merge 合并到最终的配置中 - 通过 webpack-chain 链式修改配置,vue-cli3 内部也是通过这样的方式来维护
我选择的是第二种方式,因为它有友好的类型提示,不用边写边翻文档,关键的配置如下:
// vue.config.js |
主要的配置就是对于 .ts
、.tsx
文件先通过 ts-loader 解析,然后再交由babel处理。
如果你的项目是 vue-cli2 生成的话,直接在 build/webpack.base.conf.js
中做相关的修改即可,关键代码如下
// build/webpack.base.conf.js |
配置 tsconfig.json
ts的编译需要读取 tsconfig.json 文件,在根目录下创建 tsconfig.json 文件
// tsconfig.json |
进行到这一步,如果你只是想简单的在项目中混用ts的话(比如在.js、.vue中引入.ts),配置就算是全部完成了,你可以新建一个 .ts
文件,然后再入口文件中导入开发测试了;如果你还需要eslint进行代码规范、编写类组件等需求的,则需要继续进行下面的步骤
配置eslint
因为eslint的生态圈比较繁荣,typescript团队已经放弃了tslint从而转向eslint,所以这里我们也是用eslint作为代码规范校验的工具。需要安装以下工具
npm i @typescript-eslint/eslint-plugin @typescript-eslint/parser @vue/eslint-config-typescript -D |
然后修改eslint配置文件
module.exports = { |
支持在ts文件中导入.vue文件
默认情况下,typescript是无法识别 .vue 文件,当你需要在ts导入vue的单文件组件时(比如路由配置),编辑器会报错:找不到模块
。为了让ts能将 .vue 当成模块识别,需要在项目中创建shims-vue.d.ts
文件,这样ts就会把 .vue 文件当成模块来解析了。
// src/shims-vue.d.ts |
用装饰器注册组件(不推荐再使用)
npm i vue-property-decorator -S |
由于vue的api设计原因,导致其很难使用ts来编写vue组件(无法正确的推导出this),所以还需要安装vue-property-decorator
,通过它提供的一列装饰器,来编写类组件,用起来大有一种angular的感觉,具体可以移步到这里👉 https://github.com/kaorun343/vue-property-decorator,详细的参考demo👉TodoMvc-vue
不过vue官方已经决定放弃这种写法,学习react的hook并推出了composition-api,虽然社区对此颇有不满。所现阶段不推荐装饰器写法,等vue3正式发布后再逐步迁移vue组件吧。
在ts中导入js
既然是ts和js混用,那就会存在js中导入ts,或ts中导入js的情况。前者一般情况经过上面的配置,是不会有太多问题出现的。而后者(ts中导入js)可能在编写代码的时候,编辑器可能会提示一些小错误。这时候就需要你为相关的js文件编写类型提示文件了。
// a.js |
为了在ts中导入a.js不报错,我们要在相同的目录下创建a.d.ts
类型提示文件
export type sum = (m: number, n:number) => numer; |
如果导入的js文件代码量不是很多,建议直接修改源文件。
删除jsconfig.json
如果你使用了vscode作为开发工具,并且也配置了jsconfig.json
文件。那么在引入ts之后,你完全可以删除这个文件,然后将tsconfig.json
中的compilerOptions.allowJs
设置为true
即可。https://code.visualstudio.com/docs/languages/jsconfig
下一步计划
接下来会逐步将所有的 .js 文件加上类型系统,转成 .ts 文件。对于 .vue 单文件组件,继续保持原有写法,等到vue3发布后再做迁移的打算。当然也有可能会迁移到其他的框架,在这期间只要不断弱化 vue 的比重,让它之负责 ui 部分。
总结
- 安装
typescript
、ts-laoder
,修改webpack配置,支持对.ts
文件的解析 - 配置
tsconfig.json
- 配置
eslint
- 添加
shims-vue.d.ts
支持对 .vue 文件的识别 - 如果需要编写类组件,安装
vue-property-decorato
- 为需要导入到ts文件中的js文件编写类型文件,或者直接修改该文件为 .ts 文件