美文网首页
理解 webpack编译后的文件

理解 webpack编译后的文件

作者: 别过经年 | 来源:发表于2021-01-26 16:24 被阅读0次

以webpack@4.46.0 官网首页的代码为例,分析webpack编译为web环境的代码(webpack默认构建目标为web)
总观,编译后的代码为立即执行函数


立即执行函数

函数的参数为对象,对象的key就是两个文件的相对路径,value为函数index.js 跟bar.js放在eval内,为了方便阅读把eval中的函数拿出来

{
  "./src/bar.js": function barWrapper(
    module,
    __webpack_exports__,
    __webpack_require__
  ) {
    __webpack_require__.r(__webpack_exports__);
    __webpack_require__.d(__webpack_exports__, "default", function () { // 将bar函数挂载到__webpack_require__中定义的exports对象上,从而保证被调用模块可以拿到bar函数
      return bar;
    });
    function bar() {
      console.info("xx");
    }
  },
  "./src/index.js": function indexWrapper(
    module,
    __webpack_exports__,
    __webpack_require__
  ) {
    __webpack_require__.r(__webpack_exports__);
    var _bar__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__("./src/bar.js");
    Object(_bar__WEBPACK_IMPORTED_MODULE_0__["default"])();
  },
};

__webpack_require__的定义

  function __webpack_require__(moduleId) {
    // Check if module is in cache
    if (installedModules[moduleId]) {
      return installedModules[moduleId].exports;
    } // Create a new module (and put it into the cache)
    var module = (installedModules[moduleId] = {
      i: moduleId,
      l: false,
      exports: {}, // 定义exports空对象
    }); // Execute the module function

    modules[moduleId].call(
      module.exports,
      module,
      module.exports, // 将exports
      __webpack_require__
    ); // Flag the module as loaded

    module.l = true; // Return the exports of the module

    return module.exports; // 返回exports对象
  } // expose the modules object (__webpack_modules__)

__webpack_require__.d 用来在exports对象上定义属性

  __webpack_require__.d = function (exports, name, getter) {
    if (!__webpack_require__.o(exports, name)) {
      Object.defineProperty(exports, name, {
        enumerable: true,
        get: getter,
      });
    }
  }; // define __esModule on exports

exports 在__webpack_require__函数中生成,每执行一次__webpack_require__函数也就是用__webpack_require__调用一次模块,exports都是新的对象(即__webpack_exports__

总结:
__webpack_require__函数中定义exports对象,根据moduleId去调用对应的模块,将_webpack_require__函数传入模块,从而保证该模块可以调用其他模块,也将__webpack_exports__传入模块,从而将模块中定义的函数变量挂载到__webpack_require__定义的exports对象中,从而在调用__webpack_require__模块的地方可以拿到被调用模块内定义的变量跟函数。这么理解下来可以知道,__webpack_require__传递到每个模块是必要的,但是为啥要将__webpack_exports__每个模块,完全可以在每个模块中定义一个对象返回出来,这样调用者就可以拿到被调用模块的变量 函数了。不是很明白,有清楚的,可以告知

看完代码也可以回答一个问题:webpack是怎样实现模块的依赖的?
将文件的相对路径作为模块的id ,通过最外层的立即执行函数避免模块内变量污染全局,用_webpack_require__函数来实现模块的相关引用,每个模块都是包裹在函数里,通过传入的__webpack_exports__对象将模块内的变量函数暴露给调用模块,最终调用模块就可以拿到被调用模块内部的函数 变量了。说白了就是用函数从模拟模块,将每个模块的代码包裹在一个函数内,通过__webpack_exports__将其暴露给调用模块。

相关文章

网友评论

      本文标题:理解 webpack编译后的文件

      本文链接:https://www.haomeiwen.com/subject/apvgzktx.html