React 項目從JavaScript 到 TypeScript 的無痛遷移

遷移準備

動態類型一時爽 代碼重構火葬場

TypeScript其與JavaScript的區別是提供的靜態類型系統,一些錯誤能夠再編譯階段儘早的發現和解決,提升了代碼的健壯性,加強了代碼的可讀性以及可維護性,動態類型一時爽 代碼重構火葬場以前很流行的一句話也能夠很好的解釋他們的區別,也正式這個緣由開始把既有項目遷移到TypeScript 語言上來。javascript

以上是一些基本教程,若是你已經熟悉TypeScript 和webpack 的基本知識,能夠跳過上面,開始遷移css

添加 TypeScript 配置文件 tsconfig.json

tsconfig.json 文件中指定了用來編譯這個項目的根文件和編譯選項。 首先在項目中安裝 typescript npm install typescript or yarn add typescript。 而後在項目的根目錄下添加 TypeScript 配置文件 tsconfig.json 文件, 使用npx tsc --init能夠配置。html

{
  "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'.

更多配置細節java

webpack 的配置

webpack.config.js 中須要加上 ts 的 loader 規則,ts 的rule 規則要在js 的rule 以前 ,以及添加配置解析的文件格式。下面就是 ts 配置在最前面且 tsconfig 轉成 es2016 的形式,如何確保編譯以後的代碼再被 babel loader 編譯成 es5 的形式? rules 規則數組到條件把以.tsx文件應用ts-loader 處理,而且 ts-loader 用於處理 ts 和 tsx 文件,解決這個問題須要如下兩個步驟node

  • 使用 ts-loader 把 ts 代碼編譯到 ES6
  • 使用 babel 把 ES6 代碼 和 jsx 編譯到 ES5

webpack 的配置一般以下react

{
    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 配置以下:webpack

{
  "presets": [
    "@babel/env",
    "@babel/react",
    "@babel/typescript"
  ]
}
複製代碼

如下經過幾種方式,來查看bulid打包後的文件中是否含有箭頭函數的=>,const等。git

第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的升級配置es6

第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等。github

  • 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>
    );
  }
}


複製代碼
相關文章
相關標籤/搜索