構建工具系列
- Gulp構建工具
- Grunt構建工具
- Webpack構建工具
- Vite構建工具
Webpack構建工具
- 構建工具系列
- 前言
- 一、安裝
- 打包
- 配置webpack
- 安裝樣式加載器
- devtool
- webpack devtool 配置詳解
- 常見 devtool 值及適用場景
- 選擇建議
- 性能影響
- 注意事項
- module
- 處理流程
- module.rules
- module.use
- module.type
跟著B站視頻30 分鐘掌握 Webpack寫的
代碼:項目地址
前言
Webpack 是一個現代 JavaScript 應用的靜態模塊打包工具。它將項目中的各類資源(如 JavaScript、CSS、圖片等)視為模塊,通過依賴關系分析生成優化后的靜態資源。
一、安裝
- 通過 npm 安裝相關插件:
mkdir pkdemo cd pkdemo npm init -y npm i webpack webpack-cli -D npm i html-webpack-plugin -D npm i babel-loader @babel/core @babel/preset-env -D npm i terser-webpack-plugin -D npm i webpack-dev-server -D npm i webpack-bundle-analyzer -D code .
- npm init -y 是一個快速初始化 Node.js 項目的命令,它跳過交互式問答環節,直接生成默認的 package.json 文件。 -y 或 --yes 參數表示使用默認配置,無需手動輸入信息。默認值包括項目名(基于當前目錄)、版本號(1.0.0)、描述等字段。
- webpack 是模塊打包工具,用于處理 JavaScript 和其他靜態資源
- webpack-cli 是 Webpack 的
命令行工具
,提供命令行交互和配置支持。- –save-dev(或 -D 簡寫)表示將安裝的包記錄在 devDependencies 中,即這些包僅在開發階段需要,不會包含在生產環境中。
- html-webpack-plugin一個常用的插件,用于簡化 HTML 文件的創建和管理。它能夠
自動生成 HTML 文件
,并自動注入打包后的 JavaScript 和 CSS 資源。- babel-loader將現代 JavaScript 代碼(如 ES6+、TypeScript 或 JSX)轉換為向后兼容的版本,確保代碼能在舊版瀏覽器或環境中運行。babel-loader 依賴于 Babel 核心工具鏈(@babel/core)和配置的預設(presets)或插件(plugins)來完成轉譯任務。
- @babel/core負責解析源代碼、應用插件或預設的轉換規則,并生成目標代碼,是
整個 Babel 生態系統的引擎
。- @babel/preset-env 是一個智能預設,根據目標瀏覽器或環境自動確定需要的 Babel 插件和 polyfill。它通過分析項目的 browserslist 配置或手動指定的目標環境,僅轉換必要的語法特性,避免不必要的代碼轉換。例如:
- 如果目標環境支持箭頭函數,@babel/preset-env 會跳過箭頭函數的轉換。
- 如果目標環境缺乏 Promise,它會自動引入相關 polyfill(需配合 core-js 使用)。- terser-webpack-plugin用于通過 Terser 工具
壓縮 JavaScript 代碼
- webpack-dev-server一個基于 Express 的本地開發服務器,專為 webpack 項目提供實時重新加載(Live Reloading)和模塊熱替換(HMR)功能。它通過內存編譯文件,避免寫入磁盤,從而提升開發效率。配置完成,
初次打包后將自動打開瀏覽器并加載頁面,且更改代碼后將自動更新頁面
。- webpack-bundle-analyzer 是一個可視化工具,用于分析 Webpack 構建生成的 bundle 文件。它幫助開發者理解打包后的文件結構、大小及其依賴關系,從而優化性能。
配置后打包得時候會自動顯示一個可視化頁面,從里面可以看到各文件大小
。
可視化分析 bundle 組成
通過交互式樹狀圖或矩形圖展示 bundle 中每個模塊的大小及其占比,直觀呈現哪些模塊占用了最多空間。開發者可以快速定位體積過大的模塊。
識別冗余或重復依賴
工具會高亮顯示重復或未被使用的依賴項,幫助開發者發現代碼分割或 Tree Shaking 未優化的部分,減少不必要的代碼打包。
優化代碼分割策略
分析結果可用于調整 Webpack 的 SplitChunks 配置,合理拆分公共代碼或第三方庫,避免單個 bundle 過大影響加載速度。
對比不同構建版本
支持與歷史構建結果對比,觀察優化前后的 bundle 變化,驗證配置調整是否有效。例如檢查是否成功壓縮了特定依賴的體積。
輔助長期性能監控
整合到持續集成流程中,定期生成分析報告,監控項目體積的增長趨勢,防止因新增依賴導致性能退化。- code . 打開VScodde
打包
在項目根目錄新建一個
index.html
文件。輸入英文狀態下的!
或者輸入html:5
并回車即可自動創建一個HTML模板。
新建src\index.js
在插件市場安裝Live Server
,可幫我們運行html頁面,在html頁面右鍵選擇open in the Liver Server
即可(安裝目的:查看html頁面編寫是否有問題)。
運行打包指令:
npx webpack
在根目錄出現一個dist
文件夾即打包成功。
配置webpack
在項目根目錄新建webpack.config.js文件,并在其中進行信息配置。
// 導入path插件
const path = require('path');
//導入靜態頁面生成插件
const HtmlWebpackPlugin = require('html-webpack-plugin');
//導入壓縮插件
const TerserPlugin = require('terser-webpack-plugin');
//導入打包分析插件
const BundleWebpackPlugin = require('webpack-bundle-analyzer').BundleAnalyzerPlugin;
/*
* model.exports:nodejs模塊導出對象
* mode 開發模式或生產模式
* entry 用于指定打包的入口文件。webpack會從這些入口文件開始,構建內部依賴圖,并打包所有依賴模塊
* output 用于指定打包后的文件輸出位置、文件名格式以及其他相關設置
* module指的是項目中可被分割的最小功能單位。每個文件(如JavaScript、CSS、圖片等)都被視為一個module.
* webpack通過分析這些module之間的依賴關系,構建依賴圖(Dependency Graph),最終打包成瀏覽器可識別的靜態資源
*/
module.exports = {mode: 'development', // 模式, development或production//設置此屬性是為了方便查看打包后得源代碼devtool: 'inline-source-map', // 開發環境下使用source-map,生產環境下使用hidden-source-map,eval-source-mapentry: "./src/index.js",//入口文件output: {//輸出文件path: path.resolve(__dirname ,'dist'), // 指定輸出文件的目錄,必須為絕對路徑// filename: "bundle.js"// 定義輸出文件的名稱。可以使用[name]、[hash]等占位符動態生成文件名filename: "[name].[contenthash].js"// [name]會被替換為入口文件的名稱,[contenthash]會根據內容生成一個唯一的哈希值,確保文件名在內容變化時也會變化,從而實現緩存優化},optimization: {minimize:true,//是否壓縮minimizer:[new TerserPlugin()]//使用TerserPlugin壓縮},/* 插件 * plugins:[new HtmlWebpackPlugin() ]可自動生成html,可不傳參*/plugins:[// 自動生成html文件new HtmlWebpackPlugin({title: 'webpack打包測試',// 定義生成的html文件的標題filename: 'testIndex.html',// 定義生成的html文件的名稱// template: 'src/index.html'// 定義html模板文件路徑}),// 打包分析插件new BundleWebpackPlugin({})],module:{ rules: [//匹配css的規則{//用于匹配以 .css 結尾的字符串,且匹配時不區分大小寫test: /\.css$/i,//\.轉義'.' ,$匹配字符串的結尾,i 修飾符表示不區分大小寫的匹配/**用于指定處理特定文件類型時使用的 loader。*它是一個數組,可以包含多個 loader,webpack 會從右到左(或從下到上)依次應用這些 loader。*/use: ['style-loader', 'css-loader']// 使用的loader,Loader 從右向左執行,例如 use: ['style-loader', 'css-loader'] 中先執行 css-loader。},//匹配圖片的規則{test:/\.(png|jpg|jpeg|png|gif|svg)$/i,type: 'asset/resource', // 使用資源模塊處理圖片文件,將文件直接輸出到輸出目錄并返回最終的 URL},//匹配js的規則{ test: /\.js$/, // 匹配所有以 .js 結尾的文件exclude: /node_modules/, // 排除 node_modules 目錄下的文件use: {loader: 'babel-loader', // 使用 babel-loader 處理 JavaScript 文件options: {presets: ['@babel/preset-env'] // 使用 @babel/preset-env 預設}}}]},// 開發環境下使用 webpack-dev-server 開啟熱更新,還需要再去package.json中配置相關命令:scripts中添加“"start": "webpack serve --open"”devServer:{// 靜態資源目錄static: "./dist"},resolve:{alias: {// 設置別名,方便在代碼中引用'@': path.resolve(__dirname, 'src'),'@utils': path.resolve(__dirname, 'src/utils'),'@assets': path.resolve(__dirname, 'src/assets')},}// EntryOptionPlugin
}
安裝樣式加載器
在Webpack或Vite等構建工具中配置樣式加載器后方可編譯樣式文件。
npm i style-loader css-loader -D
devtool
devtool 是 webpack 配置中用于控制生成 source map 方式的選項,主要用于調試代碼。source map 可以映射編譯后的代碼回源文件,方便定位問題。
webpack devtool 配置詳解
devtool
是 webpack 配置中用于控制生成 source map 方式的選項,主要用于調試代碼。source map 可以映射編譯后的代碼回源文件,方便定位問題。
常見 devtool 值及適用場景
eval
- 使用
eval
包裹模塊代碼,生成速度最快 - 只能映射到轉換后的代碼,無法映射到源文件
- 適用于開發環境快速構建
module.exports = {devtool: 'eval'
}
eval-source-map
- 每個模塊使用
eval
執行 - 生成完整的 source map 并作為 DataUrl 嵌入
- 構建速度較慢但質量高
- 適用于開發環境需要精確源映射
cheap-eval-source-map
- 類似 eval-source-map 但只映射行號
- 不映射列信息,構建速度更快
- 適用于開發環境折中方案
cheap-module-eval-source-map
- 類似 cheap-eval-source-map
- 但會映射 loader 轉換前的源代碼
- 推薦用于開發環境
source-map
- 生成完整獨立的 source map 文件
- 質量最高但構建速度最慢
- 適用于生產環境調試
module.exports = {devtool: 'source-map'
}
hidden-source-map
- 生成 source map 但不添加引用注釋
- 需要手動處理 source map 文件
- 適用于生產環境但不想暴露源文件
nosources-source-map
- 生成 source map 但不包含源代碼
- 只能看到錯誤堆棧但無法查看代碼
- 適用于生產環境部分保護源代碼
選擇建議
開發環境推薦:
eval-source-map
或cheap-module-eval-source-map
生產環境推薦:
source-map
或hidden-source-map
性能考慮:
- 帶
eval
的選項構建更快 - 帶
module
的選項能映射 loader 前代碼 - 帶
cheap
的選項忽略列映射
性能影響
不同 devtool 設置對構建和重建速度有顯著影響。質量越高的 source map 生成時間越長。開發環境下需要在質量和速度間取得平衡。
// 開發環境推薦配置
module.exports = {devtool: 'cheap-module-eval-source-map',// 其他配置...
}// 生產環境推薦配置
module.exports = {devtool: 'source-map',// 其他配置...
}
注意事項
- 生產環境如需 source map 應考慮安全性
- 某些設置可能導致源文件暴露
- 大型項目應測試不同設置的構建速度
- 現代瀏覽器開發工具已很好支持各種 source map
module
在webpack中,module指的是項目中可被分割的最小功能單位。每個文件(如JavaScript、CSS、圖片等)都被視為一個module,webpack通過分析這些module之間的依賴關系,構建依賴圖(Dependency Graph),最終打包成瀏覽器可識別的靜態資源。
module的類型
webpack支持多種類型的module,常見的有:
- JavaScript模塊:通過import或require導入的JS文件。
- CSS模塊:通過css-loader處理的樣式文件。
- 圖片/字體資源:通過file-loader或url-loader處理的靜態資源。
- 第三方庫:如lodash、jQuery等通過npm安裝的依賴。
處理流程
module的處理流程
- 解析路徑:webpack根據配置的resolve規則解析模塊路徑。
- 匹配規則:通過test正則匹配文件類型,調用對應的loader處理。
- 依賴分析:處理過程中發現新的依賴(如import語句),遞歸處理。
- 打包輸出:最終將所有module合并為bundle文件。
module.rules
module.exports = {module: {rules: [{test: /\.js$/,use: 'babel-loader',exclude: /node_modules/},{test: /\.css$/,use: ['style-loader', 'css-loader']}]}
};
module.use
用于指定處理特定文件類型時使用的 loader。它是一個數組,可以包含多個 loader,webpack 會從右到左(或從下到上)依次應用這些 loader。
常見loader的作用
- babel-loader:將ES6+代碼轉換為ES5。
- css-loader:解析CSS文件中的@import和url()。
- style-loader:將CSS注入到DOM中。
- file-loader:將文件輸出到指定目錄并返回URL。
注意事項
- loader 的執行順序是從右到左(或從下到上),第一個 loader 會將結果傳遞給下一個 loader
- 對于需要選項的 loader,建議使用對象形式配置
- 復雜的 loader 鏈可以拆分成多個規則
- 在生產環境中,可能需要使用 MiniCssExtractPlugin.loader 替代 style-loader
module.type
module.type 用于定義模塊的處理方式。
- asset/resource:專門用于處理文件資源(如圖片、字體等),它會將文件直接輸出到輸出目錄并返回最終的 URL。適用于需要直接引用文件路徑而非文件內容的場景,例如:
- 圖片文件(.png, .jpg, .svg)
- 字體文件(.woff, .ttf)
- 其他靜態資源
- asset/inline:將文件內容作為 Data URL 嵌入(適用于小文件)。
- asset/source:將文件內容作為字符串返回(適用于文本文件)。
- asset:自動選擇 resource 或 inline(默認閾值 8KB)。