版本要求

node版本需要18及以上,否则下载最新的webpack一些包,运行起来会出问题

npm版本一般都是跟随node

建议

最好是可以利用nvm来对你电脑的node版本进行管理

如何查看版本

  1. 调出来你的cmd工具

    按键:Win+R

  2. 查看node版本

    1
    node -v

    image-20240517160158000

    得到版本为V 18.18.2

  3. 查看npm版本

    1
    npm -v

    image-20240517160244635

    得到版本为V 9.8.1

注意

本章节前置知识点、优化点大部分均在[Webapck创建Vue3项目](https://wutiaowu5t5.github.io/posts/54d94922/)这里


一、新建项目

新建一个项目,并在编辑器里面打开,这里用的是Webstorm,项目名字是WebpackCreateReact


二、初始化项目

打开终端, 运行下面这段命令,会给我们的项目初始化,生成一个package.json文件

1
npm init -y

image-20240527163346809


三、搭建项目

这一步将要实现目标就是:

  1. webpack区分打包环境
  2. 给项目添加React
  3. 给项目添加css预处理器
  4. 把项目跑起来

3.1-Webpack基础包

执行下面这段命令,我们就可以启动webpack项目了,这些包在使用Webpack进行项目构建时常用到的

1
npm install webpack-dev-server webpack webpack-cli webpack-merge --save-dev

这时候我们看到到项目里面多出来了一个目录node_modules,一个文件package-lock.jsonpackage.json里面多出来了一个devDependencies

3.2-配置文件

项目内创建webpackConfig目录,用来保存和webpack相关的配置文件,和项目文件分离出来

image-20240517172236108

webpack.common.js公共配置文件

配置模块解析规则 resolve
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
/**
* 引入Node.js的path模块
* 该模块提供了一系列处理文件路径的函数。
*/
const path = require('path')


module.exports = {
// 配置模块解析规则
resolve: {
// 后缀名自动补全,当引入模块时,可以不写具体的后缀名,这里指定了可用的后缀名列表
extensions: [
'.js', '.ts', '.json', '.tsx', '.css', '.less'
],
// 配置别名,方便在import时使用简写,提高编码效率
alias: {
// 使用'@'作为简写,指向项目的src目录
'@': path.resolve(__dirname, '../src'),
// 'cmp'别名指向组件目录,方便直接引入组件
'cmp': path.resolve(__dirname, '../src/components'),
// 'api'别名指向API接口目录,便于调用接口
'api': path.resolve(__dirname, '../src/api')
}
},
}


配置入口文件entry
1
2
3
4
5
6
module.exports = {
... other code ...
// 配置入口文件
entry: path.resolve(__dirname, '../src/main.tsx'),
... other code ...
}


配置输出选项output
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
module.exports = {
... other code ...
// 配置输出选项
output: {
// 指定输出的文件名,[chunkhash:8]表示使用8位的块哈希值作为文件名的一部分
filename: '[name].[chunkhash:8].js',
// 指定输出文件的路径
path: path.resolve(__dirname, '../dist'),
// 启用异步块加载
asyncChunks: true,
// 设置资源的公共路径,对于在页面中引用的静态资源,都将以此路径为基础
publicPath: '/',
// 清除上一次打包构建出来的文件
clean: true
},
... other code ...
}

在Webpack配置中,output 属性告诉Webpack如何写出它所创建的bundles(打包后的文件),以及在哪里写出它们

这个属性定义了打包过程生成的文件的输出方式和位置

它的配置对于确定你打包后的资源如何分发和使用至关重要


定义模块的规则配置module
1
2
3
4
5
6
7
8
9
10
11
module.exports = {
... other code ...
// 定义模块的规则配置
module: {
rules: [
// 这里是模块规则的数组,用于配置不同类型的文件如何被处理
// 每个规则包括测试表达式(test)、加载器(loader)和选项(options)等
]
},
... other code ...
}

写好之后进行下一步操作,后续随着配置增加,会给这个rules数组添加新东西


插件配置数组plugins
1
2
3
4
5
6
7
8
9
module.exports = {
... other code ...
// 插件配置数组
plugins: [
// 这里放置项目使用的插件列表
// 插件可以执行各种任务,如自动优化和压缩代码、注入环境变量等
]
... other code ...
}

写好之后进行下一步操作,后续随着配置增加,会给这个数组添加新东西


webpack.dev.js开发环境配置文件

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
/**
* 合并基础的webpack配置文件与开发环境的特定配置。
*
* @module exports
* @param {Object} base - 来自webpack.common.js的基础配置对象。
* @returns {Object} 返回一个合并后的webpack配置对象,专用于开发环境。
*/

const { merge } = require("webpack-merge") // 引入webpack合并配置的工具
const base = require("./webpack.common.js") // 引入基础的webpack配置文件

module.exports = merge(base, {
mode: 'development', // 设置为开发模式
devtool: "source-map", // 启用source-map,便于调试
devServer: {
compress: true, // 启用gzip压缩
port: 3000, // 设置监听的端口号
hot: true, // 启用热更新
open: true, // 自动打开浏览器
historyApiFallback: true, // 使得HTML5 History API可以正常工作
client: {
progress: true, // 显示编译进度
logging: 'error', // 仅输出错误日志
overlay: {
errors: true, // 在浏览器上覆盖错误警告
warnings: true // 在浏览器上覆盖警告
}
},
proxy: {
// 设置对"/apis"开头的请求的代理
"/apis": {
target: "your-target-url", // 目标服务器URL
pathRewrite: {"^/apis": "" }, // 将请求路径中的"/apis"移除
changeOrigin: true, // 设置请求的origin为目标服务器的origin
secure: false // 目标服务器地址是否为https,false表示不是
}
}
}
})

这段代码使用 webpack-merge 工具来合并基础的Webpack配置和开发环境特定的配置,生成一个适用于开发环境的Webpack配置对象


webpack.pros.js生产环境配置文件

1
2
3
4
5
6
7
8
9
10
11
const path = require('path')
const { merge } = require("webpack-merge")
const base = require("./webpack.common.js")


module.exports = merge(base, {
mode: 'production',
plugins: [

]
})


修改script启动项目命令

运行这段命令,安装cross-env包,用于设置跨平台环境变量,通常用于设置NODE_ENV等环境变量

1
npm install cross-env --save-dev

然后修改package.json文件的script

1
2
3
4
"scripts": {
"dev": "cross-env NODE_ENV=development webpack serve --config ./webpackConfig/webpack.dev.js",
"build": "cross-env NODE_ENV=production webpack --config ./webpackConfig/webpack.prod.js"
},

3.3-React系列

安装React全家桶

1
npm install react react-dom

新建src文件

这个目录是我们React项目的主要存放地方,所有Vue的东西都是包含在这里面的

新建assets

这个目录主要存放我们的资源:图片、字体、css

新建apis

这个目录主要存放我们的接口,分成不同的模块js文件去存放对应的接口

新建utils

这个目录主要存放我们的一些公共函数

新建hooks

这个目录主要存放我们的一些hooks函数

新建components

这个目录主要存放我们的公共组件

新建store

这个目录是要存放公共状态管理,是pinia的使用入口

新建pages

这个目录存放项目的React主要页面

新建main.tsx

这个文件是Webpack的项目入口,也是React的实例创建文件

1
2
3
4
5
6
7
8
import React from 'react'
import { createRoot } from 'react-dom/client'
import App from './App';

const root = document.getElementById('root')
if(root) {
createRoot(root).render(<App />)
}

新建App.tsx

1
2
3
4
5
6
import React from 'react'

function App() {
return <h2>webpack5-react-ts</h2>
}
export default App

安装Ts类型依赖

1
npm i @types/react @types/react-dom babel-loader @babel/core @babel/preset-react @babel/preset-typescript -D

修改webpack.common.js文件

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
module.exports = {
// ...
module: {
rules: [
{
test: /.(ts|tsx)$/, // 匹配.ts, tsx文件
use: {
loader: 'babel-loader',
options: {
// 预设执行顺序由右往左,所以先处理ts,再处理jsx
presets: [
'@babel/preset-react',
'@babel/preset-typescript'
]
}
}
}
]
}
}

新增tsconfig.json文件

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
{
"compilerOptions": {
"target": "ESNext",
"lib": ["DOM", "DOM.Iterable", "ESNext"],
"allowJs": false,
"skipLibCheck": false,
"esModuleInterop": false,
"allowSyntheticDefaultImports": true,
"strict": true,
"forceConsistentCasingInFileNames": true,
"module": "ESNext",
"moduleResolution": "Node",
"resolveJsonModule": true,
"isolatedModules": true,
"noEmit": true,
"jsx": "react", // react18这里也可以改成react-jsx
"baseUrl": ".",
"paths": {
"@/*": [
"src/*"
],
"@cmp/*": [
"src/components/*"
],
"@api/*": [
"src/apis/*"
],
"@utils/*": [
"src/utils/*"
]
}
},
"include": ["./src"]
}

到此为止的目录结构如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
├─node_modules     
├─src
│ ├─apis // 项目接口
│ ├─assets // css、图片、字体资源
│ │ ├─css
│ │ ├─fonts
│ │ └─images
│ ├─components // 公共组件
│ ├─directive // 自定义指令
│ ├─hooks // hooks函数
│ ├─router // 路由管理
│ ├─store // Pinia状态管理
│ │ └─modules
│ ├─utils // 公共工具函数
│ └─pages // 项目页面
│ ├─Home
│ └─Login
└─webpackConfig // webpack公共、开发、生产配置

指定html文件

在项目的根目录下面新建一个index.html文件,内容如下

1
2
3
4
5
6
7
8
9
10
11
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Webpack Create React</title>
</head>
<body>
<div id="root"></div>
</body>
</html>

接着运行这段命令,安装一下html-webpack-plugin

1
npm install html-webpack-plugin --save-dev

这个插件可以帮助我们将打包好的文件都引入到index.html里面,不再需要我们自己手动去引入

修改webpack.common.js文件

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
const HtmlWebpackPlugin = require('html-webpack-plugin')

module.exports = {
... other code ...
// 插件配置数组
plugins: [
// 这里放置项目使用的插件列表
// 插件可以执行各种任务,如自动优化和压缩代码、注入环境变量等

new HtmlWebpackPlugin({
template: './index.html',
filename: './index.html',
title: 'Vue3 + webpack -> Web App',
minify: {
collapseWhitespace: true, // 去掉空格
removeComments: true // 去掉注释
}
}),
]
... other code ...
}

测试运行

控制台输入npm run dev

这时候编辑器会自动在打包好以后给你在浏览器打开端口3000的地址

image-20240527173235447


3.4-样式系列

在前端工程化里面,常用的预编译的css就是lessscsssass,这里我们选用less来作为项目的预编译器

1
npm install css-loader style-loader less-loader less --save-dev

修改webpack.common.js文件

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
module.exports = {
... other code ...

// 定义模块的规则配置
module: {
rules: [
// 这里是模块规则的数组,用于配置不同类型的文件如何被处理
// 每个规则包括测试表达式(test)、加载器(loader)和选项(options)等

{
// 匹配.css文件
test: /\.css$/,
use: [
// 将CSS样式插入到DOM中
"style-loader",
// 处理CSS文件,支持模块化、压缩等
"css-loader"
]
},

{
// 匹配.less文件
test: /\.less$/,
use: [
// 将CSS样式插入到DOM中
"style-loader",
// 处理CSS文件,支持模块化、压缩等
"css-loader",
// 编译LESS到CSS
"less-loader"
]
}

]
},

... other code ...
}


四、优化项目

4.1-静默样式热更新

1
npm i @pmmmwh/react-refresh-webpack-plugin react-refresh -D

修改webpack.dev.js文件

1
2
3
4
5
6
7
8
9
const ReactRefreshWebpackPlugin = require('@pmmmwh/react-refresh-webpack-plugin');

module.exports = merge(baseConfig, {
// ...
plugins: [
new ReactRefreshWebpackPlugin(), // 添加热更新插件
]
})

五、源代码