create-react-app + Typescript脚手架搭建
1、创建使用ts的新项目
yarn create react-app my-test-app --template typescript
2、配置tsconfig.json
(1)在根目录下新建文件tsconfig.extend.json
{ "compilerOptions": { "baseUrl": "src", "paths": { "@/*": ["./*"] } } }
"extends": "./tsconfig.extend.json"
(3)允许装饰器语法
"experimentalDecorators": true
3、安装依赖
(1)yarn add antd
(2)安装craco以覆盖webpack配置
yarn add @craco/craco
"scripts": { "start": "craco start", "build": "craco build", "test": "craco test" },
(3)安装其他craco插件
yarn add craco-antd
yarn add craco-less
yarn add craco-alias
(4)在根目录下新建craco.config.js文件
const CracoAntDesignPlugin = require("craco-antd"); const CracoAlias = require("craco-alias"); const CracoLessPlugin = require("craco-less"); const path = require('path'); module.exports = { plugins: [ /* antd组件按需加载&样式覆盖等 */ { plugin: CracoAntDesignPlugin, options: { customizeThemeLessPath: path.join( __dirname, "src/styles/antd.theme.less" ), }, }, /* 支持less module */ { plugin: CracoLessPlugin, options: { cssLoaderOptions: { modules: { localIdentName: "[local]_[hash:base64:5]" }, }, modifyLessRule: function(lessRule, _context) { lessRule.test = /\.(module)\.(less)$/; lessRule.exclude = path.join(__dirname, 'node_modules'); return lessRule; }, }, }, /* 别名设置 */ { plugin: CracoAlias, options: { source: "tsconfig", baseUrl: "./src", tsConfigPath: "./tsconfig.extend.json" } }, ], devServer: (devServerConfig) => { return { ...devServerConfig, // 服务开启gzip compress: true, proxy: { '/api': { target: 'https://test.com/', changeOrigin: true, xfwd: false, } } } } };
(5)在react-app-env.d.ts文件中新增(否则将无法正常使用less module!!!)
/* 允许在ts中使用import styles from '*.less' */ declare module '*.less' { const styles: any; export = styles; }
(6)安装eslint
yarn add eslint @typescript-eslint/parser @typescript-eslint/eslint-plugin eslint-config-airbnb eslint-import-resolver-typescript eslint-plugin-import eslint-plugin-jsx-a11y eslint-plugin-react eslint-plugin-react-hooks --dev
在根目录下新建.eslintrc.js
module.exports = { env: { browser: true, es6: true, }, extends: [ 'plugin:react/recommended', 'plugin:@typescript-eslint/recommended', 'airbnb', 'airbnb/hooks', ], parser: '@typescript-eslint/parser', parserOptions: { ecmaFeatures: { jsx: true, tsx: true, modules: true }, ecmaVersion: 2020, sourceType: 'module', }, plugins: [ 'react', '@typescript-eslint', ], rules: { "react/jsx-filename-extension": [2, { "extensions": [".js", ".jsx", "ts", "tsx"] }], "@typescript-eslint/explicit-function-return-type": [0, { allowTypedFunctionExpressions: true }], "react/state-in-constructor": 0, "import/extensions": [2, 'ignorePackages', { ts: 'never', tsx: 'never', json: 'never', js: 'never' }], "jsx-a11y/click-events-have-key-events": 0, "jsx-a11y/no-static-element-interactions": 0, "react/jsx-props-no-spreading": 0, "no-unused-expressions": 0, "jsx-a11y/anchor-is-valid": 0, "no-nested-ternary": 0, "react/static-property-placement": 0, "object-curly-newline": 0, }, settings: { "import/resolver": { node: { extensions: [".js", ".jsx", ".ts", ".tsx"] }, typescript: { directory: "./tsconfig.json" } }, }, };
(7)prettier
yarn add prettier eslint-config-prettier eslint-plugin-prettier -D
在根目录下新建.prettierrc.js
module.exports = { "semi": true, "singleQuote": true, "trailingComma": "es5", "tabWidth": 2, "useTabs": false };
修改.eslintrc.js
extends: [ ... 'prettier/@typescript-eslint', 'plugin:prettier/recommended' ],
(8)stylelint
yarn add stylelint stylelint-config-recommended stylelint-config-recess-order stylelint-config-standard -D
在根目录下新建.stylelintrc.json
{ "extends": [ "stylelint-config-recommended",
"stylelint-config-recess-order", "stylelint-config-standard" ], "rules": { "indentation": 2, "selector-pseudo-class-no-unknown": [ true, { "ignorePseudoClasses": ["global"] } ] } }
(9)增加pre-commit
yarn add pre-commit --dev
yarn add lint-staged --dev
"lint": "eslint src --fix --ext .ts,.tsx", "lint-staged": "lint-staged"
"lint-staged": { "**/*.{ts,tsx,less}": [ "prettier --write" ], "**/*.{ts,tsx}": "yarn lint", "**/*.less": "stylelint --syntax less" }, "husky": { "hooks": { "pre-commit": "yarn lint-staged" } }