当前位置: 首页 > 工具软件 > KV.JS > 使用案例 >

深入理解webpack打包bundle.js的机制

纪秋月
2023-12-01

本文通过实际打包查看bundle.js的源码的方式来理解webpack的打包输出。

项目目录如下:

+ index.js
+ package.json
+ webpack.config.js


其中webpack.config.js的配置如下

const path = require('path');
module.exports = {
  entry: './index.js',
  mode: 'development',
  output: {
    path: path.resolve(__dirname, 'dist'),
    filename: 'bundle.js',
    library: 'demo',
    libraryTarget: 'umd'
  },
}


index.js来模拟一个需要导出的包。并使用了esmodule的方式导出。

function demo() {
  console.log('this is demo');
}

export default demo;


以上的配置是希望打包出一个支持umd模块规范的lib库。执行webpack打包出了./dist/bundle.js,最好配合node中commonjs的规范对比理解。

我这里先把commonjs执行的过程列一下,详细见这里

// 1. 检查 Module._cache,是否缓存之中有指定模块
// 2. 如果缓存之中没有,就创建一个新的Module实例
// 3. 将它保存到缓存
// 4. 使用 module.load() 加载指定的模块文件,
// 读取文件内容之后,使用 module.compile() 执行文件代码
// 5. 如果加载/解析过程报错,就从缓存删除该模块
// 6. 返回该模块的 module.exports

打包出的文件源码内容摘略如下,请仔细看注释。

// umd规范
(function webpackUniversalModuleDefinition(root, factory) {
    // commonjs2
    if(typeof exports === 'object' && typeof module === 'object')
        module.exports = factory();
    // amd
    else if(typeof define === 'function' && define.amd)
        define([], factory);
    // commonjs
    else if(typeof exports === 'object')
        exports["demo"] = factory();
    else
    // 注入到全局
        root["demo"] = factory();
})(self, function() {
return /******/ (() => { // webpackBootstrap
/******/     "use strict";
/******/     var __webpack_modules__ = ({
// index.js 即为需要导出的模块,可以看出这就是一个kv组成的模块的map
/***/ "./index.js":
/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => {
        eval("...")
      })
          });
          // 如同nodejs的commonjs,webpack也会缓存已经加载的模块。
          var __webpack_module_cache__ = {};
/******/     
/******/     // The require 函数
/******/     function __webpack_require__(moduleId) {
/******/         // 检查是否在缓存中
/******/         if(__webpack_module_cache__[moduleId]) {
/******/             return __webpack_module_cache__[moduleId].exports;
/******/         }
/******/         // 创建一个新的模块并放入到缓存,其实可以看出只是一个对象字面量
/******/         var module = __webpack_module_cache__[moduleId] = {
/******/             // no module.id needed
/******/             // no module.loaded needed
/******/             exports: {}
/******/         };
/******/     
/******/         // 执行Module中的代码
/******/         __webpack_modules__[moduleId](module, module.exports, __webpack_require__);
/******/     
/******/         // 导出模块。
/******/         return module.exports;
/******/     }
            // 运行入口文件,并导出
/******/     return __webpack_require__("./index.js");
/******/ })()
;
});


可以看出,几乎就是Node.js commonjs规范的浏览器实现。可参考阮一峰的模块加载机制进行对比。这样相互印证,更好去理解和记忆。

 类似资料: