如何将项目改为TypeScript

2019-09-30  本文已影响0人  kingller

准备工作

 git clone git@git.gaiaworks.cn:fe/thanos-template-public.git
 git clone git@git.gaiaworks.cn:fe/walle-template-mocker.git

请大家先下载代码,并将thanos-template-public切换至typescript-demo分支,安装包,并运行

Step 1 升级

npx @pandora/upgrade

将组件库升级至最新版本

Step 2 i18next

由于i18next包进行了大版本的升级,我们需要进行一些修改

reactI18nextModule  =>  initReactI18next
translate  =>  withTranslation

Step 3 tsconfig.json

创建tsconfig.json配置文件

{
    "compilerOptions": {
        "outDir": "./dist/",
        "sourceMap": true,
        "noImplicitAny": true,
        "strictNullChecks": false,
        "module": "commonjs",
        "target": "ESNext",
        "jsx": "react",
        "experimentalDecorators": true,
        "emitDecoratorMetadata": true,
        "allowSyntheticDefaultImports": true, // 允许使用 ES2015 默认的 import 风格
        "esModuleInterop": true, // 可调用的CommonJS模块必须被做为默认导入,在已有的“老式”模块模式之间保证最佳的互通性
        "moduleResolution": "node",
        "allowJs": true
    },
    "include": [
        "./src/**/*"
    ],
    "files": [
        "./node_modules/tsx-control-statements/index.d.tsx",
        "./node_modules/hrone-react/src/typings/index.d.ts"
    ]
}

这里,我们将tsx-control-statements和组件库中的定义文件./node_modules/hrone-react/src/typings/index.d.ts加入files中。
并将esModuleInterop设为true,以兼容老式模块,统一import风格为import XX from 'XX'
你可以在这里了解更多关于tsconfig.json文件的说明。

Step 4 webpack

修改webpack.config.js文件

module.exports = {
    context: __dirname,
    entry: './src/index.tsx',
    output: {
        filename: 'bundle.js',
        path: `${__dirname}/dist`
    },

    // Enable sourcemaps for debugging webpack's output.
    devtool: "#source-map",

    resolve: {
        // Add '.ts' and '.tsx' as resolvable extensions.
        extensions: ['.js', '.ts', '.tsx']
    },

    module: {
        rules: [
            // All files with a '.ts' or '.tsx' extension will be handled by 'babel-loader'.
            {
                test: /\.tsx?$/,
                loader: 'babel-loader',
                options: {
                    presets: ['@babel/preset-typescript'],
                    plugins: [['@babel/plugin-transform-typescript', { allowNamespaces: true }]],
                },
                include: [
                    path.resolve(__dirname, 'src'),
                    path.resolve(__dirname, 'node_modules/hrone-react'),
                    path.resolve(__dirname, '../../hrone-react/src'),
                ],
            },
        ]
    }
};

这里我们使用@babel/plugin-transform-typescript插件来处理TypeScript
那么,TypeScript的类型检测怎么办呢?不是相当于废了吗?这里我们使用 fork-ts-checker-webpack-plugin来启用TypeScript类型检测。

继续修改webpack.config.js

const ForkTsCheckerWebpackPlugin = require('fork-ts-checker-webpack-plugin');
const ForkTsCheckerNotifierWebpackPlugin = require('fork-ts-checker-notifier-webpack-plugin');

module.exports = {
    // ...
    plugins: [
        new ForkTsCheckerWebpackPlugin({
            // 将async设为false,可以阻止Webpack的emit以等待类型检查器/linter,并向Webpack的编译添加错误。
            async: false
        }),
        // 将TypeScript类型检查错误以弹框提示
        // 如果fork-ts-checker-webpack-plugin的async为false时可以不用
        // 否则建议使用,以方便发现错误
        new ForkTsCheckerNotifierWebpackPlugin({
            title: 'TypeScript',
            excludeWarnings: true,
            skipSuccessful: true,
        }),
    ]
};

Step 5 Prettier

在项目根目录下创建配置文件.prettierrc.js

module.exports = {
    printWidth: 120,
    tabWidth: 4,
    singleQuote: true,
    semi: true,
    trailingComma: 'es5',
    bracketSpacing: true,
    jsxBracketSameLine: true,
    arrowParens: 'always',
    parser: 'typescript'
};

我们引入prettier来自动化格式代码

Step 6 ESLint

创建配置文件

在项目根目录下创建.eslintrc.js文件进行配置:

module.exports = {
    parser: '@typescript-eslint/parser', // Specifies the ESLint parser
    extends: [
        'plugin:@typescript-eslint/recommended', // Uses the recommended rules from the @typescript-eslint/eslint-plugin
        'plugin:react/recommended',
        'plugin:jsx-control-statements/recommended',
        'prettier/@typescript-eslint', // Uses eslint-config-prettier to disable ESLint rules from @typescript-eslint/eslint-plugin that would conflict with prettier
        'plugin:prettier/recommended', // Enables eslint-plugin-prettier and displays prettier errors as ESLint errors. Make sure this is always the last configuration in the extends array.
        'prettier/react'
    ],
    "settings": {
        "react": {
            "version": "detect",
        }
    },
    plugins: ['@typescript-eslint', 'react', 'jsx-control-statements', 'prettier'],
    env: {
        browser: true,
        node: true,
        es6: true,
        mocha: true,
        'jsx-control-statements/jsx-control-statements': true
    },
    globals: {
        $: true
    },
    rules: {
        'prettier/prettier': 1,
        '@typescript-eslint/indent': ['error', 4, { VariableDeclarator: 4, SwitchCase: 1 }],
        '@typescript-eslint/no-unused-vars': 0,
        "@typescript-eslint/interface-name-prefix": 0,
        "@typescript-eslint/explicit-member-accessibility": 0,
        "@typescript-eslint/no-triple-slash-reference": 0,
        "@typescript-eslint/ban-ts-ignore": 0,
        "@typescript-eslint/no-this-alias": 0,
        "@typescript-eslint/triple-slash-reference": ['error', { "path": "always", "types": "never", "lib": "never" }],
        'no-console': ['warn', { allow: ['warn', 'error'] }],
        "eqeqeq": ['warn', 'always'],
        "prefer-const": ['error', {"destructuring": "all", "ignoreReadBeforeAssign": true}],
        // React相关校验规则
        "react/jsx-indent": [2, 4],
        "react/jsx-no-undef": [2, { allowGlobals: true }],
        "jsx-control-statements/jsx-use-if-tag": 0
    }
};

由于TypeScript 官方决定全面采用 ESLint,我们引入ESLint来进行代码检测。

强制校验和格式化

安装

npm install --save-dev husky lint-staged

修改 package.json

{
  "name": "project-name",
  // ...
  "scripts": {
    "eslint": "eslint --ext .tsx,.ts --fix ./src", // 需要在这里指定校验.tsx,.ts后缀的文件
  },
  "husky": {
    "hooks": {
      // git commit 前强制代码格式化和代码校验
      "pre-commit": "lint-staged"
    }
  },
  "lint-staged": {
    "*.{ts,tsx}": [
      "npm run eslint",
      "prettier .prettierrc.js --write",
      "git add"
    ]
  }
}

Step 7 将代码改为TypeScript

现在所有的配置都已做好,我们只要将我们的代码一步步改为TypeScript就可以了。

上一篇下一篇

猜你喜欢

热点阅读