说在前头
项目采用的是react + webpack + typescript + tslint的技术栈,优化之后速度有了大幅度的提高。
优化之前的webpack配置
module.exports = {
...,
module: {
rules : [
{
test: /\.tsx?$/,
use: [
{
loader: 'awesome-typescript-loader',
options: {
configFileName: './tsconfig.json',
useCache: true,
}
}
],
},
{
test: /\.tsx?$/,
enforce: 'pre',
loader: 'tslint-loader',
options: {
configFile: path.resolve(__dirname, './tslint.json'),
emitErrors: true,
failOnHint: true
},
},
]
}
}
为什么想要弃用 awesome-typescript-loader呢?是因为每当文件改动时,该loader都会重新去转译和类型检查,项目慢慢大了,特别影响开发速度,并且会有类型检查遗漏的情况发生。
@babel/preset-typescript方案,直接移除了TypeScript,转为JS,这使得它的编译速度飞快。
优化之后的webpack配置
{
test: /\.(jsx?|tsx?)$/,
use: ['thread-loader', // 采用thread-loader多进程编译源文件
{
loader: 'babel-loader',
options: {
presets: ['@babel/preset-typescript'],
plugins: [
["@babel/plugin-proposal-decorators", {
legacy: true }],
['@babel/plugin-transform-typescript', {
allExtensions: true,
isTSX: true,
allowNamespaces: true }],
]
},
}
],
},
{
test: /\.tsx?$/,
use: ['eslint-loader'],
// 由于去除了ts,故采用eslint来进行代码检测,同时添加ForkTsCheckerWebpackPlugin和ForkTsCheckerNotifierWebpackPlugin两个plugin单独开个进程来做lint
},
babel.config.js(babel配置文件)
module.exports = function (api) {
api.cache(true);
const presets = [
"@babel/preset-typescript",
"@babel/preset-react",
"@babel/preset-env",
"mobx"
];
const plugins = [
"react-hot-loader/babel",
"@babel/proposal-object-rest-spread",
["@babel/plugin-transform-runtime"],
["@babel/plugin-transform-modules-commonjs", { "strictMode": true }],
["@babel/plugin-proposal-decorators", { "legacy": true }],
["@babel/plugin-proposal-class-properties", { "loose": true }]
];
return {
presets,
plugins
};
}
.eslintrc.js (eslint配置文件)
module.exports = {
parser: '@typescript-eslint/parser', //定义ESLint的解析器
extends: [
'plugin:react/recommended',
'plugin:@typescript-eslint/recommended'
], //定义文件继承的子规范
plugins: ['@typescript-eslint'], //定义了该eslint文件所依赖的插件
env:{ //指定代码的运行环境
browser: true,
node: true,
commonjs: true,
es6: true
},
settings: { //自动发现React的版本,从而进行规范react代码
"react": {
"pragma": "React",
"version": "detect"
}
},
parserOptions: { //指定ESLint可以解析JSX语法
"ecmaVersion": 2019,
"sourceType": 'module',
"ecmaFeatures":{
jsx:true
}
},
rules: {
}
}
需要特别指出的是,采用babel-loader之后,我们不能直接使用webpack-dev-server自带的hot模块,而是应该通过react-hot-loader来处理热更新的部分。
新增的package.json
devDependencies: {
"@babel/core": "^7.9.0",
"@babel/plugin-proposal-class-properties": "^7.8.3",
"@babel/plugin-proposal-decorators": "^7.8.3",
"@babel/plugin-proposal-object-rest-spread": "^7.9.5",
"@babel/plugin-transform-modules-commonjs": "^7.9.0",
"@babel/plugin-transform-runtime": "^7.9.0",
"@babel/plugin-transform-strict-mode": "^7.8.3", // 用来设置打包后js是否为严格模式
"@babel/preset-env": "^7.9.5",
"@babel/preset-react": "^7.9.4",
"@babel/preset-typescript": "^7.9.0",
"@typescript-eslint/eslint-plugin": "2.27.0",
"@typescript-eslint/parser": "2.27.0",
"babel-loader": "^8.1.0",
"babel-plugin-transform-class-properties": "^6.24.1",
"babel-plugin-transform-decorators-legacy": "^1.3.5",
"babel-preset-mobx": "^2.0.0", // 项目里用到了mobx
"eslint": "^6.8.0",
"eslint-loader": "^4.0.0",
"eslint-plugin-react": "^7.19.0",
"react-hot-loader": "^4.12.20",
},
dependencies: {
"@babel/runtime": "^7.9.2", // 构建时需要
}