第二章的配置基本已能达到正常的开发需求了。但是还有很多地方可以进行改善。
第三章 改善项目
使用最新的ES语法
React开发中难免要用到ES最新语法。例如常用的Decorators还在Stage 2阶段,Dynamic import还在Stage 3阶段。这些新的语法并没被@babel/preset-env
涵盖。因此我们需要额外配置对应的babel插件。
安装babel插件:
- 支持装饰器
@babel/plugin-proposal-decorators
- 支持类属性
@babel/plugin-proposal-class-properties
- 支持动态import
@babel/plugin-syntax-dynamic-import
配置.babelrc
文件:
{
"presets": ["@babel/preset-env", "@babel/preset-react"],
"plugins": [
// 注意decorators插件要写在class-properties前面
// decorators插件需要配置legacy为true来兼容以前的装饰器写法
["@babel/plugin-proposal-decorators", { "legacy": true }],
["@babel/plugin-proposal-class-properties", { "loose": true }],
"@babel/plugin-syntax-dynamic-import"
]
}
添加css预处理与postcss
我们可以使用sass来增强css的编程和抽象能力,使用postcss的autoprefixer
插件给css自动添加浏览器厂商前缀。
安装:
sass-loader
postcss-loader
autoprefixer
webpack.dev.js
的配置:
// ...
module: {
rules: [
{
test: /\.scss$/,
// loader是从后往前加载的,postcss-loader得在sass-loader前面
use: ["style-loader", "css-loader", "postcss-loader", "sass-loader"]
},
// ...
]
},
// ...
webpack.prod.js
的配置:
// ...
module: {
rules: [
{
test: /\.scss$/,
use: [
MiniCssExtractPlugin.loader,
"css-loader",
"postcss-loader",
"sass-loader"
]
},
// ...
]
},
// ...
在项目根目录下创建postcss.config.js
文件:
module.exports = {
plugins: [require("autoprefixer")]
};
配置浏览器兼容范围
.babelrc
内配置的@babel/preset-env
能自动为项目打包必要的polyfill,postcss.config.js
内配置的autoprefixer
插件能自动为css添加必要的浏览器厂商前缀。它们是怎么确定哪些polyfill还有哪些浏览器厂商前缀是必要添加的呢,毕竟不同公司甚至不同项目所要兼容的浏览器版本不一样。有的项目没有任何兼容需求,那么项目应该少依赖一些polyfill,有些项目要兼容到IE浏览器,那就要添加更多的polyfill和浏览器厂商前缀。所以我们需要配置.browserslistrc
来告诉这些打包工具我们要兼容的浏览器范围。
在项目根目录下创建.browserslistrc
文件:
> 1%
last 2 versions
not ie <= 8
这个配置的大概意思是:市场份额大于1%的浏览器,最新的两个版本,排除IE8以下的浏览器。
配置.editorconfig
有些人喜欢用水平制表符缩进,而有些人喜欢用2个空格。因为使用的操作系统不同,有些人换行符是LF,有些人是CRLF。虽然这些琐碎的东西可以在项目开发初期约定好,并设置到每个开发人员编辑器格式化配置内。但是这样很麻烦。
我们在项目根目录下创建.editorconfig
:
root = true
[*]
indent_style = space
indent_size = 2
end_of_line = lf
insert_final_newline = true
这个配置告诉编辑器,当前项目的缩进用的是2个空格,换行用的是LF,并在每个文件底部插入一行空行。编辑器看到项目内有.editorconfig
文件,就会按它的要求来格式化项目文件。
使用editorconfig的好处是,他能更细粒度的控制每个项目甚至不同文件类型的格式化风格,这样可以让不同的项目拥有不同的格式化风格。
配置完后,编辑器需要在插件市场下载editorconfig插件。webstorm内部默认安装了该插件,所以可以不用下载。
配置ESLint和prettier
ESLint可以校验我们的代码风格和一些语法错误,在团队开发时,可以保证代码风格的一致性并及早发现一些错误。
ESLint很多时候会因为缺少空格或逗号而报错,这些琐碎的错误会很恼人,因此我们可以使用prettier来帮助我们来格式化代码。
安装:
eslint
eslint-loader
babel-eslint
eslint-config-airbnb
eslint-config-prettier
在安装eslint-config-airbnb
时,控制台会有warning,我们需要根据它的warning将所有的peer dependency都安装好。
webpack.common.js
配置:
// ...
module: {
rules: [
{
enforce: "pre",
test: /\.jsx?$/,
include: path.resolve(__dirname, "src"),
use: "eslint-loader"
},
// ...
]
}
// ...
根目录下添加.eslintrc.js
:
module.exports = {
root: true,
parser: "babel-eslint",
env: {
browser: true,
es6: true,
node: true
},
parserOptions: {
ecmaVersion: 6,
sourceType: "module"
},
extends: ["airbnb", "prettier"],
rules: {
"no-console": process.env.NODE_ENV === "production" ? "error" : "off",
"no-debugger": process.env.NODE_ENV === "production" ? "error" : "off"
}
};
在package.json
内添加lint
precommit
两条脚本
// ...
"scripts": {
"start": "cross-env NODE_ENV=development webpack-dev-server --config webpack.dev.js",
"build": "cross-env NODE_ENV=production webpack --config webpack.prod.js",
"lint": "cross-env NODE_ENV=production eslint --ext .jsx --ext .js --fix ./src",
"precommit": "npm run lint"
},
// ...
执行npm run lint
时,ESLint会检查./src
目录下的所有.js
.jsx
结尾的文件,并尽力修复一些问题。ESLint不能修复的问题会打印到控制台上,此时就要手动去修复问题了。
每次git提交代码前会先执行precommit
脚本,该脚本就是让ESLint检查代码,如果检查不通过就无法提交代码。这样可以保证代码仓库内的代码质量。想要precommit
脚本生效,需要安装husky
(哈士奇),而且我们在脚本内使用“cross-env”来修改环境变量,所以得安装cross-env
。
安装:
husky
cross-env
推荐在编辑器内安装ESLint 插件,这样能在书写代码实就能看的ESLint的报错信息。安装ESLint插件后,它可能会在我们不愿意它去检查的文件内报错,所以我们添加.eslintignore
来告诉插件要跳过的检查文件与目录。
.eslintignore配置
node_modules
/dist
webpack.common.js
webpack.prod.js
webpack.dev.js
postcss.config.js
同时推荐安装prettier插件,并配置编辑器在保存时自动格式化。
热更新 (Hot Module Replacement)
使用webpack-dev-server
开发React时,每次文件修改便会自动刷新页面。虽然这和传统的手动刷新页面相比方便了很多,但是在某些情况下还不够方便。就比如开发一个表单模态窗口时,刷新页面会导致模态窗口被关闭,并且表单内填写的信息丢失。
webpack的热更新就能解决这个痛点,它能在界面不刷新的状态下更新界面。
webpack4默认支持热更新,我们只需要开启这个功能就可以。
在webpack.dev.js
内开启热更新:
// ...
devServer: {
hot: true, // 开启热更新
historyApiFallback: true
},
// ...
我们使用react-hot-loader
来支持React的热更新。
安装:
react-hot-loader
在.babelrc
添加react-hot-loader
提供的插件:
{
"presets": ["@babel/preset-env", "@babel/preset-react"],
"plugins": [
["@babel/plugin-proposal-decorators", { "legacy": true }],
["@babel/plugin-proposal-class-properties", { "loose": true }],
"@babel/plugin-syntax-dynamic-import",
"react-hot-loader/babel"
]
}
注意这个插件的写法是react-hot-loader/babel
。
最后,修改App.jsx
内的代码。使用react-hot-loader
提供的高阶组件来装饰我们的App
组件。
import React from "react";
// 导入hot函数
import { hot } from "react-hot-loader/root";
// ...
function App() {
return (
// ...
);
}
// 使用hot函数装饰App组件
export default hot(App);
摇树优化 (Tree Shaking)
webpack4在production
模式下会开启Tree Shaking,但是需要注意以下几点
- 使用ES2015模块语法(例:
import
和export
),被编译成CommonJS规范的模块不能被优化。 - 需要在
package.json
文件内添加"sideEffects"
字段。该字段的值可以是模块名称数组,用来告诉webpack哪些模块是有负作用的。该字段的值也可以是false
,表示所有模块都没有副作用。被标识有副作用的模块不会被Tree Shaking。 - webpack配置内的
mode
设为"production"