30分鐘掌握 Webpack
為什么使用 Webpack
在我們進行傳統網頁開發中,會在 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 就可以了。在打包過程中,還可以通過插件來干預打包過程,例如剔除不必要的代碼,形成體積更小的項目。
創建項目
-
打開命令行工具,我們在這里創建一個名為
blog的博客項目:mkdir blog cd blog yarn init -y (或者npm init) -
添加
webpack依賴:yarn add webpack webpack-cli --dev -
使用
VSCode打開項目:code .
初出茅廬
-
在
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> <h1>Hello World</h1> <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 來導入其他的依賴。
使用 import 導入依賴
-
在
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文件. -
在網頁中查看下結果:

成功地輸出了數組.
Webpack 配置文件
webpack 的配置文件可以說是 webpack 最核心的部分了,我們可以在配置文件中修改入口和出口文件、通過 loader 加載不同類型的文件和使用 plugins 對代碼做其他的操作。
嘗試修改打包后生成文件的名稱
-
在項目中新建
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文件.
使用模塊化語法
-
修改
/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:
列表成功插入到了頁面.
引入 css
-
在
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打包:
可以看到,剛才寫的樣式生效了.
加載圖片
-
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:
自動生成 HTML
上述的例子中,我們只是使用 webpack 來打包 js 和 css 文件,并手動的導入編寫好的 html 中,使用下面的插件,就可以自動為我們生成 HTML 文件。
-
安裝插件:
yarn add html-webpack-plugin --dev -
使用插件:
const HtmlWebpackPlugin = require("html-webpack-plugin"); ... plugins: [new HtmlWebpackPlugin({ title: "博客列表", // 這里可以自定義網頁的標題 })], -
npx webpack:
可以看到生成了和剛才相同的頁面
使用
webpack打包出來的網頁沒有顯示<h1>Hello World</h1>的原因是 這個標簽是我們自己寫的?? -
定義打包好 html 文件的網頁標題
我們使用
html-webpack-plugins打包生成的文件名默認是 Webpack App,其實網頁標題是可以在插件內傳遞參數來更改的:plugins: [new HtmlWebpackPlugin({ title: "博客列表", })],
Babel
有時我們的代碼可能需要運行在更低版本的瀏覽器上,這些瀏覽器可能并不支持我們所寫的更高級的代碼,這時就需要用到 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的形式,增強了對低版本瀏覽器的兼容性。
使用 Terser 插件壓縮打包后的代碼
-
安裝插件:
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 文件都被緊密地寫在了一起,右鍵屬性查看文件大小也要比之前的小一些。??
使用 DevServer 插件自動打包
-
安裝:
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
可以看到生成了文件后綴名不同的文件,這樣可以避免由于瀏覽器緩存機制而導致更新不及時的問題。
配置目錄別名:
和之前寫的 http://www.rzrgm.cn/hhsk/p/16460701.html 大同小異
- 配置:
// webpack.config.js module.exports = { ... resolve: { alias: { assets: path.resolve(__dirname, "src/assets") } } }

浙公網安備 33010602011771號