第二章的配置基本已能达到正常的开发需求了。但是还有很多地方可以进行改善。
第三章 改善项目
使用最新的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 versionsnot ie <= 8复制代码
这个配置的大概意思是:市场份额大于1%的浏览器,最新的两个版本,排除IE8以下的浏览器。
配置.editorconfig
有些人喜欢用水平制表符缩进,而有些人喜欢用2个空格。因为使用的操作系统不同,有些人换行符是LF,有些人是CRLF。虽然这些琐碎的东西可以在项目开发初期约定好,并设置到每个开发人员编辑器格式化配置内。但是这样很麻烦。
我们在项目根目录下创建.editorconfig
:
root = true[*]indent_style = spaceindent_size = 2end_of_line = lfinsert_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/distwebpack.common.jswebpack.prod.jswebpack.dev.jspostcss.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"