webpack打包的基础原理-打包后的文件解读

1、概念

  本质上,webpack 基于node平台,利用 node 的各种api来实现 javascript 应用程序的一个静态模块的打包工具。

  在打包过程中,构建依赖关系,并且实现模块引用预处理,以及缓存等。

2、分析

  

  1、人口文件

// mian.js
const a = require('./m1')
const b= require('./m2')
import { test } from './m1'
console.log(test)

  

//m2.js
export default {
  b:2
}

  

//m1.js
export const test = {test:1}
export default {
  a:1
}

  

  2、生产的文件

(function (modules) {
  var installedModules = {}; //缓存
  /*
  * 加载模块函数
  * 传入模块id
  * */
  function __webpack_require__(moduleId) {
    // 检查缓存中是否有模块
    if (installedModules[moduleId]) {
      return installedModules[moduleId].exports;
    }
    // 创建一个新模块,并缓存起来
    var module = installedModules[moduleId] = {
      i: moduleId,
      l: false,
      exports: {}
    };
    // 调模块的函数,modules
    modules[moduleId].call(module.exports, module, module.exports, __webpack_require__);
    module.l = true;
    // 返回对应模块
    return module.exports;
  }
  __webpack_require__.m = modules;
  __webpack_require__.c = installedModules;
  __webpack_require__.d = function (exports, name, getter) {
    if (!__webpack_require__.o(exports, name)) {
      Object.defineProperty(exports, name, {
        configurable: false,
        enumerable: true,
        get: getter
      });
    }
  };
  __webpack_require__.n = function (module) {
    var getter = module && module.__esModule ?
      function getDefault() {
        return module['default'];
      } :
      function getModuleExports() {
        return module;
      };
    __webpack_require__.d(getter, 'a', getter);
    return getter;
  };
  __webpack_require__.o = function (object, property) {
    return Object.prototype.hasOwnProperty.call(object, property);
  };
  __webpack_require__.p = "";

  // 加载入口文件
  return __webpack_require__(__webpack_require__.s = 0);
})
([
  (function (module, exports, __webpack_require__) {
    const a = __webpack_require__(1)
    const b = __webpack_require__(2)
  }),
  (function (module, __webpack_exports__, __webpack_require__) {
    "use strict";
    Object.defineProperty(__webpack_exports__, "__esModule", {value: true});
    __webpack_exports__["default"] = ({
      a: 1
    });
  }),
  (function (module, __webpack_exports__, __webpack_require__) {
    "use strict";
    Object.defineProperty(__webpack_exports__, "__esModule", {value: true});
    __webpack_exports__["default"] = ({
      b: 2
    });
  })
]);

  

  观察以上代码得到结果:

  1、打包后的代码是一个立即执行函数,且传入的参数为一个数组

  2、参数数组就是我们引用的模块

  3、每一个模块对应着数组的位置就是那么的id

  4、在立即函数中加载入口文件,并执行

  __webpack_require__ : 加载并执行某一个模块并将模块缓存在 installedModules 中。

modules[moduleId].call(module.exports, module, module.exports, __webpack_require__);

  这里是执行引用的某一个模块。

  并将module,exports,require 加入模块中。

  这也是为什么我们在模块中有全局变量 module/exports/require

  通过对打包后的文件分析,基本可以完全理解打包过程。