Webpack5搭建React开发环境 | 蛋烘糕
蛋烘糕.

不写博客的工程师不是好的搬砖工🧱

Webpack5搭建React开发环境

Cover Image for Webpack5搭建React开发环境
蛋烘糕
蛋烘糕

平常业务开发过程中习惯使用脚手架来搭建开发环境,create-react-app、vue-cli 等等,各个框架都提供了快速上手的脚手架。这样保证了快速开发的效率,不过阻碍了我们熟悉了解 webpack、rollup 这类构建工具的生态和原理。

1 当前主要依赖包版本

webpack@5.16.0
webpack-cli@4.4.0
webpack-dev-server@
react@
babel-core@
babel-preset-env@
baele-preset-react@

2 webpack 安装和配置

2.1 起步

新建项目目录,初始化 npm 环境,创建项目代码目录

mkdir react-project && cd react-project
yarn init -y
mkdir src

2.2 安装 webpack

  • webpack: 模块打包库
  • webpack-cli: webpack 命令行工具
yarn add webpack webpack-cli -D

3 Webpack 基础配置

在项目根目录下创建一个 webpack.config.js

3.1 Entry

配置入口文件,webpack 会首先从入口文件开始编译代码

// webpack.config.js
const path = require("path");

module.exports = {
  entry: {
    app: "./src/index.js",
  },
};

此时在 src 目录下创建一个 index.js 文件

// index.js
const a = 123;

console.log(a);

3.2 Output

定义打包后文件输出位置和文件名。[name]是一个占位符,这里是根据 entry 中定义的 key 值,即'app'。

// webpack.config.js
module.exports = {
  output: {
    path: path.resolve(__dirname, "./dist"),
    filename: "[name].bundle.js",
  },
};

现在可以使用最小化的配置完成打包了。在 package.json 中添加如下代码:


"scripts": {
  "build": "webpack"
}

运行命令

yarn build

可以在命令行中看到打包运行,并且在项目目录下生成了一个 dist 文件夹,并且生成一个 app.bundle.js 文件,说明打包成功。 打开 app.bundle.js 文件,可以看到内容为:

// app.bundle.js
console.log(123);

4 Plugin

插件让 webpack 具备可扩展性,可以让 webpack 运行过程中支持更多的功能。

4.1 模板文件

构建一个 web 应用,需要一个 html 入口文件,然后 html 引入对应的 js 和 css 文件。并且往往配置打包出来的 bundle 文件名称为了防止缓存问题是带有 hash 值的,如果每次手动修改会比较麻烦,所以最好的方法是自动将 bundle 文件打包到 html 中。 此时我们用到 html-webpack-plugin 这个插件,这个插件的作用是从模板生成一个 html 文件。

  1. 安装
yarn add html-webpack-plugin -D
  1. 创建 index.html 在项目根目录下创建一个 public/index.html 文件,内容如下:
<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <meta http-equiv="X-UA-Compatible" content="IE=edge" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title><%= htmlWebpackPlugin.options.title %></title>
  </head>
  <body>
    <div id="root"></div>
  </body>
</html>

其中 title 是读取 html-webpack-plugin 插件的配置,具体配置如下:

// webpack.config.js
const path = require("path");
const HtmlWebpackPlugin = require("html-webpack-plugin");

module.exports = {
  /*...*/
  plugins: [
    new HtmlWebpackPlugin({
      title: "蛋烘糕的学习笔记",
      template: path.resolve(__dirname, "./public/index.html"),
      filename: "index.html",
    }),
  ],
};

现在再次运行yarn build,就可以看到 dist 目录下面多出了一个 index.html 文件,并且其中自动插入了标题和 js 代码引用。

<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <meta http-equiv="X-UA-Compatible" content="IE=edge" />
    <meta name="viewport" content="width=device-width,initial-scale=1" />
    <title>蛋烘糕的学习笔记</title>
  </head>

  <body>
    <script src="app.bundle.js"></script>
  </body>
</html>

4.2 打包前清除 dist

clean-webpack-plugin 打包前移除、清理打包目录

  1. 安装
yarn  add yarn add clean-webpack-plugin -D
  1. 配置
const path = require("path");
const { CleanWebpackPlugin } = require("clean-webpack-plugin");

module.exports = {
  /* ... */

  plugins: [
    /* ... */
    new CleanWebpackPlugin(),
  ],
};

4.3 命令行友好提示插件

  1. 安装
yarn add friendly-errors-webpack-plugin -D
  1. 配置
// webpack.config.js
const friendlyErrorsWebpackPlugin = require("friendly-errors-webpack-plugin");

module.exports = {
  plugins: [new friendlyErrorsWebpackPlugin()],
};

5 Loaders

webpack 使用 loaders 去解析模块,想要 webpack 如何理解 JavaScript、静态资源(图片、字体、CSS)、转义 TypeScrip 和 Babel,都需要配置响应的 loader 规则。

在项目中只有一个 HTML 和一些 JavaScript 是不能完成整个项目的,我们需要 webpack 能够帮我们完成更多的事:

  • 将最新的 JavaScript 特性编译成浏览器能理解的代码;
  • 模块化 CSS,将 SCSS、LESS、CSSNext 编译成 CSS;
  • 导入图片、字体等静态资源
  • 识别自己喜欢的框架代码,如 React

5.1 Babel

Babel 是一个 JavaScript 编译器,能将 ES6+ 代码转为 ES5 代发,让我们使用最新的语言特性而不用担心兼容性问题,并且可以通过插件机制根据需求灵活扩展。

  1. 安装依赖
yarn add babel-loader @babel/core @babel/preset-env -D
  • babel-loader 使用 Babel 和 Webpack 转义文件
  • @balel/core 转译 ES2015+ 的代码
  • @babel/preset-env Babel 环境预设配置
  1. 配置
// webpack.config.js
module.exports = {
 /* ... */

 module: {
  rules: [
   // JavaScript
   {
    test: /\.m?js$/,
    exclude: /node_modules/,
    use: {
     loader: 'babel-loader',
     options: {
      presets: ['@babel/preset-env'],
     },
    },
   },
  ],
 },
}

在 Babel 执行编译的过程中,会从项目根目录下的配置文件读取配置。在根目录下创建 Babel 的配置文件 .babelrc

{
  "presets": ["@babel/preset-env"]
}

5.2 图片和字体解析

  1. 解析图片的 loader 配置
module.exports = {
 /* ... */
 module: {
  rules: [
   // Images
   {
    test: /\.(?:ico|gif|png|jpg|jpeg)$/i,
    type: 'asset/resource',
   },
  ],
 },
}
  1. 解析字体文件的 loader 配置
module.exports = {
 /* ... */
 module: {
  rules: [
   // Fonts and SVGs
   {
    test: /\.(woff(2)?|eot|ttf|otf|svg|)$/,
    type: 'asset/inline',
   },
  ],
 },
}

5.3 样式

我们希望能够在 JavaScript 中导入 CSS,以及将 CSS 注入 DOM,另外还想使用 CSS 的高级特性,比如 cssnext,需要依赖一下库:

  • css-loader 解析 CSS 导入
  • style-loader 将 CSS 注入 DOM
  • postcss PostCSS 是一个允许使用 JS 插件转换样式的工具。 这些插件可以检查(lint)你的 CSS,支持 CSS Variables 和 Mixins, 编译尚未被浏览器广泛支持的先进的 CSS 语法,内联图片,以及其它很多优秀的功能。
  • postcss-loader 用 PostCSS 处理 CSS
    • postcss-preset-env PostCSS 的默认配置
  • postcss-next - PostCSS 的插件,可以使用 CSS 最新的语法
  1. 安装
yarn add css-loader style-loader postcss-loader postcss-preset-env postcss postcss-cssnext -D
  1. 配置
// webpack.config.js

module.exports = {
 /* ... */
 module: {
  rules: [
   // CSS, PostCSS, and Sass
   {
    test: /\.(scss|css)$/,
    use: ['style-loader', {
      loader: 'css-loader',
      options: {
       importLoaders: 1,
      },
     }, 'postcss-loader'],
   },
  ],
 },
}
  1. postcss 配置 在项目根目录下新建 postcss.config.js 文件,内容如下:
module.exports = {
  plugins: {
    'postcss-preset-env': {
      browsers: 'last 2 versions',
    },
  },
}

6 搭建开发环境

现在我们来搭建开发模式的配置:

// webpack.config.js

module.exports = {
 mode: 'development',
 // ...
}

6.1 使用 source maps

为了在报错的时候更好地追踪报错的代码位置,并且给出错误代码出现的地方提示,我们可以使用 source map,具体配置如下:

// webpack.config.js

module.exports = {
 devtool: 'inline-source-map'
 // ...
}

6.2 热模块替换 HMR(Hot Module Replacement)

当我们代码改动的时候,我们希望能够重新编译,webpack 提供了三种不同的方式实现:

  • 监听模式
  • webpack-dev-server
  • webpack-dev-middleware

大多数情况下,使用的是 webpack-dev-server,当前我们也是用这个工具。顺带介绍一下其他两种方式。

6.2.1 监听模式

// package.json
{
 "watch": "webpack --watch"
}

执行以下命令

yarn run watch

现在当我们保存代码的时候会自动编译代码,刷新浏览器后即可看到效果;但是我们想要自动刷新浏览器怎么办,这时候就需要用到 webpack-dev-server。

6.2.2 webpack-dev-server

它为我们提供了一个服务器和 live reloading 的能力。

yarn add webpack-dev-server -D

然后配置如下:

// webpack.config.js
module.exports = {
 // ...
 devServer: {
  historyApiFallback: true,
  contentBase: path.join(__dirname, './dist'),
  open: false,
  hot: true,
  quiet: true,
  port: 8080,
 },
}
// package.json
{
  "scripts": {
    "start": "webpack serve"
  }
}

我们再 8080 端口监听了一个服务,监听的目录是 dist,并且支持热重载,现在打开 http://localhost:8080,可以看到我们的页面,然后改动代码,浏览器会自动刷新到最新的效果。

6.2.3 webpack-dev-middleware

这是一个 webpack 的中间件,可以让 webpack 把文件交给一个服务器处理,比如我们可以使用 nodejs 的服务器 express,这个了我们更多对于运行的服务器的控制权。

  1. 安装 express 和 webpack-dev-middleware
yarn add express webpack-dev-middleware -D

更改配置

module.exports = {
 //...
 output: {
  //...
  publicPath: '/'
 }
}

publicPath 可以定义 express 监听服务的路径,接下来就创建我们的 express 服务器

新建一个 server.js

const express = require('express');
const webpack = require('webpack');
const webpackDevMiddleware = require('webpack-dev-middleware');

const app = express();
const config = require('./webpack.config.js');
const compiler = webpack(config);

// Tell express to use the webpack-dev-middleware and use the webpack.config.js
// configuration file as a base.
app.use(
 webpackDevMiddleware(compiler, {
  publicPath: config.output.publicPath,
 })
);

// Serve the files on port 3000.
app.listen(3000, function () {
 console.log('Example app listening on port 3000!\n');
});

监听端口为 3000,执行以下命令启动服务

node server.js

方便起见,可以将该命令加入 package.json

{
  //...
  "scripts": {
    "server": "node server.js"
  }
}

7 使用 TypeScript

现在前端不会使用 TypeScript 貌似已经没有竞争力了。🤦‍

安装依赖

yarn add typescript ts-loader -D

在根目录下创建 typescript 的配置文件 tsconfig.json,具体配置如下:

{
  "compilerOptions": {
    "outDir": "./dist/",
    // "rootDir": "./src",
    "sourceMap": true, // 开启sourcemap
    "module": "commonjs",
    "target": "es5",
    "jsx": "react",
    "esModuleInterop": true,
    "allowJs": true,
    "strict": true
  }
}

添加对应代码解析 loader

// webpack.config.js
module.exports = {
 //...
 module: {
  rules: [
    {
    test: /\.tsx?$/,
    use: 'ts-loader',
    exclude: /node_modules/,
   },
  ]
 }
}

8 配置 React

在上面配置 typescript 配置中中,已经开启了支持 react,现在只需安装 react 的依赖即可

yarn add react react-dom @types/react @types/react-dom

将入口 index.js 文件名称改为 index.tsx,内容如下:

import React from 'react';
import ReactDOM from 'react-dom';

import './index.css';

const App = () => {
 return <div>hello world2</div>;
};

ReactDOM.render(<App />, document.getElementById('root'));

9 代码规范

一个中大型项目肯定涉及到团队协作,规范的代码能够大幅提高团队合作的效率。我们需要在一开始搭建项目的时候就需要对于代码规范进行约定,这里我们需要用到两个工具。

9.1 Prettier

Prettier 是一个诞生于 2016 年就迅速流行起来的专注于代码格式化的工具。

Prettier 只关注格式化,并不具有 lint 检查语法等能力。它通过解析代码并匹配自己的一套规则,来强制执行一致的代码展示格式。

它在美化代码方面有很大的优势,配合 ESLint 可以对 ESLint 格式化基础上做一个很好的补充。

  1. 使用 以 VSCode 为例,安装 Prettier 插件即可使用,如果想自定义配置,可以 cmd+,快捷键进入 vscode 配置,搜索 Prettier 找到对应的配置项进行配置。

9.2 ESlint

ELint 是一个在 JavaScript 代码中通过规则模式匹配作代码识别和报告的插件化的检测工具,它的目的是保证代码规范的一致性和及时发现代码问题、提前避免错误发生。

ESLint 的关注点是代码质量,检查代码风格并且会提示不符合风格规范的代码。除此之外 ESLint 也具有一部分代码格式化的功能。

安装依赖,方便起见,直接使用已有的 ESlint 配置,这里使用的是 fabric

yarn add @umijs/fabric -D

在项目根目录下创建 .eslintrc.js,配置如下

module.exports = {
  extends: [require.resolve("@umijs/fabric/dist/eslint")],
  globals: {},
  plugins: ["react-hooks"],
  rules: {
    "no-restricted-syntax": 0,
    "no-param-reassign": 0,
    "no-unused-expressions": 0,
  },
};

重新启动编辑器,即可看到 ESLint 已经可以检查代码的准确性了。

10 总结

到目前为止,我们已经搭建了一个简单的 react 脚手架,并且支持 TypeScript、CSSnext、HMR 等特性,对于一个小项目已经足够用了。后期对于用到的其他内容可以自己扩展上去。

React 17来了
Vue3.0核心源码解读 | 一文看懂Vue3.0的优化
博客日历
2022年10月
26
27
28
29
30
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
01
02
03
04
05
06
更多