Webpack 核心原理剖析

時至今日,Webpack 已迭代到 5.x 版本,其功能模塊的擴充和復雜度的提升使得源碼學習成本陡增。官方文檔的晦澀表述更是讓許多開發者望而卻步。然而,理解 Webpack 的核心原理對優化構建流程、定制化打包方案至關重要。本文將通過簡化流程和代碼示例,剖析 Webpack 的運作機制,幫助讀者從本質層面掌握其核心能力,突破“配置工程師”的局限。

Webpack 的核心能力

Webpack 本質上是一個 JavaScript 應用程序的靜態模塊打包器。它將應用程序中的資源(JS、CSS、圖片等)視為模塊,分析依賴關系后打包成靜態資源文件,官網的動畫就能很好的詮釋這一點。

請添加圖片描述

其核心能力可概括為:

  1. 模塊化整合:將分散的代碼按依賴關系組織成 chunk。
  2. 資源轉換:通過 Loader 系統處理非 JS 文件。
  3. 擴展性:通過 Plugin 系統在構建生命周期中注入自定義邏輯。

基礎使用

初始化項目

npm init -y
npm install webpack webpack-cli --save-dev

目錄結構

├── package.json
├── webpack.config.js   # 配置文件
└── src├── index.js        # 入口文件├── a.js└── b.js

webpack.config.js

module.exports = {mode: "development",   // 開發模式(不壓縮代碼)entry: "./src/index.js",devtool: "source-map"  // 生成源碼映射
};

src/index.js

console.log("index module");
const a = require('./a.js');
console.log(a);

src/a.js

console.log("a module");
const b = require('./b.js');
console.log(b);
module.exports = 'a';

src/b.js

console.log("b module");
module.exports = 'b';

打包結果分析

執行 npx webpack 后生成的 dist/main.js

(() => {// 初始化、定義了一個模塊對象,key為模塊的路徑,value函數里面的內容就是我們書寫的模塊的代碼var __webpack_modules__ = ({"./src/a.js": ((module, __unused_webpack_exports, __webpack_require__) => {console.log("a module");const b = __webpack_require__("./src/b.js");console.log(b);module.exports = 'a';}),"./src/b.js": ((module) => {console.log("b module");module.exports = 'b';})});// 模塊緩存var __webpack_module_cache__ = {};// 定義__webpack_require__函數,就是我們在代碼中使用的require函數function __webpack_require__(moduleId) {// 查找緩存中是否有該模塊var cachedModule = __webpack_module_cache__[moduleId];if (cachedModule !== undefined) {return cachedModule.exports;}var module = __webpack_module_cache__[moduleId] = {exports: {}};__webpack_modules__[moduleId](module, module.exports, __webpack_require__);return module.exports;}// 入口文件 src/index.js(() => {console.log("index module");const a = __webpack_require__(/*! ./a.js */ "./src/a.js");console.log(a);})();
})()

打包后的核心內容包含:

  1. 模塊映射表:以路徑為 key,模塊代碼為 value。
  2. 模塊緩存:避免重復加載。
  3. require 函數:實現模塊依賴解析。
  4. 入口執行邏輯:立即執行入口模塊代碼。

那核心問題來了,Webpack 是如何將我們的源代碼打包成 dist/main.js 的?

Webpack 的工作流程

Webpack 的進行打包的工作流程可以分為三個主要階段:

  1. 初始化階段:合并配置,創建 Compiler 對象,加載插件。
  2. 編譯階段:從入口遞歸分析依賴,構建模塊依賴圖。
  3. 輸出階段:按 chunk 生成文件并寫入磁盤。

請添加圖片描述

初始化階段

初始化階段是 Webpack 打包流程的起點,關鍵步驟

  1. 合并配置(CLI 參數 + 配置文件 + 默認配置)。
  2. 創建 Compiler 對象(核心控制器)。
  3. 加載插件并綁定生命周期鉤子。

編譯階段

編譯階段是 Webpack 處理模塊的核心階段,核心過程

  1. 模塊轉譯:Loader 將非 JS 文件轉為 JS,生成 AST。
  2. 依賴分析:遍歷 AST 提取模塊依賴,遞歸處理。
  3. 生成模塊表:記錄模塊代碼、依賴關系和唯一 ID。
// 編譯后的模塊表示例
const modules = [{id: "./src/a.js",dependencies: ["./src/b.js"],code: `/* 轉換后的代碼 */`}
];

編譯流程圖

請添加圖片描述

輸出階段

輸出階段是 Webpack 打包流程的最后階段,主要包括以下步驟:

  1. 生成 chunk:按入口和動態導入規則拆分模塊。
  2. 資源封裝:將 chunk 轉為包含運行時邏輯的 IIFE 函數。
  3. 文件寫入:根據輸出配置生成最終文件。

經過這三個階段,Webpack 就實現了將我們的源代碼打包成了最終的工程文件了。

但是在構建的整個過程中,由于瀏覽器只能認識** html、css、js** 這幾種格式的文件,所以需要對其他格式的文件進行轉換,這個就需要一個工具來實現,就是 Loader 系統

Loader 系統

Loader系統可以將非 JS 文件(如 CSS、圖片)轉換為 Webpack 可識別的模塊,從而納入到 Webpack 的打包流程中。

請添加圖片描述

Loader 的工作原理

Loader 通過定義一個函數,將輸入的內容轉換為輸出的內容。Webpack 會將 Loader 鏈式調用,每個 Loader 處理完內容后,會將結果傳遞給下一個 Loader,直到鏈尾。
Loader 的基本結構如下:

module.exports = function (content) {// 處理內容return processedContent;
};

在 Webpack 配置中,可以通過 module.rules 來指定 Loader:

module.exports = {module: {rules: [{test: /\.js$/,use: 'babel-loader',},{test: /\.scss$/,use: ['style-loader', 'css-loader', 'sass-loader'],},],},
};

在這個配置中,test 指定了要匹配的文件類型,use 指定了要使用的 Loader 。當 Webpack 處理文件時,會根據文件類型選擇對應的 Loader 鏈來處理文件。

除了文件轉換之外,Webpack 也需要在特定時機進行一些處理,這個時候需要一個接口的設計,就是 Plugin 系統

Plugin 系統

Plugin 系統是 Webpack 功能擴展的重要機制。通過 Plugin,開發者可以實現各種功能,如代碼壓縮、提取 CSS、生成 HTML 等。

Plugin的工作原理

Plugin 通過監聽 Webpack 的生命周期事件,在特定的時機介入編譯過程。Webpack 提供了豐富的鉤子(hooks),Plugin 可以通過注冊這些鉤子來實現功能擴展。

請添加圖片描述

Plugin 的基本結構如下:

class SomePlugin {apply(compiler) {// 注冊鉤子compiler.hooks.someHook.tap('SomePlugin', () => {// 實現插件功能});}
}

apply 函數中,Plugin 可以通過 compiler.hooks 訪問各種鉤子,并注冊回調函數。當 Webpack 執行到對應的生命周期階段時,會觸發這些鉤子,從而執行 Plugin 的功能。

總結

Webpack 的核心原理可歸結為模塊化依賴分析資源整合。通過理解其工作流程的三階段(初始化、編譯、輸出),開發者能更高效地配置優化策略,定制 Loader/Plugin 解決個性化需求。

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/bicheng/96260.shtml
繁體地址,請注明出處:http://hk.pswp.cn/bicheng/96260.shtml
英文地址,請注明出處:http://en.pswp.cn/bicheng/96260.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

移植Qt4.8.7到ARM40-A5

移植Qt4.8.7到ARM40-A5 主機平臺:Ubuntu 16.04 LTS(x64) 目標平臺:ARM40-A5 Qt版本:Qt4.8.7 ARM GCC編譯工具鏈: arm-2014.05-29-arm-none-linux-gnueabi-i686-pc-linux-gnu.tar.bz2 ----------## Qt移植步驟 ## 1、了解Ubuntu&am…

C++_哈希

1. unordered系列關聯式容器在C98中,STL提供了底層為紅黑樹結構的一系列關聯式容器,在查詢時效率可達到$log_2 N$,即最差情況下需要比較紅黑樹的高度次,當樹中的節點非常多時,查詢效率也不理想。最好 的查詢是&#xf…

Redis 內存管理機制:深度解析與性能優化實踐

🧠 Redis 內存管理機制:深度解析與性能優化實踐 文章目錄🧠 Redis 內存管理機制:深度解析與性能優化實踐🧠 一、Redis 內存架構全景💡 Redis 內存組成結構📊 內存占用分布示例?? 二、內存分配…

cargs: 一個輕量級跨平臺命令行參數解析庫

目錄 1.簡介 2.安裝與集成 3.項目的目錄結構及介紹 4.核心數據結構與函數 5.基本使用示例 6.應用案例和最佳實踐 7.高級用法 8.與其他庫的對比 9.總結 1.簡介 cargs 是一個輕量級、無依賴的 C 語言命令行參數解析庫,雖然本身是 C 庫,但可以無縫…

【數學建模】質量消光系數在煙幕遮蔽效能建模中的核心作用

前言:歡迎各位光臨本博客,這里小編帶你直接手撕質量相關系數,文章并不復雜,愿諸君耐其心性,忘卻雜塵,道有所長!!!! **🔥個人主頁:IF’…

Java代碼審計實戰:XML外部實體注入(XXE)深度解析

Java代碼審計實戰:XML外部實體注入(XXE)深度解析XML外部實體注入(XXE)是Web應用程序中一種常見但又常常被忽視的漏洞。它利用了XML解析器解析XML文檔時,允許引用外部實體這個特性。如果解析器沒有禁用外部實…

當服務器出現網卡故障時如何檢測網卡硬件故障并解決?

當服務器出現網卡故障時,可能導致網絡通信中斷,從而影響業務的正常運行。以下是檢測網卡硬件故障、診斷問題并解決的詳細方法和步驟。1. 網卡故障的常見表現1.1 硬件故障的常見癥狀網絡無法連接:服務器無法訪問外部網絡或用戶無法連接到服務器…

從車輛中心到用戶中心:E/E架構的變革與挑戰

我是穿拖鞋的漢子,魔都中堅持長期主義的汽車電子工程師。 老規矩,分享一段喜歡的文字,避免自己成為高知識低文化的工程師: 做到欲望極簡,了解自己的真實欲望,不受外在潮流的影響,不盲從,不跟風。把自己的精力全部用在自己。一是去掉多余,凡事找規律,基礎是誠信;二是…

RPC內核細節(轉載)

RPC內核細節(轉載) 背景 隨著數據量、并發量、業務復雜度的增長,服務化是架構演進必由之路。服務化離不開RPC框架。 RPC服務化的好處 服務化的一個好處就是,不限定服務的提供方使用什么技術選型,能夠實現大公司跨團隊的技術解耦。 如下圖…

SpringAMQP 的發布方確認

前言 這里的發布方確認是以 SpringAMQP 寫的,之前我們在前面的篇章中就學過了 使用 Java 原生的SDK編寫,當時是發布確認模式,在這里我們將用 Spring 集成的 rabbitmq 方法來編寫 開啟發布者確認機制需要進行下面的配置,以 yml 為例…

一套自用的git提交規范,可清晰的識別到關聯的任務/bug

分享一套自用的git提交規范&#xff0c;可清晰的識別到關聯的任務/bug 一、提交信息的基本結構 推薦使用約定式提交的一種變體&#xff0c;結構如下&#xff1a; <類型>(<范圍>): <主題> [#<禪道-ID>]<正文>&#xff08;可選&#xff09;<腳注…

從音頻到文本實現高精度離線語音識別

會議頻繁&#xff0c;記錄繁瑣&#xff1f;語音轉換成文字工具價格高昂&#xff0c;自己手動整理又耗時費力&#xff1f; 它支持本地離線運行&#xff0c;無需聯網&#xff0c;所有數據留在本地&#xff0c;隱私安全毫無顧慮&#xff0c;同時它的功能是實時語音轉文字&#xf…

SpringMVC 工作原理

SpringMVC 工作原理 SpringMVC 是 Spring 框架中用于構建 Web 應用的核心模塊&#xff0c;其工作流程圍繞 “前端控制器&#xff08;DispatcherServlet&#xff09;” 展開&#xff0c;通過組件間的協作完成請求處理與響應。理解其工作原理是掌握 SpringMVC 開發的關鍵&#xf…

HoRain云--Python機器學習神器:Sklearn全解析

&#x1f3ac; HoRain云小助手&#xff1a;個人主頁 &#x1f525; 個人專欄: 《Linux 系列教程》《c語言教程》 ??生活的理想&#xff0c;就是為了理想的生活! ?? 推薦 前些天發現了一個超棒的服務器購買網站&#xff0c;性價比超高&#xff0c;大內存超劃算&#xff01;…

瘋狂星期四文案網第64天運營日記

網站運營第64天&#xff0c;點擊觀站&#xff1a; 瘋狂星期四 crazy-thursday.com 全網最全的瘋狂星期四文案網站 運營報告 今日訪問量 今日搜索引擎收錄情況

設計一個 AB 測試平臺

1. 需求明確化 功能需求實驗管理 創建、編輯、刪除、復制實驗設置實驗參數&#xff08;變體、權重、目標指標、時長等&#xff09;實驗狀態管理&#xff08;草稿、運行中、已結束&#xff09;用戶分流與分配 支持多種分流策略&#xff08;隨機分配、分層分配、定向分配&#xf…

HiCMAE 論文復現:基于 RAVDESS 數據集的音視頻情感識別

HiCMAE 論文復現:基于 RAVDESS 數據集的音視頻情感識別 1. 項目背景與論文概述 1.1 多模態情感識別背景 多模態情感識別是人工智能領域的重要研究方向,旨在通過結合多種感知模態(如音頻、視頻、文本等)來更準確地識別人類情感狀態。與傳統單模態方法相比,多模態方法能夠…

HarmonyOS 數據處理性能優化:算法 + 異步 + 分布式實戰

摘要 不管是寫 App&#xff0c;還是做 IoT 設備開發&#xff0c;數據處理都是繞不開的主題。你可能要處理幾百條傳感器數據&#xff0c;也可能要應對幾十萬條用戶行為日志。如果算法不夠高效&#xff0c;應用就會卡頓甚至直接崩潰。尤其是在 HarmonyOS&#xff08;鴻蒙系統&…

華為麒麟操作系統運維常見知識點

1.開放root賬號密碼登錄。(1)修改/etc/ssh/sshd_config文件中&#xff0c;PermitRootLogin 屬性值為yes。PermitRootLogin yes(2)使用passwd命令設置root密碼。sudo su 切換到root賬戶下&#xff0c;使用passwd 設置密碼。(3)重啟sshd服務。systemctl restart sshd2.避免使用ch…

嵌入式面試|MCU+RTOS技術棧——面試八股文整理3:STM32

目錄 1.單片機啟動流程 2.看門狗 3.最小系統 4.ROM、RAM、Flash 5.EPROM、EEPROM 6.Bootloader與OTA 7.NAND FLASH 和NOR FLASH 相同點 區別 適用場景 8.CPU、MPU、MCU、SOC、SOPC 9.交叉編譯 10.寄存器 寄存器的作用 寄存器與內存的區別 11.Cortex-M3寄存器組…