Webpack 是如何工作的?

这是一个极简版的 Webpack 打包原理演示。

为了让你一眼看懂,我去掉了所有复杂的缓存检查、异步加载和辅助函数,只保留最核心的 "模块注册表""require 函数"

🎯 核心逻辑:Webpack 是如何工作的?

Webpack 打包后的本质就是一个 自执行函数(IIFE) ,它做了两件事:

  1. 把所有文件代码存进一个对象里(键是文件名,值是函数)。
  2. 实现一个简单的 require 函数,用来从这个对象里取代码并执行。

💻 简化版 Demo 代码

假设这是 dist/bundle.js 的核心内容:

javascript 复制代码
// ==========================================
// 1. Webpack 启动引导 (Bootstrap)
// ==========================================
(function(modules) { 
  // modules 参数就是下面那个巨大的对象,包含所有文件代码

  // 【核心】模拟 require 函数
  function __webpack_require__(moduleId) {
    // 1. 检查模块是否已经执行过 (缓存),这里简化省略缓存逻辑
    
    // 2. 从 modules 对象中取出对应的模块函数
    var module = modules[moduleId];
    
    // 3. 创建一个空的 exports 对象,用于接收模块导出的内容
    var exports = {};
    
    // 4. 执行模块函数!
    //    把 exports 和 __webpack_require__ 传进去
    //    模块内部通过操作 exports 来导出变量
    module(exports, __webpack_require__);
    
    // 5. 返回导出的内容
    return exports;
  }

  // 【启动】执行入口文件 (假设 index.js 的 ID 是 './src/index.js')
  __webpack_require__('./src/index.js');

})({
  // ==========================================
  // 2. 模块注册表 (所有源文件都在这里)
  // ==========================================
  
  './src/a.js': function(exports, __webpack_require__) {
    // --- 原始代码: export function sayHelloA() ... ---
    
    // Webpack 将 export 转换为对 exports 对象的赋值
    exports.sayHelloA = function() {
      console.log("Hello from A");
    };
  },

  './src/b.js': function(exports, __webpack_require__) {
    // --- 原始代码: export function sayHelloB() ... ---
    
    exports.sayHelloB = function() {
      console.log("Hello from B");
    };
  },

  './src/index.js': function(exports, __webpack_require__) {
    // --- 原始代码: import { sayHelloA } from './a.js' ---
    
    // Webpack 将 import 转换为调用 __webpack_require__
    var a = __webpack_require__('./src/a.js');
    var b = __webpack_require__('./src/b.js');

    // 调用导入的函数
    a.sayHelloA();
    b.sayHelloB();
    
    console.log("App Finished");
  }
});

🔍 原理解析 (3 步走)

第一步:包裹 (Wrap)

Webpack 把你的每个文件 (a.js, b.js, index.js) 都塞进一个函数里。

这个函数接收两个参数:

  • exports: 用来存放你要导出的东西。
  • __webpack_require__: 用来引入别的文件。

第二步:收集 (Collect)

所有包裹好的函数,被放进一个大对象 modules 里。

  • Key: 文件路径 (如 './src/a.js')
  • Value: 包裹后的函数

第三步:执行 (Execute)

  1. Webpack 立即调用最外层的函数,传入 modules 对象。

  2. 它调用 __webpack_require__('./src/index.js') 启动程序。

  3. index.js 运行到 require('./src/a.js') 时:

    • modules 对象里找到 './src/a.js' 对应的函数。
    • 创建一个空对象 {} 作为 exports
    • 执行 该函数,此时 exports 被填入了 sayHelloA
    • 把填好的 exports 返回给 index.js
  4. 最终,所有依赖按顺序执行完毕。

🚀 总结

Webpack 并没有真的让浏览器支持 import/export,它是通过闭包和对象映射,在浏览器里"模拟"了一套 CommonJS 风格的模块系统

  • 源码 : import a from './a'
  • 打包后 : var a = __webpack_require__('./src/a.js')

这就是模块化打包的魔法所在。

相关推荐
放下华子我只抽RuiKe56 小时前
FastAPI 全栈后端(三):数据库与 ORM
前端·数据库·react.js·oracle·性能优化·前端框架·fastapi
梵得儿SHI6 小时前
Vue 项目实战与性能优化全攻略:从代码、渲染到首屏,一站式解决卡顿慢加载
前端·vue.js·性能优化·vite·前端面试·前端优化·首屏优化
ShyanZh6 小时前
【skill】HTML PPT Skill:用 Claude Code 一句话生成专业演示文稿
前端·ai·html·powerpoint·skill
AI视觉网奇6 小时前
three教学 3d资产拼接源代码
前端·css·css3
程序猿阿伟7 小时前
《Chrome标签组搭建多任务高效浏览指南》
前端·chrome
2601_958352907 小时前
双麦 DSP 音频模块实战:一文梳理 A-68 在全行业场景的声学解决方案与落地要点
前端·嵌入式硬件·音视频·语音识别·降噪消回音·音频处理模块
智码看视界8 小时前
老梁聊全栈:JavaScript 原型链深入探索对象继承的奥秘
前端·javascript·ecmascript
布朗克1688 小时前
39 Spring Boot Web实战
前端·spring boot·后端·实战
纽格立科技8 小时前
DRM 发射端链路图(上)
前端·人工智能·车载系统·信息与通信·传媒
云水一下8 小时前
Vue.js从零到精通系列(七):高级特性实战——Teleport、异步组件、自定义指令与TypeScript深度结合
前端·vue.js·typescript