vue项目引入ts步骤(小结)

最近考虑到老项目代码的可维护性以及稳定性,决定引入ts做规范检测。因为介绍的东西比较基础,如果介绍的不对,麻烦指正。

1. 简介

TypeScript 是 JavaScript 的一个超集,主要提供了类型系统和对 ES6 的支持。网上关于ts的学习资料很多,这里不做详细介绍。可参考的学习网站:

ts.xcatliu.com/

typescript.bootcss.com/

2. 安装依赖包

cnpm i typescript ts-loader --save-dev

3. 添加tsconfig.json文件

在项目根目录下添加 tsconfig.json 文件。tsconfig.json 文件用来指定ts的编译选项。配置可参考:

https://typescript.bootcss.com/tsconfig-json.html

项目工程 tsconfig.json 文件配置如下:(仅做参考)

{
  \"compilerOptions\": {
    \"baseUrl\": \".\",
    \"experimentalDecorators\": true,
    \"emitDecoratorMetadata\": true,
    \"noEmitOnError\": true,
    \"target\": \"esnext\",
    \"module\": \"esnext\",
    \"strict\": true,
    \"allowJs\": true,
    \"noEmit\": false,
    \"noImplicitThis\": true,
    \"esModuleInterop\": true,
    \"sourceMap\": true,
    \"moduleResolution\": \"node\"
  },
  \"include\": [
    \"src/**/*\", \"types\"
  ],
  \"exclude\": [
    \"node_modules\",
    \"build\"
  ]
}

4. webpack打包配置修改

webpack.config.js 打包文件修改,新增对.ts文件的打包配置。

4.1 入口文件后缀名由.js修改为.ts

module.exports = {
  entry: {
    app: [\'@babel/polyfill\', \'./src/main.ts\']
  }
}

4.2 extensions 文件扩展名增加 .ts, .tsx 文件的支持

tsx针对react项目文件的支持,因为我们的工程基于vue开发,支持.ts文件就可以了。

module.exports = {
  resolve: {
    extensions: [\'.js\', \'.vue\', \'.json\', \'.css\', \'.ts\']
  }
}

4.3 loader增加对ts文件的支持

使用ts-loader来转换ts文件。

module.exports = {
  module: {
    rules: [
      {
        test: /\\.ts?$/,
        loader: \'ts-loader\',
        exclude: /node_modules/,
        options: {
         appendTsSuffixTo: [/\\.vue$/],
        }
      }
    ]
  }
}

5. eslint 添加对ts文件的检测

5.1 安装依赖包

cnpm i @typescript-eslint/parser @typescript-eslint/eslint-plugin eslint-config-typescript eslint-plugin-typescript --save-dev

@typescript-eslint/parser ts文件解析器

@typescript-eslint/eslint-plugin 版本号需要与@typescript-eslint/parser的版本一致,解析器相关的配置选项

eslint-config-typescript 针对ts项目配置的eslint检测规范

5.2 .eslintrc配置文件修改

.eslintrc配置文件修改,支持对ts的文件的校验。经过多次调整,我们工程的 .eslintrc 配置文件如下:

{
  \"parserOptions\": {
    \"parser\": \"@typescript-eslint/parser\",
    \"project\": \"./tsconfig.json\",
    \"extraFileExtensions\": [\".vue\"],
    \"ecmaVersion\": 2017,
    \"sourceType\": \"module\",
    \"ecmaFeatures\": {
      \"modules\": true
    }
  },
  \"env\": {
   \"jest\": true,
   \"browser\": true
  },
  \"settings\": {
   \"import/resolver\": {
    \"node\": {
     \"extensions\": [\".js\", \".jsx\", \".ts\", \".tsx\", \".eslintrc\"]
    },
    \"webpack\": {
     \"config\": {
      \"resolve\": {
       \"alias\": {
        \"src\": \"src\"
       }
      }
     }
    }
   }
  },
  \"plugins\": [
    \"vue\",
    \"babel\",
    \"@typescript-eslint\"
  ],
  \"extends\": [
    \"eslint:recommended\",
    \"plugin:vue/base\",
    \"typescript\",
    \"standard\"
  ],
  \"rules\": {
    \"func-names\": 0,
    \"one-var\": [1, \"never\"],
    \"prefer-const\": 1,
    \"no-unused-expressions\": 1,
    \"new-cap\": 2,
    \"prefer-arrow-callback\": 2,
    \"arrow-body-style\": 0,
    \"max-len\": [
      1,
      {
      \"code\": 200,
      \"ignoreStrings\": true,
      \"ignoreUrls\": true,
      \"ignoreRegExpLiterals\": true
      }
    ],
    \"consistent-return\": \"off\",
    \"default-case\": 2,
    \"prefer-rest-params\": 2,
    \"no-script-url\": 0,
    \"no-console\": [
      2,
      {
      \"allow\": [\"info\", \"error\", \"warn\", \"log\"]
      }
    ],
    \"no-duplicate-imports\": 2,
    \"newline-per-chained-call\": 2,
    \"no-underscore-dangle\": 2,
    \"eol-last\": 2,
    \"no-useless-rename\": 2,
    \"class-methods-use-this\": 0,
    \"prefer-destructuring\": 0,
    \"no-unused-vars\": 0,
    \"@typescript-eslint/no-unused-vars\": 1,
    \"no-plusplus\": 0,
    \"import/prefer-default-export\": 0,
    \"import/no-dynamic-require\": 2,
    \"@typescript-eslint/no-var-requires\": 2,
    \"no-use-before-define\": [
      \"error\",
      {
      \"functions\": false
      }
    ],
    \"@typescript-eslint/no-use-before-define\": 0,
    \"@typescript-eslint/explicit-function-return-type\": 0,
    \"@typescript-eslint/interface-name-prefix\": 0,
    \"no-invalid-this\": 0,
    \"babel/no-invalid-this\": 2,
    \"no-await-in-loop\": \"off\",
    \"array-callback-return\": \"off\",
    \"no-restricted-syntax\": \"off\",
    \"@typescript-eslint/no-explicit-any\": 0,
    \"import/no-extraneous-dependencies\": 0,
    \"import/no-unresolved\": 0,
    \"@typescript-eslint/explicit-member-accessibility\": 0,
    \"@typescript-eslint/no-object-literal-type-assertion\": 0,
    \"no-param-reassign\": [
      2,
      {
      \"props\": false
      }
    ],
    \"generator-star-spacing\": \"off\",
    \"indent\": [2, 4, {
      \"SwitchCase\": 1
    }],
    \"eqeqeq\": 0,
    \"no-else-return\": 2,
    \"arrow-parens\": 0,
    \"space-before-function-paren\": [\"error\", \"never\"],
    \"comma-dangle\": [2, \"never\"],
    \"semi\": [2, \"always\"]
  }
 }

注意\”extends\”: [\”plugin:vue/base\”], 只能选择vue/base,不能用vue/recommend。不然会有规则冲突。

6. 项目文件转换

项目配置好后,开始对老代码进行改造,来支持ts的语法检测。

6.1 增加ts声明文件目录

项目中总会依赖一些资源包,或是自己开发的一些组件,这些文件需要补充声明文件,声明文件就是将多个声明语句放在一起,这些声明文件可统一放到一个目录里。这个目录需要包含在 tsconfig.json 文件的include里。

ms工程在根目录下新建 types 目录,目前包含 vue.d.ts, request.d.ts, dialog.d.ts, base.d.ts 等文件。

6.2 全局vue.d.ts声明文件

需要在ts环境下识别vue文件,需要添加 vue.d.ts 全局声明文件,例子如下:

import VueRouter, { Route } from \'vue-router\';
import RequestAxios from \'./request\';

declare module \'*.vue\' {
  import Vue from \'vue\';
  export default Vue;
}
declare module \'vue/types/vue\' {
  interface Vue {
    $router: VueRouter;
    $route: Route;
    $request: RequestAxios;
    ....
  }
}

6.2 vue文件的改造

vue文件的改造,只改造js部分,代码大致修改如下:

import { Vue, Component, Prop, Watch } from \'vue-property-decorator\';

@Component({
  components: {
    ....
  }
})
export default class MyComponent extends Vue {
  // prop
  @Prop({ default: () => {} }) readonly pageInfo !: any

  // data
  private showAnimation : boolean = true;

  // watch
  @Watch(\'showModuleIndex\')
  onShowModuleIndexChanged(newValue: any) {
    this.$emit(\'input\', newValue);
  }

  // computed
  get list() {
    const { page, cityList } = this;
    return page.cityList.split(\',\').map(
      cityId => cityList.find(c => String(c.id) === cityId)
    );
  }

  // mounted
  private mounted() :void {
    this.initEditor();
  }

  // methods
  private initEditor() :void {
    ....
  }
}
</script>

6.3 js文件的改造

将文件后缀名更改为.ts,然后加上类型就可以了。

7. 踩坑总结

大部分都是eslint校验时的报错,按照提示修复就可以了。

\”vue/html-indent\”: [2, 4] eslint这条规则去掉

\”plugin:vue/base\”与\”plugin:vue/recommend\”的区别

8. 总结

项目改造过程中,大部分时间都是在查配置兼容问题,配置这块解决了,改造起来速度还是挺快的。虽然前期会有一些改造成本,但是长远来看,还是有意义的。毕竟很多代码类型上的问题在开发阶段就可以暴露,不用等到运行时才发现了。

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持。

© 版权声明
THE END
喜欢就支持一下吧
点赞0 分享
评论 抢沙发

请登录后发表评论

    暂无评论内容