持续创作,加速成长!这是我参与「掘金日新计划 · 6 月更文挑战」的第2天,点击查看活动详情
我的博客网站,学习react后写的,开源了管理系统及后台WebApi,欢迎查看交流 👉 www.weison-zhong.cn
前言
本文章仅介绍前端开发中常用的webpack的配置,基于webpack@5.73.0,不涉及webpack原理知识,若想学习原理相关的,可以看👉[万字总结] 一文吃透 Webpack 核心原理
1 初始化
- mkdir webpack-learn-notes
- cd webpack-learn-notes
- npm init 按提示完成即可
- npm install webpack webpack-cli -D 安装webpack
2 配置webpack.config.js
- 在项目根目录下新建webpack.config.js文件及src目录,并在src下新建index.js入口文件,在里面写入简单的测试代码。
class Test {
constructor() {
document.write("test");
}
}
new Test();

- 控制台运行 npx webpack 打包,webpack会默认帮我们在根目录创建了dist文件夹用来保存输出文件,里面有main.js,但这段代码直接在浏览器跑是不行的,后面需要配置babel转换为es5的代码。
- 当然,我们也可以手动配置打包入口和输出目录
const path = require("path"); module.exports = { entry: "./src/index.js", // 打包入口地址 output: { path: path.join(__dirname, "dist"), // 输出文件目录 filename: "bundle.js", // 输出文件名 }, }; - 此时查看控制台发现有个warning警告,提醒我们配置一下配置 mode,webpack目前有以下三种模式:
- developmen:开发模式,打包更加快速,省了代码优化步骤;
- production:生产模式,打包比较慢,会开启 tree-shaking和压缩代码;(默认模式)
- none:不使用任何默认优化选项
- mode配置方式:
- 在项目根目录下新建webpack.config.js配置:
配置好重新运行npx webpack 查看已经没有警告信息了module.exports = { mode: 'development', ... };- 或者从cli中传递参数: webpack --mode=development
3 配置babel
- 先安装依赖: npm install babel-loader @babel/core @babel/preset-env -D
- babel-loader 使用 Babel 加载 ES2015+ 代码并将其转换为 ES5;
- @babel/core Babel 编译的核心包;
- @babel/preset-env Babel 编译的预设,可以理解为 Babel 插件的超集.
- 根目录下新增.babelrc 配置文件
// .babelrc
{
"presets": ["@babel/preset-env"]
}
- 修改webpack.config.js配置
const path = require("path"); module.exports = { mode: "development", // 模式 entry: "./src/index.js", // 打包入口地址 output: { path: path.join(__dirname, "dist"), // 输出文件目录 filename: "bundle.js", // 输出文件名 }, module: { rules: [ { test: /\.(jsx|js)$/, use: "babel-loader", }, ], }, };- 配置完成后再打包发现代码已经转换为es5
- 配置完成后再打包发现代码已经转换为es5
4 配置html-webpack-plugin
- 如果不配置html-webpack-plugin插件,那么我们打包完后要手动在dist目录下新建index.html并把js文件引入script标签中;
此时在浏览器中即可预览到效果
- 实际项目中,通常会配置打包文件名的哈希值配合设置浏览器缓存,这样每次打包输出的文件名都不同,而借助html-webpack-plugin插件可自动帮我们完成把打包文件插入html这项工作;
- ,安装依赖 npm install html-webpack-plugin -D,根目录下新建public目录用来存放静态资源,并在其中新建index.html模板
- 在webpack.config.js中配置
html-webpack-plugin... const HtmlWebpackPlugin = require('html-webpack-plugin'); module.exports = { ... plugins: [ new HtmlWebpackPlugin({ template: path.resolve(__dirname, './public/index.html'), inject: 'body', scriptLoading: 'blocking', }), ] } - 我们可以先删除dist文件夹再运行npx webpack打包看看效果
可以看到已经自动生成了index.html并引入了js文件
5 配置文件名哈希值
-
实际项目中一般都有在web服务器上配置浏览器缓存以加快页面加载和减轻服务器压力,以我自己的博客网站为例,在nginx中我给js和图片等静态资源配置了强缓存,所以配置文件名哈希值是很必要的,否则当页面有新更新时浏览器还读取了旧的缓存文件。
-
配置只需要在webpack.config.js的output属性中修改下filename即可
module.exports = { ... output: { path: path.join(__dirname, "dist"), // 输出文件目录 filename: "bundle.[contenthash:8].js",//contenthash指每个文件都有单独的hash值,文件的改动只会影响自身的hash值 }, -
重新打包即可看到效果
但发现旧的bundle.js文件还在,所以还要配置clean-webpack-plugin插件来自动清空打包目录
6 配置clean-webpack-plugin清空打包目录
- 安装依赖:npm install clean-webpack-plugin -D
- 修改webpack.config.js中的plugins属性
module.exports = {
...
plugins: [
new HtmlWebpackPlugin({
template: path.resolve(__dirname, "./public/index.html"),
inject: "body",
scriptLoading: "blocking",
}),
new CleanWebpackPlugin(), //清空打包目录
],
};
- 重新打包发现dist会先清空,不会有旧的文件了
7 配置css-loader
-
新建index.css文件并在index.js中导入
-
重新打包,发现控制台有报错,提示需要loader来处理css文件
-
安装依赖 npm install css-loader -D
-
配置webpack.config.js
...
module: {
{
test: /\.css$/, //匹配所有的 css 文件
use: "css-loader", // use: 对应的 Loader 名称
},
],
},
...
重新打包预览发现并没有效果
因为还少了style-loader,先npm install style-loader -D 安装依赖 修改配置后重新打包
```js
...
{
test: /\.css$/,
use: ["style-loader", "css-loader"], //loadeer执行顺序是从右至左
},
...
```
此时预览发现已经有效果了
8 配置less-loader
- 安装依赖 npm install less less-loader -D
- 修改index.css为index.less
- 修改配置文件
... { test: /\.(le|c)ss$/, use: ["style-loader", "css-loader", "less-loader"], }, ...
9 抽离并压缩css文件
- 安装依赖 npm i css-minimizer-webpack-plugin -D
- 修改配置文件
const MiniCssExtractPlugin = require("mini-css-extract-plugin");
const CssMinimizerPlugin = require("css-minimizer-webpack-plugin");
...
module: {
...
{
test: /\.(le|c)ss$/,
use: [MiniCssExtractPlugin.loader, "css-loader", "less-loader"],
},
],
},
optimization: {
minimizer: [new CssMinimizerPlugin()],
},
plugins: [
...
new MiniCssExtractPlugin(),
],
...
- 重新打包发现css文件已经单独抽离
10 安装webpack-dev-server工具实现热更新
- 安装依赖 npm install webpack-dev-server -D
- 修改配置文件
module.exports = { ... plugins:[...], devServer: { port: "3000", // 默认是 8080 hot: true, compress: true, // 是否启用 gzip 压缩 open: false, // 是否自动打开浏览器 proxy: { //配置代理 "/api": { target: "http://0.0.0.0:5000", pathRewrite: { "/api": "", }, }, }, }, ... - 在package.json的script中添加一个命令
"scripts": { "dev": "webpack serve" }, - 控制台执行
npm run dev即可启动项目且浏览器自动打开了 http://localhost:3000/ ,修改样式发现可以自动构建并实时预览效果了 - 关于npm run xxx可看我的另一篇文章npm run xxx的执行流程
11 配置sourcemap
- 修改index.js
控制台会报ReferenceError错误,但如果不配置sourcemap,我们很难找出出错位置import './index.less' class Test { constructor() { document.write("test"); } } new Test(); console.log(a); - 修改webpack.config.js
重新启动项目即可看到效果module.exports = { ... devtool: 'eval-cheap-module-source-map', };
12 配置环境
- 在第11条中,对于生产环境一般不需要生成sourcemap,所以需要根据开发和生产等不同环境对webpack做不同的配置;
- 首先需要修改下script脚本传递不同参数区分环境:
"scripts": { "dev": "webpack serve --env development", "build": "webpack --env production" }- 又或者拆分成不同脚本,例如create-react-app脚手架搭建的react项目
- 又或者拆分成不同脚本,例如create-react-app脚手架搭建的react项目
- 修改webpack.config.js配置文件
module.exports = function (env) { const isEnvDevelopment = env.development;//判断是否为开发环境 return { ... devtool: isEnvDevelopment ? "eval-cheap-module-source-map" : false, ... };
13 配置copy-webpack-plugin插件复制静态资源到打包目录
- 在public目录下新建js文件夹存放foo.js,在index.html中引入
- 重新打包打开预览发现找不到foo.js文件,因为dist目录并没有这个文件
- 安装依赖 npm install copy-webpack-plugin -D
- 修改配置文件
const CopyWebpackPlugin = require("copy-webpack-plugin");
...
new CopyWebpackPlugin({
patterns: [
{
from: path.resolve(__dirname, "public/static"),
to: path.resolve(__dirname, "dist/static"),
},
],
}),
...
-
运行npm run build 打包后发现已经自动将文件复制到dist目录了
14 资源加载器
- 改造一下index.js,并在src目录下创建如下结构保存图片
此时控制台会报错
- 修改webpack.config.js配置文件,再重新启动项目就可以了
rules: [ ... { test: /\.(png|jpg|gif|jpeg|webp|svg|eot|ttf|woff|woff2)$/, type: "asset", generator: { filename: "assets/[name].[hash:8].[ext]", }, parser: { dataUrlCondition: { maxSize: 10 * 1024, //超过10kb时不转换为base64 }, }, }, ]
15 配置路径别名
- 修改配置文件
... resolve: { // 配置别名 alias: { "@": path.join(__dirname, "src"), }, }, - 测试效果
import photo1 from '../src/assets/images/a.png' 改为 ↓ import photo1 from '@/assets/images/a.png'
16 添加react支持 基于react17
- 安装依赖 npm i @babel/preset-react -D
- 修改.babelrc 配置文件
// .babelrc { "presets": ["@babel/preset-env", "@babel/preset-react"] } - 新建App.jsx组件并修改index.js文件
//App.jsx
import React from 'react'
export default function App() {
return (
<div>App</div>
)
}
//index.js
import ReactDOM from "react-dom";
import React from "react";
import App from "./App.jsx";
ReactDOM.render(<App />, document.getElementById("root"));
- 重新启动项目即可
17 添加Vue支持 基于Vue3
- 安装依赖:
- npm i -D vue-loader vue-template-compiler vue-style-loader
- npm i vue -S
- 修改webpack配置
const { VueLoaderPlugin } = require("vue-loader/dist/index"); //rules中增加 { test: /\.vue$/, use: ["vue-loader"], }, //plugins中增加new VueLoaderPlugin(), - 新增App.vue
<template>
<div>
<p class="title">{{ title }}</p>
</div>
</template>
<script>
import { defineComponent, ref } from "vue";
export default defineComponent({
setup() {
const title = ref("test");
return {
title,
};
},
});
</script>
<style scoped>
.title {
color: #000;
}
</style>
- 修改index.js
import { createApp } from "vue";
import App from "./App.vue";
const app = createApp(App);
app.mount("#root");
- 重启项目即可
18 webpack构建配置优化
学习中...