React 项目从JavaScript 到 TypeScript 的无痛迁移

迁移准备

动态类型一时爽 代码重构火葬场

TypeScript其与JavaScript的区别是提供的静态类型系统,一些错误可以再编译阶段尽早的发现和解决,提高了代码的健壮性,增强了代码的可读性以及可维护性,动态类型一时爽 代码重构火葬场之前很流行的一句话也可以很好的解释他们的区别,也正式这个原因开始把既有项目迁移到TypeScript 语言上来。

以上是一些基本教程,如果你已经熟悉TypeScript 和webpack 的基本知识,可以跳过上面,开始迁移

添加 TypeScript 配置文件 tsconfig.json

tsconfig.json 文件中指定了用来编译这个项目的根文件和编译选项。 首先在项目中安装 typescript npm install typescript or yarn add typescript。 然后在项目的根目录下添加 TypeScript 配置文件 tsconfig.json 文件, 使用npx tsc --init可以配置。


{
  "compilerOptions": {
    "outDir": "/dist",   
    "module": "esnext",
    "target": "es6",
    "lib": ["es6", "dom"],
    "sourceMap": true,
    "baseUrl": ".",
    "jsx": "react",
    "allowSyntheticDefaultImports": true,
    "moduleResolution": "node",
    "rootDirs": ["/src", "/test", "/mock","./typings"],
    "forceConsistentCasingInFileNames": true,
    "noImplicitReturns": true,
    "suppressImplicitAnyIndexErrors": true,
    "noUnusedLocals": true,
    "allowJs": true,
    "experimentalDecorators": true,
    "paths": {
      "@/*": ["./src/*"]
    },
  },
  "include": ["./src"],
  "exclude": [
    "node_modules",
    "build",
    "scripts",
    "acceptance-tests",
    "webpack",
    "jest",
    "src/setupTests.ts",
    "tslint:latest",
    "tslint-config-prettier"
  ]
}

复制代码
  • 读取所有可识别的 src 目录下的文件(通过 include)。
  • 接受 JavaScript 做为输入(通过 allowJs)。
  • 使用react ,"jsx"设置为"react",
  • 生成的所有文件放在 built 目录下(通过 outDir)。
  • 将 JavaScript 代码降级到低版本比如 ECMAScript 5(通过 target)'ES3' (default), 'ES5', 'ES2015', 'ES2016', 'ES2017', 'ES2018', 'ES2019' or 'ESNEXT'。
  • "module": "esnext", 指定模块的方式,可以为'none', 'commonjs', 'amd', 'system', 'umd', 'es2015', or 'ESNext'.

更多配置细节

webpack 的配置

webpack.config.js 中需要加上 ts 的 loader 规则,ts 的rule 规则要在js 的rule 之前 ,以及添加配置解析的文件格式。下面就是 ts 配置在最前面且 tsconfig 转成 es2016 的形式,如何确保编译之后的代码再被 babel loader 编译成 es5 的形式? rules 规则数组到条件把以.tsx文件应用ts-loader 处理,并且 ts-loader 用于处理 ts 和 tsx 文件,解决这个问题需要以下两个步骤

  • 使用 ts-loader 把 ts 代码编译到 ES6
  • 使用 babel 把 ES6 代码 和 jsx 编译到 ES5

webpack 的配置通常如下

{
    test: /\.tsx?$/,
    exclude: /node_modules/,
	 use: [
	    {
	      loader: 'babel-loader'
	    },
	    {
	      loader: 'ts-loader'
	    }
	  ]
}

// . babelrc 文件配置

{
   "presets": [
        "@babel/env",
        "@babel/preset-typescript"
    ],
    "plugins": [
        "@babel/proposal-class-properties",
        "@babel/proposal-object-rest-spread"
    ]
}

复制代码

配置扩展

下一代的 babel 7 带来了新的能力,有了解析 typescript 的能力,让我们可以不需要在编译两轮了。 babeljs.io/docs/en/bab…) .babelrc 配置如下:

{
  "presets": [
    "@babel/env",
    "@babel/react",
    "@babel/typescript"
  ]
}
复制代码

以下通过几种方式,来查看bulid打包后的文件中是否含有箭头函数的=>,const等。

第1种配置
 module: {
	  rules: [
	    {
	      test: /\.tsx?$/,
	      loader: 'babel-loader'
	 
	    },
        
 // . babelrc 文件配置以及对应的babel 要升级到版本7.4.0以上

{
   "presets": [
        "@babel/env",
        "@babel/preset-typescript"
    ],
    "plugins": [
        "@babel/proposal-class-properties",
        "@babel/proposal-object-rest-spread"
    ]
}

复制代码

babel的升级配置

第2种配置
 module: {
      rules: [
        {
          test: /\.tsx?$/,
          loader: 'ts-loader'
      
        },
复制代码
第3种配置
module: {
      rules: [
        {
          test: /\.tsx?$/,
           use: [
             {
               loader: 'babel-loader',
             },
             {
               loader: 'ts-loader'
             }
          ]
        },
复制代码

以上方式的配置中,在build 打包后的文件中都有=>,const 等的原因是tsconfig.json文件配置为"target": "es2016",的方式, 然后把tsconfig.json文件配置为"target": "es5",以上3种方式打包后的文件中都没有=> ,const等。

  • ts-loader 可以根据tsconfig.json的一个基本的配置,来支持 JSX,并将 TypeScript 编译到target指定的形式,如 ES5,es2016等
  • 以上都是分别针对ts文件和js文件分开处理

经过以上实验和考虑到webpack 的tree sharking优化, 我们的项目采用第三种方式。

找不到对应模块 Cannot find module './style.css

这个要看是第三方插件还是自己的模块,如果是第三方插件,使用npm 进行安装,如果是自己写的业务模块,就是引用路径的问题,这个要和tsconfig 文件的配置相对应。

为什么切 ts 会影响代码的写法,能否统一成 import 写法?

因为一直出现 Cannot find module './style.css'. 这个问题,找了官方的解释如下:

Using CSS Modules with TypeScript is not as obvious as with JavaScript. The reason is that TypeScript has special treatment for imports and if you try to use CSS Modules the same way you did in JavaScript:

有两种解决方案如下:

  • 最简单的方式使用require的方式 const style = require("./style.css");
  • 使用 typings-for-css-modules-loader
    • npm install --save-dev typings-for-css-modules-loader
    • 修改wepack 配置
//...

 rules: [
    {
      test: /\.css$/,
      use: [
        'style-loader',
        {
          loader: 'typings-for-css-modules-loader',
          options: {
            modules: true,
            namedExport: true
          }
        }
      ]
    }
  ]


复制代码

添加以上配置才可以使用 import 的方式。import style from './style.css';

转换为 .tsx 文件相应改变
  • react 组件的更改
    • 组件传入类型的定义
    • 函数类型的声明定义
    • props 和 state 都要做类型限制
import React from 'react';
import { connect } from 'react-redux';
import { getAuth } from '../../../modules/app/reducers/user/auth';
// import style from './style.css';

const style  = require("./style.css");
interface propTypes{
  getAuth: ()=>void;
}

class LoginScene extends React.PureComponent<propTypes> {

  handleClick = () => {
    this.props.getAuth();
  };

  render() {
    return (
      <div className={style.login}>
        // ...
      </div>
    );
  }
}


复制代码

转载于:https://juejin.im/post/5d26de056fb9a07ef6400809

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值