[译] 如何利用 Webpack4 提高你的 React.js 开发效率

如何利用 Webpack4 提高你的 React.js 开发效率

图片来源:www.instagram.com/p/BiaH379hr…javascript

在现实生活的开发中,咱们常常须要对新功能进行快速迭代。在本教程中,我将向你展现一些你能够采起的措施,以提高大约 20% 的开发速度。html

为何要这样,你可能会问?前端

由于在编程时进行人工操做每每会很是拔苗助长,咱们但愿尽量将流程自动化。所以,我将向你展现使用 Webpack v4.6.0 提高 React 的开发过程当中的哪些部分。java

我不会介绍如何初始化配置 webpack,由于我已经在以前的帖子里讲过它。在那篇文章里,我详细介绍了如何配置 Webpack。我假设在阅读本文以前你已经熟悉 Webpack 配置的基础知识,这样咱们就能够从准备好了基本配置以后开始。node

配置 Webpack

在你的 webpack.config.js 文件中,添加如下代码:react

// webpack v4
const path = require('path');
const HtmlWebpackPlugin = require('html-webpack-plugin');
const WebpackMd5Hash = require('webpack-md5-hash');
const CleanWebpackPlugin = require('clean-webpack-plugin');

module.exports = {
  entry: { main: './src/index.js' },
  output: {
    path: path.resolve(__dirname, 'dist'),
    filename: '[name].[chunkhash].js'
  },
  module: {
    rules: [
      {
        test: /\.js$/,
        exclude: /node_modules/,
        use: {
          loader: "babel-loader"
        }
      }
    ]
  },
  plugins: [ 
    new CleanWebpackPlugin('dist', {} ),
    new HtmlWebpackPlugin({
      inject: false,
      hash: true,
      template: './src/index.html',
      filename: 'index.html'
    }),
    new WebpackMd5Hash()
  ]
};
复制代码

并在你的 package.json 文件中添加这些依赖:android

{
 "name": "post",
 "version": "1.0.0",
 "description": "",
 "main": "index.js",
 "scripts": {
  "build": "webpack --mode production",
  "dev": "webpack --mode development"
 },
  "author": "",
 "license": "ISC",
 "devDependencies": {
    "babel-cli": "^6.26.0",
    "babel-core": "^6.26.0",
    "babel-loader": "^7.1.4",
    "babel-preset-env": "^1.6.1",
    "babel-preset-react": "^6.24.1",
    "babel-runtime": "^6.26.0",
    "clean-webpack-plugin": "^0.1.19",
    "html-webpack-plugin": "^3.2.0",
    "react": "^16.3.2",
    "react-dom": "^16.3.2",
    "webpack": "^4.6.0",
    "webpack-cli": "^2.0.13",
    "webpack-md5-hash": "0.0.6"
  }
}
复制代码

接下来你能够安装你的项目所需依赖:webpack

npm i
复制代码

并将 index.htmlindex.js 两个文件添加进项目的 src/ 目录下ios

首先在 src/index.html 文件中添加以下代码:git

<html>
  <head>
  </head>
  <body>
    <div id="app"></div>
    <script src="<%= htmlWebpackPlugin.files.chunks.main.entry %>"></script>
  </body>
</html>
复制代码

接着在 src/index.js 中添加:

console.log("hello, world");
复制代码

执行 dev 脚本:

npm run dev
复制代码

接下来你就会发现:项目完成编译了!如今让咱们继续为它配置 React。

配置 React 项目

因为 React 使用了名为 JSX 的特殊语法,咱们须要转换代码。若是咱们去 babel 的官网,就能够看到它为咱们提供了 React 的 preset.

npm install --save-dev babel-cli babel-preset-react
复制代码

咱们的 .babelrc 文件应该长这样:

{
  "presets": ["env", "react"]
}
复制代码

在你的 index.js 文件中添加一些项目的初始化代码:

import React from 'react';
import { render } from 'react-dom';

class App extends React.Component {

render() {
    return (
      <div>
        'Hello world!'
      </div>
    );
  }
}

render(<App />, document.getElementById('app'));
复制代码

接着执行 dev 脚本:

npm run dev
复制代码

若是在你的 ./dist 目录下可以看到一个 index.html 文件和一个带有 hash 值的 main.js 文件,那么说明你作得很棒!项目完成了编译!

配置 web-dev-server

严格来讲,咱们并非必需要使用它,由于社区里有不少为前端服务的 node.js 服务端程序。但我之因此建议使用 webpack-dev-server 由于本就是为 Webpack 而设计的,它支持一些很好的功能,如热模块替换、**Source Maps(源文件映射)**等。

正如他们在官方文档中提到的那样:

使用 webpack 和后端开发服务配合可以实现 live reloading(热重启),但这只应当被用于开发环境下。

这可能会让人感到有些困惑:怎样使 webpack-dev-server 仅在开发模式下生效?

npm i webpack-dev-server --save-dev
复制代码

在你的 package.json 文件中,调整:

"scripts": {
  "dev": "webpack-dev-server --mode development --open",
  "build": "webpack --mode production"
}
复制代码

如今它应该可以启动一个本地服务器并使用你的应用程序自动打开浏览器选项卡。

你的 package.json 如今看起来应该像这样:

{
 “name”: “post”,
 “version”: “1.0.0”,
 “description”: “”,
 “main”: “index.js”,
 “scripts”: {
   "dev": "webpack-dev-server --mode development --open",
   "build": "webpack --mode production"
 },
 “author”: “”,
 “license”: “ISC”,
 “devDependencies”: {
   “babel-cli”: “6.26.0”,
   “babel-core”: “6.26.0”,
   “babel-loader”: “7.1.4”,
   “babel-preset-env”: “1.6.1”,
   “babel-preset-react”: “6.24.1”,
   “babel-runtime”: “6.26.0”,
   “clean-webpack-plugin”: “0.1.19”,
   “html-webpack-plugin”: “3.2.0”,
   “react”: “16.3.2”,
   “react-dom”: “16.3.2”,
   “webpack”: “4.6.0”,
   “webpack-cli”: “2.0.13”,
   “webpack-dev-server”: “3.1.3”,
   “webpack-md5-hash”: “0.0.6”
 }
}
复制代码

如今,若是你尝试修改应用中的某些代码,浏览器就会自动刷新页面。

接下来,你须要将 React devtools 添加到 Chrome 扩展程序。

这样,你就能够更轻松地使用 Chrome 控制台调试应用。

ESLint 配置

咱们为何须要它?好吧,一般来说咱们不是必须使用它,但 ESLint 是一个方便的工具。在咱们的例子中,它将呈现并突出显示(在编辑器和终端中以及在浏览器上)咱们代码中的错误,包括拼写错误等等(若是有的话),这称为 linting

ESLint 是一个开源的 JavaScript linting 实用程序,最初由 Nicholas C. Zakas 于 2013 年 6 月开发完成。它有其替代品,但到目前为止,它与 ES6 和 React 配合使用效果特别好,可以发现常见问题,并能与项目的生态系统其余部分集成。

如今,让咱们在本地为咱们本身的新项目安装它。固然,此时 ESLint 会有不少设置。你能够在官方网站阅读更多相关信息。

npm install eslint --save-dev

./node_modules/.bin/eslint --init
复制代码

最后一个命令将建立一个配置文件。系统将提示你选择如下三个选项:

在本教程中,我选择了第一个:回答问题。如下是个人答案:

这会将一个 .eslintrc.js 文件添加到项目目录中。我生成的文件以下所示:

module.exports = {
    "env": {
        "browser": true,
        "commonjs": true,
        "es6": true
    },
    "extends": "eslint:recommended",
    "parserOptions": {
        "ecmaFeatures": {
            "experimentalObjectRestSpread": true,
            "jsx": true
        },
        "sourceType": "module"
    },
    "plugins": [
        "react"
    ],
    "rules": {
        "indent": [
            "error",
            4
        ],
        "linebreak-style": [
            "error",
            "unix"
        ],
        "quotes": [
            "error",
            "single"
        ],
        "semi": [
            "error",
            "always"
        ]
    }
};
复制代码

到目前为止什么都没发生。虽然这是一个彻底有效的配置,但这还不够,咱们必须将它与 Webpack 和咱们的文本编辑器集成才能工做。正如我所提到的,咱们能够在代码编辑器、终端(做为 linter)或 git 的 precommit 钩子中使用它。咱们如今将为咱们的编辑器配置它:

Visual Studio Code 中安装

若是你想要,几乎每一个经常使用的代码编辑器都有 ESLint 插件,包括 Visual Studio Code、Visual Studio、SublimeText、Atom、WebStorm 甚至是 vim。因此,下载你本身的文本编辑器的对应版本。在本次示例中我会使用 VS Code

如今咱们能够看到出现了一些代码错误提示。这是由于项目有一个 Lint 配置文件,它会在没有遵照某些规则时标记代码并提示警告。

你能够经过检查错误消息手动调试它,或者你可使用它只需执行保存便自动修复问题的功能。

你如今也能够调整 ESLint 设置:

module.exports = {
    "env": {
        "browser": true,
        "commonjs": true,
        "es6": true
    },
    "extends": ["eslint:recommended", "plugin:react/recommended"],
    "parserOptions": {
        "ecmaFeatures": {
            "experimentalObjectRestSpread": true,
            "jsx": true
        },
        "sourceType": "module"
    },
    "plugins": [
        "react"
    ],
    "rules": {
        "indent": [
            "error",
            2
        ],
        "linebreak-style": [
            "error",
            "unix"
        ],
        "quotes": [
            "warn",
            "single"
        ],
        "semi": [
            "error",
            "always"
        ]
    }
};
复制代码

更改了配置以后,若是你错误地使用了双引号而不是单引号,ESLint 不会中断构建。它还将为 JSX 添加一些检查。

添加 Prettier

Prettier 是当今最流行的格式化程序之一,它已被编码社区普遍使用。它能够添加到 ESLint、你的编辑器,也能够被挂载在 git 的 pre-commit 钩子上。

我会在这里将它安装到个人 VS Code 中

安装后,你能够尝试再次检查代码。若是咱们写一些奇怪的缩进并执行保存,它应该会自动格式化代码。

但这还不够。为了使其与 ESLint 同步工做而且不会两次发出相同的错误,甚至发生规则冲突,你须要将它与 ESLint 集成

npm i --save-dev prettier eslint-plugin-prettier
复制代码

在官方文档中,他们建议你使用 yarn,但 npm 如今一样也能安装。在你的 .eslintrc.json 文件中添加:

...
  sourceType: "module"
},
plugins: ["react", "prettier"],
extends: ["eslint:recommended", "plugin:react/recommended"],
rules: {
  indent: ["error", 2],
  "linebreak-style": ["error", "unix"],
  quotes: ["warn", "single"],
  semi: ["error", "always"],
  "prettier/prettier": "error"
}
...
复制代码

如今咱们想扩展咱们的 ESLint 规则以包含 prettier 的规则:

npm i --save-dev eslint-config-prettier
复制代码

并为你的 eslint 配置添加一些 extends:

...
extends: [
  "eslint:recommended",
  "plugin:react/recommended",
  "prettier",
  "plugin:prettier/recommended"
]
...
复制代码

让咱们为它添加更多配置。为了不默认的 Prettier 规则和你的 ESLint 规则之间的不匹配,你应该像我如今这样作:

Prettier 借用了 ESLint 的 override 格式,这容许你将配置应用于特定的文件。

你如今能够以 .js 文件的形式为其建立配置文件。

nano prettier.config.js
复制代码

如今,粘贴到该文件中:

module.exports = {
  printWidth: 80,
  tabWidth: 2,
  semi: true,
  singleQuote: true,
  bracketSpacing: true
};
复制代码

如今,当你执行保存时,你会看到代码自动格式化。那不是很漂亮(prettier)吗?双关语颇有意思。

个人 package.json 文件如今看起来是这样:

{
 "name": "post",
 "version": "1.0.0",
 "description": "",
 "main": "index.js",
 "scripts": {
  "build": "webpack --mode production",
  "dev": "webpack-dev-server --mode development --open"
 },
 "author": "",
 "license": "ISC",
 "devDependencies": {
  "babel-cli": "^6.26.0",
  "babel-core": "^6.26.0",
  "babel-loader": "^7.1.4",
  "babel-preset-env": "^1.6.1",
  "babel-preset-react": "^6.24.1",
  "babel-runtime": "^6.26.0",
  "clean-webpack-plugin": "^0.1.19",
  "eslint": "^4.19.1",
  "eslint-config-prettier": "^2.9.0",
  "eslint-plugin-prettier": "^2.6.0",
  "eslint-plugin-react": "^7.7.0",
  "html-webpack-plugin": "^3.2.0",
  "prettier": "^1.12.1",
  "react": "^16.3.2",
  "react-dom": "^16.3.2",
  "webpack": "^4.6.0",
  "webpack-cli": "^2.0.13",
  "webpack-dev-server": "^3.1.4",
  "webpack-md5-hash": "0.0.6"
 }
}
复制代码

如今咱们已经完成了不少工做,让咱们快速回顾一下:ESLint 会监视代码中的错误,而 Prettier 是一种样式格式化工具。ESLint 有许多方法能够捕获错误,而 Prettier 能够很好地格式化你的代码。

// webpack v4
const path = require('path');
const HtmlWebpackPlugin = require('html-webpack-plugin');
const WebpackMd5Hash = require('webpack-md5-hash');
const CleanWebpackPlugin = require('clean-webpack-plugin');
module.exports = {
  entry: { main: './src/index.js' },
  output: {
    path: path.resolve(__dirname, 'dist'),
    filename: '[name].[chunkhash].js'
  },
  module: {
    rules: [
      {
        test: /\.js$/,
        exclude: /node_modules/,
        use: {
          loader: "babel-loader"
        }
      }
    ]
  },
  plugins: [ 
    new CleanWebpackPlugin('dist', {} ),
    new HtmlWebpackPlugin({
      inject: false,
      hash: true,
      template: './src/index.html',
      filename: 'index.html'
    }),
    new WebpackMd5Hash()
  ]
};
复制代码

问题:Prettier 不会自动格式化 Visual Studio Code 中的代码

有些人指出 VS Code 没法使用 Prettier。

若是你的 Prettier 插件在保存时没有自动格式化代码,你能够经过将下面的代码添加到 VS Code 设置来修复它:

"[javascript]": {
    "editor.formatOnSave": true
  }
复制代码

问题描述在这里

添加 ESLint loader 到你的 pipeline 中

因为 ESLint 是在项目中配置的,所以一旦运行 dev 服务器,它也会在终端中提示警告。

特别提示:尽管能够这样作,但此时我不建议将 ESLint 用做 Webpack 的 loader。它将破坏 source map 的生成,我在个人前一篇文章《如何解决 Webpack 中的问题 —— 一些实际案例》中有更详细的描述。我将展现如何在这里设置它,以防这些人已经修复了他们的错误。

Webpack 有它本身的 ESLint loader.

npm install eslint-loader --save-dev
复制代码

你必须将 ESLint 添加到 rules 配置中。当使用了使用了编译类的 loader(如 babel-loader)时,请确保它们的执行顺序正确(从下到上)。不然,Webpack 将检查文件通过 babel-loader 编译后的文件。

...
module: {
  rules: [
    {
      test: /\.js$/,
      exclude: /node_modules/,
      use: [{ loader: "babel-loader" }, { loader: "eslint-loader" }]
    }
  ]
},
...
复制代码

如下是你可能遇到的一些问题:

  • 将未使用的变量添加到 index 文件中

若是你偶然发现了这个错误(no-unused-vars),那么在 GitHub 和这里这个 issue 中很好地解释了这个错误。

咱们能够经过添加一些规则来解决这个问题,这里这里都有解答。

你可能已经注意到,这里会出现 no-unused-vars 错误,你须要将其设为警告而不是错误,由于这样能够更轻松地进行快速开发。你须要向 ESLint 添加新规则,以便不会收到默认错误。

你能够在此处此处更详细地了解这个配置。

...
semi: ['error', 'always'],
'no-unused-vars': [
  'warn',
  { vars: 'all', args: 'none', ignoreRestSiblings: false }
],
'prettier/prettier': 'error'
}
...
复制代码

这样咱们就会获得漂亮的错误和警告信息。

我喜欢使用自动修复功能,但咱们必须明确一点:我并非特别想让事情神奇地改变。为了不这种状况,咱们如今能够提交 autofix。

Pre commit 钩子

在使用 Git 工具时,人们都会很是当心。但我向你保证,这个东西很是简单并且直截了当。挂载了 Prettier 的 Pre commit 钩子以后,团队在每一个项目文件中将有一致的代码风格,而且没有人能够提交不规范的代码。要为你的项目设置 Git 集成,以下所示:

git init
git add .
nano .gitignore (add your node_modules there)
git commit -m "First commit"
git remote add origin your origin
git push -u origin master
复制代码

这里有一些关于 git 钩子使用 Prettier 的精彩文章。

对于那些说你只能在本地作这些操做的人说:不,那不是真的!

你可使用 Andrey Okonetchnikov 开源的 lint-staged 工具执行此操做。

添加 propTypes

让咱们在咱们的应用程序中建立一个新组件。到目前为止,咱们的 index.js 看起来像这样:

import React from 'react';
import { render } from 'react-dom';

class App extends React.Component {
  render() {
    return <div>Hello</div>;
  }
}
render(<App />, document.getElementById('app'));
复制代码

咱们将建立一个名为 Hello.js 的新组件用于演示。

import React from 'react';
class Hello extends React.Component {
  render() {
    return <div>{this.props.hello}</div>;
  }
}
export default Hello;
复制代码

如今在 index.js 文件中引入:

import React from 'react';
import { render } from 'react-dom';
import Hello from './Hello';
class App extends React.Component {
  render() {
    return (
      <div>
      <Hello hello={'Hello, world! And the people of the world!'} />
     </div>
   );
  }
}
render(<App />, document.getElementById('app'));
复制代码

咱们应该看到这个元素,但 ESLint 提示警告:

Error: [eslint] ‘hello’ is missing in props validation (react/prop-types)

在 React v16 中,必须添加 prop 类型以免类型混淆。你能够在这里阅读更多相关信息。

import React from 'react';
import PropTypes from 'prop-types';
class Hello extends React.Component {
  render() {
    return <div>{this.props.hello}</div>;
  }
}
Hello.propTypes = {
  hello: PropTypes.string
};
export default Hello;
复制代码

热模块替换

如今你已经检查了代码,如今是时候向 React 应用添加更多组件了。到目前为止,你只有两个,但在大多数状况下,你会有几十个。

固然,每次更改项目中的某些内容时,从新编译整个应用程序都不是一种好的选择,你须要一种更快的方法来优化它。

因此让咱们添加热模块替换,即 HMR。在文档中,它被描述为:

热模块更换(HMR)在应用程序运行时变动、添加或删除模块无需彻底从新加载。能够经过如下几种方式显著提高开发速度:

保留在彻底从新加载期间丢失的应用程序状态。

只更新已变动的内容,便可节省宝贵的开发时间。

更快地调整样式 —— 几乎能够与在浏览器控制台中进行样式更改相媲美。

我不会在这里讨论它的工做原理:这足够写成一篇单独的文章,但我会告诉你该如何配置它:

...
output: {
  path: path.resolve(__dirname, 'dist'),
  filename: '[name].[chunkhash].js'
},
devServer: {
  contentBase: './dist',
  hot: true
},
module: {
  rules: [
...
复制代码

解决 HMR 的小问题

咱们必须使用 hash 来替换 chunkhash,由于很明显 webpack 已经修复了自上次以来的问题,如今咱们终于让热模块替换开始正常工做了!

...
module.exports = {
   entry: { main: './src/index.js' },
   output: {
     path: path.resolve(__dirname, 'dist'),
     filename: '[name].[hash].js'
   },
   devServer: {
     contentBase: './dist',
...
复制代码

解决 bugs

若是咱们在这里运行 dev 脚本:

而后使用这个 issue 提到的方案来解决它:

接下来,在 package.json 中添加 --hot 参数到 dev 脚本中:

...
"scripts": {
   "build": "webpack --mode production",
   "dev": "webpack-dev-server --hot"
}
...
复制代码

Source maps:

我以前提到过,source maps 不能和 ESLint loader 一块儿使用,我在这里提了一个 issue。

一般,你不管如何都不但愿它们出如今你的项目中(由于你想从 ESLint 错误消息中调试项目),总所周知,他们会使 HMR 变慢。

你能够在这里这里阅读更多。

若是你但愿生成 source maps,最简单的方法就是经过 devtools 选项。

...
module.exports = {
  entry: { main: './src/index.js' },
  output: {
    path: path.resolve(__dirname, 'dist'),
    filename: '[name].[hash].js'
  },
  devtool: 'inline-source-map',
  devServer: {
    contentBase: './dist',
    hot: true
  },
  ...
复制代码

注意:你必须以正确的方式配置环境,不然 source maps 将不起做用。你能够在这里阅读个人调试过程。下面我将为你梳理一个流程并解释我如何解决该问题。

若是咱们如今在代码中建立一个错误,它将显示在控制台中并指向正确的位置:

但现实好像不太尽人意…

这是错误的作法

你须要更改环境变量,以下所示:

...
"main": "index.js",
"scripts": {
  "build": "webpack --mode=production",
  "start": "NODE_ENV=development webpack-dev-server --mode=development --hot"
},
"author": ""
...
复制代码

webpack.config.js

...
devtool: 'inline-source-map',
devServer: {
  contentBase: './dist',
  open: true
}
...
复制代码

如今它就有效了!

如你所见,咱们获得了发生错误的确切文件!

如今项目的开发环境已经搭建成功!

让咱们回顾一下:

  • 咱们配置了 webpack
  • 咱们建立了第一个 React 组件
  • 咱们引入 ESLint 来检查代码是否存在错误
  • 咱们配置了热模块替换
  • 咱们(可能)添加了 source maps 功能

特别提醒:因为许多 npm 依赖项可能会在你阅读此内容时发生更改,所以相同的配置可能对你无效。我恳请你将错误留在下面的评论中,以便我之后编辑。

若是发现译文存在错误或其余须要改进的地方,欢迎到 掘金翻译计划 对译文进行修改并 PR,也可得到相应奖励积分。文章开头的 本文永久连接 即为本文在 GitHub 上的 MarkDown 连接。


掘金翻译计划 是一个翻译优质互联网技术文章的社区,文章来源为 掘金 上的英文分享文章。内容覆盖 AndroidiOS前端后端区块链产品设计人工智能等领域,想要查看更多优质译文请持续关注 掘金翻译计划官方微博知乎专栏

相关文章
相关标签/搜索