根据第一篇webpack简介的简单介绍,简要分析了一下webpack函数模块加载机制。我们先看一下如下代码,也是webpack简介中编译之后的dest.js文件。
/**
* webpack启动函数.
*
* @param {Array} modules
*/
/******/ (function(modules) { // webpackBootstrap
/******/ // 缓存模块
/******/ var installedModules = {};
/******/
/**
* webpack函数加载模块,核心代码,根据模块id加载相应模块的exports函数.
*
* @param {string} moduleId
*/
/******/ function __webpack_require__(moduleId) {
/******/
/******/ // 检查模块是否已经加载
/******/ if(installedModules[moduleId]) {
// 如果已经加载返回该模块的exports函数
/******/ return installedModules[moduleId].exports;
/******/ }
/******/ // 模块未加载,创建新模块,并且把模块加入缓存
/******/ var module = installedModules[moduleId] = {
/******/ i: moduleId, // 模块id
/******/ l: false, // load,是否加载,默认为false
/******/ exports: {} // 模块导出函数,默认为空对象
/******/ };
/******/
/******/ // 根据模块id调用入参中传入的模块函数,关键核心代码,
// 如果该模块中还存在未加载的依赖模块,则会递归调用__webpack_require__进行加载
/******/ modules[moduleId].call(module.exports, module, module.exports, __webpack_require__);
/******/
/******/ // 标记本模块为已加载
/******/ module.l = true;
/******/
/******/ // 返回模块导出函数
/******/ return module.exports;
/******/ }
/******/
/******/
/******/ // 暴露模块函数的对象(__webpack_modules__)
/******/ __webpack_require__.m = modules;
/******/
/******/ // 暴露缓存的模块
/******/ __webpack_require__.c = installedModules;
/******/
/******/ // identity function for calling harmony imports with the correct context
/******/ __webpack_require__.i = function(value) { return value; };
/******/
/******/ // define getter function for harmony exports
/******/ __webpack_require__.d = function(exports, name, getter) {
/******/ if(!__webpack_require__.o(exports, name)) {
/******/ Object.defineProperty(exports, name, {
/******/ configurable: false,
/******/ enumerable: true,
/******/ get: getter
/******/ });
/******/ }
/******/ };
/******/
/******/ // getDefaultExport function for compatibility with non-harmony modules
/******/ __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;
/******/ };
/******/
/******/ // Object.prototype.hasOwnProperty.call
/******/ __webpack_require__.o = function(object, property) { return Object.prototype.hasOwnProperty.call(object, property); };
/******/
/******/ // __webpack_public_path__
/******/ __webpack_require__.p = "";
/******/
/******/ // 加载入口模块,并且返回exports函数
/******/ return __webpack_require__(__webpack_require__.s = 2);
/******/ })
/************************************************************************/
/******/ ([
/* 0 */
/***/ (function(module, exports) {
/**
* Created by Administrator on 2017/5/30.
*/
module.exports.say = function () {
console.log('foot say function')
}
/***/ }),
/* 1 */
/***/ (function(module, exports) {
/**
* Created by Administrator on 2017/5/30.
*/
module.exports = function () {
console.log('head module')
}
/***/ }),
/* 2 */
/***/ (function(module, exports, __webpack_require__) {
/**
* Created by Administrator on 2017/5/30.
*/
var head = __webpack_require__(1)
var foot = __webpack_require__(0)
head();
foot.say();
/***/ })
/******/ ]);
这个函数初看觉得貌似很复杂,特别是项目开发代码都加载上去的时候,实际上可以简化成如下形式:
(function (modules) {
// webpack 启动函数
// webpack加载模块函数 等等。。。
})([
(function (module, exports) {
// 依赖的函数1
}),(function (module, exports) {
// 依赖的函数2
}),(function (module, exports, __webpack_require__) {
// 入口函数,app.js
})
])
本质上是一个立即执行的函数,传入的参数为各个被包裹的依赖模块,最后一个函数一般包裹的是入口文件,如果加载的模块中存在对其他模块的依赖关系,则入参会多接收一个webpack_require参数,用于在模块函数中获取依赖模块的exports函数。
现在再回头看接口暴露函数module.exports才可以被外部获取就非常好理解了:)
本文深入剖析webpack的模块加载过程,通过实例代码展示了webpack如何通过__webpack_require__函数递归加载模块,并缓存已加载模块以避免重复加载。

1625

被折叠的 条评论
为什么被折叠?



