如何使用Webpack打包React
前言
我们常用使用 create-react-app
新建 React 项目,它帮我们配置好了开箱即用的 Webpack 配置。但是如果我们要重头搭建一个使用 Webpack 打包的 React 项目,就必须要学习 Webpack 的用法了。
在本文中,你会了解到:
- Webpack 是什么
- 从开发到构建到发布发生了什么事
- 对前端项目的构建流程有一个简单的概念
首先,从 Webpack 开始。
Webpack
Webpack 是一个打包工具,本文中使用到的 Webpack 版本为 ^5.73.0
。
当我们开发一个前端项目时,会分成很多文件,当我们要发布的时候,通常希望把它们整合成少数的几个文件,并加以混淆,压缩体积,以达到最快的传输性能。打包工具就是帮我们做这样的事。
在这里附上 Webpack 的中文站点:Webpack。
以下面的代码为例子,index.js 中引用了 bar.js 模块的代码:
// ./bar.js
export function bar(name) {
console.log(`in bar: ${name}`);
}
// ./index.js
import { bar } from "./bar";
const name = "from index";
bar(name);
console.log("print from index.js");
使用 Webpack 打包 index.js 文件:webpack ./index.js
,默认会输出一个 main.js 文件,内容为整合过和压缩后的内容:
(() => {
"use strict";
console.log("in bar: from index"), console.log("print from index.js");
})();
上面只是做示例而已,先建立起对 Webpack 的简单认知。
但单纯的 Webpack 还不足以我们打包 React 项目,因为 Webpack 默认只支持 js 和 json 的打包,其他的语言一律不认识,像 ts,jsx,css 等都会因为 Webpack 无法识别而打包失败。为了解决这个问题,就需要引入其他 loader 来帮助 Webpack 认识其他语言。
loader
什么是 loader?就是用于帮助 Webpack 认识其他语言的库。比如,如果使用 Webpack 打包 ts 文件:webpack ./index.ts
,会抛出如下错误:
因为 Webpack 不认识 ts 文件,所以我们要引入一个帮助 Webpack 认识 ts 文件的 loader:ts-loader
:npm i -D ts-loader
。
然后在项目根目录下新建一个 webpack.config.js
文件,这个文件里会对 Webpack 进行各种配置,包括我们的 loader。
在 webpack.config.js
里写入:
module.exports = {
module: {
rules: [{ test: /\.ts$/i, use: "ts-loader" }],
},
};
loader 的配置写在 module 节点下的 rules 节点中,每个 loader 的配置有 test
属性:说明要使用的 loader 的文件名规则,use
属性说明要使用哪个 loader。在上面可以看到我们配置了以 .ts
结尾的文件使用 ts-loader
解析。这样,Webpack 在遇到以 .ts
结尾的文件时,就会先使用 ts-loader
解析一遍。
写好配置,再使用 Webpack 打包 ts 文件,输入命令:webpack ./index.ts
,webpack 会寻找当前目录下的 webpack.config.js
文件,如果有,就使用这个文件里的配置。因为我们配置了支持 ts 文件的 loader,所以是打包成功的。你能够在当前目录的 dist 文件夹下找到打包后的文件。
当你了解 loader 是干什么的后,同理,对于 react 的 jsx
和 tsx
文件,我们也需要安装对应的 loader 来帮助 Webpack 解析。
关于 loader 的更多信息,详细看这里的文档。
plugins
loader 只能解析其他语言,所以如果有 loader 无法实现的需求,就需要 plugins 来实现。
比如说,前端的单页面项目会有一个模板 html 文件作为入口,该 html 文件里引用了打包后的 js 文件。我们希望在打包 js 文件后自动把 html 文件也打包并引入 js,就需要 HtmlWebpackPlugin
这个 plugins 来实现这个功能。
先安装:npm i -D html-webpack-plugin
,安装好后在 webpack.config.js
中引入,并在 plugins 节点下配置:
const HtmlWebpackPlugin = require("html-webpack-plugin");
module.exports = {
plugins: [
new HtmlWebpackPlugin({
template: "index.html",
}),
],
};
上面代码新实例化了一个 HtmlWebpackPlugin
对象到 plugins 节点数组中, HtmlWebpackPlugin
对象接收参数 template
,执行了 html 模板的路径,这里要确保该路径下有这个 html 文件,比如内容为:
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8" />
<title>Webpack App</title>
</head>
<body>
<h1>Hello world!</h1>
<h2>Tip: Check your console</h2>
</body>
</html>
webpack 打包后,在 dist
文件夹下找到 index.html
和打包后的 main.js
,其中 index.html
内容如下:
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8" />
<title>Webpack App</title>
<script defer src="main.js"></script>
</head>
<body>
<h1>Hello world!</h1>
<h2>Tip: Check your console</h2>
</body>
</html>
能看到引入了 main.js
文件,这个 html 就成了我们单页应用的入口。
关于 HtmlWebpackPlugin
更多的配置看这里。
希望上面的讲解能够让你稍微了解到构建过程中发生了什么事,简单来说,就是将开发的代码精简成几个文件,对不同的项目会有不同的配置。
搭建 React
那么对 React 项目应该有什么配置呢?这里的 React 版本是 18.
首先确保有能够运行 React 的环境,所以确保安装了 react
和 react-dom
依赖。接着,从上面得知,因为 Webpack 不认识 js 和 json 以外的文件,所以要安装帮助它认识 jsx
,tsx
文件的 loader。
这里我们使用 babel
来认识。由于要在 Webpack 里使用 babel
loader,所以也要安装 babel-loader
。babel-loader
要在 node 里使用转译功能,需要安装 babel-core
,要转义 React 文件,所以要安装 @babel/preset-react
供 babel 使用,如果你使用 ts 编写,那么还要安装 @babel/preset-typescript
让 babel 拥有处理 ts 的能力。
总的来说,安装以下依赖:
npm i -D babel-loader babel-core @babel/preset-react @babel/preset-typescript
以上几个库,我希望你能够充分理解它们各自的作用。
由于我们决定使用 babel 来处理 ts 文件,所以上面的 ts-loader
就不在需要了,将它从依赖和 webpack.config.js
中去掉。
在 webpack.config.js
中修改为如下 loader:
{
module: {
rules: [
{
test: /\.(js|jsx|ts|tsx)$/,
loader: "babel-loader",
exclude: /node_modules/,
}
],
},
}
如上,我们将结尾为 js
,jsx
,ts
,tsx
的文件都交给了 babel-loader
处理。这里我们使用了 loader
节点而不是 use
节点,这两者都是 use: [{ loader: 'xxx-loader' }]
的简写。添加了 exclude
节点,意思是符合这个规则的文件、文件夹不使用这个 loader 处理。
接着要配置 babel,以告诉 babel 要这么处理这几个文件。在根目录下新建 .babelrc
文件,babel 会使用这个文件里的配置。
{
"presets": ["@babel/preset-react", "@babel/preset-typescript"]
}
在 presets
节点中配置我们的转译,@babel/preset-typescript
用于处理 ts 文件,@babel/preset-react
用于处理 React 文件。
到这里,Webpack 关于 React 的简单配置就可以了。但是为了让项目能够跑起来,还得做一点其他的配置。
其他配置
下面的各种配置,不在本文的讲解范围内,希望你能够自己去了解。
在 webpack.config.js
下添加 resolve
节点,节点下的 extensions
数组会告诉 Webpack 如果遇到导入文件没有指定后缀名的话,从这个数组里的后缀名里逐个寻找。
{
resolve: {
extensions: [".tsx", ".ts", ".jsx", ".js", "..."],
}
}
为了支持 ts 语法,需要在根目录下新建 tsconfig.json
文件,内容如下:
{
"compilerOptions": {
"allowSyntheticDefaultImports": true,
"module": "es6",
"target": "es5",
"allowJs": true,
"jsx": "react"
},
"include": ["src/**/*"],
"exclude": ["node_modules"]
}
在 src
目录下建立三个代码文件:main.tsx
,App.tsx
,foo.ts
,内容分别如下:
// main.tsx
// 项目入口
import ReactDOM from "react-dom/client";
import React from "react";
import App from "./App";
ReactDOM.createRoot(document.getElementById("root")).render(<App />);
// App.tsx
// App 组件
import React from "react";
import { print } from "./foo";
export default function App() {
React.useEffect(() => {
print("in App component");
}, []);
const [count, setCount] = React.useState(0);
return (
<div>
APP
<div>{count}</div>
<button
onClick={() => {
setCount(count + 1);
}}
>
Btn
</button>
</div>
);
}
// foo.ts
// ts 代码
export function print(value: string) {
console.log(value);
}
需要安装 React 的声明文件:npm i -D @types/react-dom
,不然找不到各种类型。
打包
最终,我们可以执行 webpack ./src/main.tsx
打包 React 项目了,这里选择了 ./src/main.tsx
文件作为打包的入口,打包完成后,你会在根目录的 dist
文件夹下看到打包后的文件:
在浏览器中打开 index.html
文件,能够正常运行,即说明打包成功了。dist
文件夹内的内容就是我们最终要发布的文件。运行起来看看吧。
总结
本文只是简单介绍 Webpack 的功能而已,还有很多常用的功能没有介绍,打包后的文件也有很多问题,比如说,代码没有混淆,体积太大,足有 1.16M!这个问题参考这篇文档可以解决。
更多的配置还是希望你能够自己去找到,毕竟,我不是想帮你们解决问题,而是想教你们如何解决问题。
告辞。
参考
Webpack 中文文档 by Webpack
webpack 深入了解之 loader 配置详解(一) by 致我逝去的青春
Issue: ReferenceError: React is not defined by yoyo837
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· Manus爆火,是硬核还是营销?
· 终于写完轮子一部分:tcp代理 了,记录一下
· 别再用vector<bool>了!Google高级工程师:这可能是STL最大的设计失误
· 单元测试从入门到精通
· 震惊!C++程序真的从main开始吗?99%的程序员都答错了