阅读 1090

使用webpack4一步步搭建react项目(三)

第二章的配置基本已能达到正常的开发需求了。但是还有很多地方可以进行改善。

第三章 改善项目

使用最新的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模块语法(例:importexport),被编译成CommonJS规范的模块不能被优化。
  • 需要在package.json文件内添加"sideEffects"字段。该字段的值可以是模块名称数组,用来告诉webpack哪些模块是有负作用的。该字段的值也可以是false,表示所有模块都没有副作用。被标识有副作用的模块不会被Tree Shaking。
  • webpack配置内的mode设为"production"

代码

项目代码 Github 仓库

其他章节

文章分类
前端
文章标签