webpack模块加载介绍

本文深入剖析webpack的模块加载过程,通过实例代码展示了webpack如何通过__webpack_require__函数递归加载模块,并缓存已加载模块以避免重复加载。

根据第一篇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才可以被外部获取就非常好理解了:)

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值