webpack-04:打包bundle原理分析和实现

205 阅读1分钟

1、webpack 打包后的结构

打包后是一个自执行函数

(function (module) {
    
    // 模块
    var installedModules = {};
    
    // 这里是webpack定义的各种方法
    
    function __webpack_require__(moduleId) {
      // ....
	}
    // ....
    
    // 加载入口
    return __webpack_require__(__webpack_require__.s = "./src/index.js");
    
})(
    {
        "./src/a.js": function(...) {
            eval('.....')
        },
        "./src/index.js": function(...) {
            eval('.....')
        }
    }
)

我们看看 传入的 module 是一个类似于以下的对象

    {
        "./src/a.js": function(module, __webpack_exports__, __webpack_require__) {
            eval('.....') // 具体文件代码
        },
        "./src/index.js": function(module, __webpack_exports__, __webpack_require__) {
            eval('.....') // 具体文件代码
        }
    }

执行的时候缺少的就是 export 和 require 加载的其他文件的函数

2、首先理解 installedModules

installedModules 是一个对象

{
    [moduleId]: {
        i: moduleId, // 放 id
        l: false, // 是否执行过
        exports: {}, // 执行结果, commonJs 语法都以exports表示导出结果
    }
}

3、首先理解 __webpack_require__ 方法

function __webpack_require__(moduleId) {
  /******/
  // 检验module 是否已被加载过
  if (installedModules[moduleId]) { // 如果存在直接返回导出结果
    return installedModules[moduleId].exports 
  }
  
  // Create a new module (and put it into the cache)
  var module = (installedModules[moduleId] = {
    i: moduleId, // 放 id 都是相对入口的相对路径
    l: false, // 
    exports: {},
  })
  
  /******/
  // 执行 最外层函数传进来的modules的方法
  modules[moduleId].call(
    module.exports,
    module,
    module.exports,
    __webpack_require__
  )
  
  /******/
  // Flag the module as loaded 
  module.l = true
  /******/
  // Return the exports of the module
  return module.exports
}