本文基于:峰华前端工程师--30分钟掌握Webpack
<font color="#6ad9a7">为什么使用 Webpack</font>
在我们进行传统网页开发中,会在 index.html 中引入大量的 js 和 css 文件,不仅可能会导致命名冲突,还会使页面体积变大,因为如果引用了第三方库,需要加载所有的代码。而在 node.js 出现后,javascript 项目支持通过 require 支持模块化开发了,并且支出 npm 方便地管理依赖。
借着 node.js 和浏览器js 的一致性,前端项目开始在 node.js 下开发,完成之后把代码构建成浏览器支持的形式。对于 react 或 vue 这种组件化的开发方式,因为有很多分散的文件,那么久特别需要这样的构建操作。
Webpack 就是进行这一步构建操作的,把 node.js 模块化的代码转化为浏览器可执行的代码。它提供了 import 和 export ES6模块化语法的支持,然后通过分析代码中 import 导入的依赖,把需要的代码加载进来。在 Webpack 中,任何文件都可以通过 import 导入,只要有对应的 loader 就可以了。在打包过程中,还可以通过插件来干预打包过程,例如剔除不必要的代码,形成体积更小的项目。
<font color="#6ad9a7">创建项目</font>
-
打开命令行工具,我们在这里创建一个名为
blog的博客项目:mkdir blog cd blog yarn init -y (或者npm init) -
添加
webpack依赖:yarn add webpack webpack-cli --dev -
使用
VSCode打开项目:code .
<font color="#6ad9a7">初出茅庐</font>
-
在
blog项目下新建src文件下,创建index.js:console.log("Hello World");我们先只做一个简单的输出.
-
在
blog项目下新建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>Document</title> </head> <body> Hello World <script src="./dist/index.js"></script> </body> </html> -
使用
LiveServer查看刚刚所编写的 html页面:
可以看到浏览器成功显示了 "Hello World",并且控制台也能够成功输出.
-
尝试使用
webpack打包打开控制台,输入
npx webpack
npx 能够直接运行 node_modules 下面安装的库的自带的命令行,而不用写 node_modules 下一串的绝对路径。
打包完成后可以看到项目里面生成了一个 dist 目录,里面有一个 main.js 文件,其内部的内容和我们刚刚所编写的 index.js 的文件一模一样,这是因为我们并没有使用任何 import 来导入其他的依赖。
<font color="#6ad9a7">使用 import 导入依赖</font>
-
在
src下新建一个data.js文件:export function getBlogPosts() { return ["博客1", "博客2", "博客3"]; } -
在
index.js中导入data.js中的函数并调用:import { getBlogPosts } from "./data"; console.log(getBlogPosts()); -
重新使用
webpack打包以下,查看结果:npx webpack现在进入
/dist/main.js中看一下,代码被简化成了直接输出刚才我们所编写的数组的语句,说明webpack自动判断了我们所编写代码的逻辑,并通过import语句得到了我们所引入的代码,分析后生成新的js文件. -
在网页中查看下结果:

成功地输出了数组.
<font color="#6ad9a7">Webpack 配置文件</font>
webpack 的配置文件可以说是 webpack 最核心的部分了,我们可以在配置文件中修改入口和出口文件、通过 loader 加载不同类型的文件和使用 plugins 对代码做其他的操作。
<font color="#6ad9a7">尝试修改打包后生成文件的名称</font>
-
在项目中新建
webpack.config.js文件:const path = require("path"); module.export = { mode: "development", // 设置为开发模式,方便调试 entry: "./src/index.js", output: { filename: "dist.js", path: path.resolve(__dirname, "dist"), // 设置文件名和目录 } } -
执行
npx webpack命令打包
可以看到
dist文件夹下多了个dist.js文件.
<font color="#6ad9a7">使用模块化语法</font>
-
修改
/index.html的script标签:<script src="./dist/dist.js"></script>将
main.js修改成为我们刚刚使用webpack打包生成的dist.js -
修改
/src/index.js文件,将之前编写的数组变成ul元素插入页面中:const blogs = getBlogPosts(); const ul = document.createElement("ul"); blogs.forEach(blog => { const li = document.createElement("li"); li.innerText = blog; ul.appendChild(li); }) document.body.appendChild(ul); -
npx webpack:
列表成功插入到了页面.
<font color="#6ad9a7">引入 css</font>
-
在
src下新建style.css文件:h1 { color: blueviolet; }这里只是简单地改变
h1标签的颜色. -
在
/src/index.js中引入css文件:import "./style.css"; -
安装
loader:打开控制台,输入:
yarn add --dev style-loader css-loader -
在
webpack.config.js中配置loadermodule.exports = { mode: "development", output: {...}, ... module: { rules: [{ test: /\.css$/i, use: ["style-loader", "css-loader"], }] } }module -> rules -> test 内是一个正则表达式,表示以 .css 结尾的文件.
use 属性下是所使用的loader -
再次使用
npx webpack打包:
可以看到,刚才写的样式生效了.
<font color="#6ad9a7">加载图片</font>
-
webpack原生支持图片等静态文件,但是需要在webpack.config.js中编写配置:module.exports = { ... module: { rules: [ ... { test: /\.(png|svg|jpg|jpeg|gif)$/i, type: "assets/resource", }] } } -
在
src下载新建assets/文件夹,放入一张图片:
-
在
index.js中引入图片:import AbcImage from "./assets/abc.png" ... const image = document.createElement("img"); image.src = AbcImage; document.body.prepend(image); -
npx webpack:
<font color="#6ad9a7">自动生成 HTML</font>
上述的例子中,我们只是使用 webpack 来打包 js 和 css 文件,并手动的导入编写好的 html 中,使用下面的插件,就可以自动为我们生成 HTML 文件。
-
安装插件:
yarn add html-webpack-plugin --dev -
使用插件:
const HtmlWebpackPlugin = require("html-webpack-plugin"); ... plugins: [new HtmlWebpackPlugin({ title: "博客列表", // 这里可以自定义网页的标题 })], -
npx webpack:
可以看到生成了和刚才相同的页面
使用 webpack 打包出来的网页没有显示 Hello World 的原因是 这个标签是我们自己写的😮
-
定义打包好 html 文件的网页标题
我们使用
html-webpack-plugins打包生成的文件名默认是 Webpack App,其实网页标题是可以在插件内传递参数来更改的:plugins: [new HtmlWebpackPlugin({ title: "博客列表", })],
<font color="#6ad9a7">Babel</font>
有时我们的代码可能需要运行在更低版本的浏览器上,这些浏览器可能并不支持我们所写的更高级的代码,这时就需要用到 babel 转译工具来使我们的代码变成浏览器能够识别的代码。
-
安装
babel-loader相关依赖:yarn add --dev babel-loader @babel/core @babel/preset-env -
在
webpack.config.js中添加配置:rules: [ ... { test: /\.js$/, // 识别js为结尾的文件 exclude: /node_modules/, //不解释node_modules/下的文件 use: { loader: "babel-loader", options: { presets: ["@babel/preset-env"] } } }]这里可以在
module.exports下配置devtool="inline-source-map"方便查看打包后的源码 -
使用
npx webpack重新打包下,进入dist/dist.js查看相关代码:/* 打包前的 */ blogs.forEach(blog => { const li = document.createElement("li"); li.innerText = blog; ul.appendChild(li); })blogs.forEach(function (blog) { var li = document.createElement("li"); li.innerText = blog; ul.appendChild(li); });可以看到 箭头函数已经被转换成了
.forEach的形式,增强了对浏览器的兼容性。
<font color="#6ad9a7">使用 Terser 插件压缩打包后的代码</font>
-
安装插件:
yarn add --dev terser-webpack-plugin -
配置:
// webpack.config.js const TerserPlugin = require("terser-webpack-plugin"); module.exports = { ... optimization: { minimize: true, minimizer: [new TerserPlugin()], }, } -
打包:
npx webpack
可以看到我们打包生成的 js 文件都被紧密地写在了一起,右键属性查看文件大小也要比之前的小一些。😎
<font color="#6ad9a7">使用 DevServer 插件自动打包</font>
-
安装:
yarn add -dev webpack-dev-server -
配置:
module.exports = { ... devServer: { static: "./dist", }, }为了我们以后方便运行开发服务器,还需要在
package.json里添加一个script:{ ... "scripts": { "start": "webpack serve --open" }, } -
启动服务器:
yarn start // 或 npm run start -
尝试一下 "热更新?"
在
index.js下添加如下代码:const header1 = document.createElement("h1"); header1.innerText = "Hello"; document.body.appendChild(header1); -
保存,查看网页
这里不在使用 VsCode 的
Live Server插件了,而是在浏览器地址栏输入命令行中输出的地址:

成功!👏
那么 webpack 是如何实现热更新的呢?其实是在我们每次保存时,插件自动生成新的
dist.js并把之前的dist.js写入缓存,这或多或少会增加我们电脑的开销。但 webpack 贴心的为我们想到了这一点。 -
每次打包生成新的
/dist.js配置
webpack.config.jsoutput: { filename: "[name].[contenthash].js", // name 默认为 main path: path.resolve(__dirname, "dist"), },更改下
index.js代码,运行npx webpack
可以看到生成了文件后缀名不同的文件,这样可以避免由于浏览器缓存机制而导致更新不及时的问题。
<font color="#6ad9a7">配置目录别名:</font>
和之前写的 https://www.cnblogs.com/hhsk/p/16460701.html 大同小异
- 配置:
// webpack.config.js module.exports = { ... resolve: { alias: { assets: path.resolve(__dirname, "src/assets") } } }










