webpack本质原理快速入门

32 阅读2分钟

webpack本质原理简单入门

首先这边只谈论最纯粹的webpack不带任何 loader / plugin

但webpack本身原理是非常简单的,我们可以直接将划分为四个模块的功能:

  • 依赖分析(Dependency Analysis)​
  • 作用域隔离(Scope Isolation)​
  • 模块系统模拟(Module System Simulation)
  • 基础打包输出(Basic Bundling)

四大核心能力详解

1. 依赖分析(Dependency Analysis)
  • 做什么
    从入口文件开始,递归分析所有 import/require 语句,构建完整的依赖关系图。
  • 示例
    // a.js
    import { b } from './b.js';
    import { c } from './c.js';
    
    // b.js
    import { d } from './d.js';
    
    → 生成依赖图谱:
    graph TD
      A[a.js] --> B[b.js]
      A --> C[c.js]
      B --> D[d.js]
    
2. 作用域隔离(Scope Isolation)
  • 解决问题:避免模块间变量污染。
  • 实现方式
    每个模块的代码会被包裹到一个函数闭包中:
    // 原始模块
    const name = 'a';
    export default name;
    
    // 打包后
    function(module, exports) {
      const name = 'a';
      exports.default = name;
    }
    
3. 模块系统模拟(Module System Simulation)
  • 关键函数__webpack_require__
    模拟 Node.js 的 require 和 ES Module 的 import
    // 模拟的模块缓存
    const cache = {};
    
    function __webpack_require__(moduleId) {
      if (cache[moduleId]) return cache[moduleId];
      
      const module = { exports: {} };
      // 执行模块代码(闭包)
      modulesmodule, module.exports, __webpack_require__;
      cache[moduleId] = module.exports;
      return module.exports;
    }
    
4. 基础打包输出(Basic Bundling)
  • 输出结构
    将所有模块闭包存入一个对象,通过 __webpack_require__ 启动入口:
    (function(modules) {
      // 模块系统实现...
    })({
      "./a.js": function(module, exports, __webpack_require__) { /* a.js 代码 */ },
      "./b.js": function(module, exports, __webpack_require__) { /* b.js 代码 */ }
    });
    

纯手工实现模拟

1. 原始文件

src/index.js

import { message } from './message.js';
console.log(message);

src/message.js

export const message = 'Hello';
2. 模拟 Webpack 打包结果
// dist/bundle.js
(function(modules) {
  const cache = {};
  
  function require(moduleId) {
    if (cache[moduleId]) return cache[moduleId];
    
    const module = { exports: {} };
    modulesmodule, module.exports, require;
    cache[moduleId] = module.exports;
    return module.exports;
  }

  // 执行入口模块
  require("./src/index.js");
})({
  "./src/index.js": function(module, exports, require) {
    const { message } = require("./src/message.js");
    console.log(message);
  },
  
  "./src/message.js": function(module, exports) {
    exports.message = 'Hello';
  }
});
3. 注意点
  • 变量隔离message.js 中的 message 不会污染全局
  • 依赖管理:通过 require 函数精准定位模块
  • 缓存机制:重复引入同一模块时直接读取缓存

如何验证

我们可以直接用webpack打包,然后查看打包后的文件是否与我们手工模拟的结果是否基本一致。

1. 安装 Webpack
npm install webpack webpack-cli --save-dev
2. 配置 Webpack

webpack.config.js

module.exports = {
  mode: 'development',
  devtool: false // 关闭 SourceMap 更清晰看代码
};
3.执行查看
npx webpack