Webpack打包原理

开门见山。

1、打包单一模块

webpack.config.js

module.exports = {
    entry:"./chunk1.js",
    output: {
        path: __dirname + '/dist',
        filename: '[name].js'
    },
};

chunk1.js

var chunk1=1;
exports.chunk1=chunk1;

那么打包后长什么样子呢?

 (function(modules) { // webpackBootstrap
     // The module cache
     var installedModules = {};
     // The require function
     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] = {
             exports: {},
             id: moduleId,
             loaded: false
         };
         // Execute the module function
         modules[moduleId].call(module.exports, module, module.exports, __webpack_require__);
         // Flag the module as loaded
         module.loaded = true;
         // Return the exports of the module
         return module.exports;
     }


     // expose the modules object (__webpack_modules__)
     __webpack_require__.m = modules;
     // expose the module cache
     __webpack_require__.c = installedModules;
     // __webpack_public_path__
     __webpack_require__.p = "";
     // Load entry module and return exports
     return __webpack_require__(0);
 })([function(module, exports) {
    var chunk1=1;
    exports.chunk1=chunk1;
}]);

好吧,好像废话好多。那么我们来简化一下。
{function(){})([function(){},function(){}])

我们来看匿名函数做了什么:

function(modules) { // webpackBootstrap
     // modules就是一个数组,元素就是一个个函数体,就是我们声明的模块
     var installedModules = {};
     // The require function
     function __webpack_require__(moduleId) {
         ...
     }
     // expose the modules object (__webpack_modules__)
     __webpack_require__.m = modules;
     // expose the module cache
     __webpack_require__.c = installedModules;
     // __webpack_public_path__
     __webpack_require__.p = "";
     // Load entry module and return exports
     return __webpack_require__(0);
 }

整个函数里就是声明了一个变量installedModules和函数webpack_require,并在函数上添加了三个属性module、cache、path,m保存的是传入的数组模块,c保存的时候installedModules的变量,p是一个空字符串。最后执行webpack_require函数,参数为0,并将结果返回。

好,我们来看webpack_require这个函数做了什么事情:

function __webpack_require__(moduleId) {
        //moduleId就是调用是传入的0
         // installedModules[0]是undefined,继续往下
         if(installedModules[moduleId])
             return installedModules[moduleId].exports;
         // module就是{exports: {},id: 0,loaded: false}
         var module = installedModules[moduleId] = {
             exports: {},
             id: moduleId,
             loaded: false
         };
         // 下面接着分析这个
         modules[moduleId].call(module.exports, module, module.exports, __webpack_require__);
         // 表明模块已经载入
         module.loaded = true;
         // 返回module.exports(注意modules[moduleId].call的时候module.exports会被修改)
         return module.exports;
     }

接下来来看一下

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

干了什么:

module就是之前声明的{exports: {},id: 0,loaded: false}
webpack_require就是声明的webpack_require函数
运行后module.exports就是{chunk1:1}(具体如何做到的等会讲)。所以当我们使用chunk1这个模块的时候(比如varchunk1=require(“chunk1”),得到的就是一个对象{chunk1:1})。如果模块里没有exports.chunk1=chunk1或者module.exports=chunk1得到的就是一个空对象{}

2、使用一个模块
上面我们分析了如何打包一个模块,接下来我们分析一下如何使用一个模块。
webpack.config.js

module.exports = {
    entry:"./main.js",
    output: {
        path: __dirname + '/dist',
        filename: '[name].js'
    }
};

main.js

var chunk1=require("./chunk1");
console.log(chunk1);

打包后:

(function (modules) { // webpackBootstrap
    // The module cache
    var installedModules = {};
    // The require function
    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] = {
            exports: {},
            id: moduleId,
            loaded: false
        };
        // Execute the module function
        modules[moduleId].call(module.exports, module, module.exports, __webpack_require__);
        // Flag the module as loaded
        module.loaded = true;
        // Return the exports of the module
        return module.exports;
    }
    // expose the modules object (__webpack_modules__)
    __webpack_require__.m = modules;
    // expose the module cache
    __webpack_require__.c = installedModules;
    // __webpack_public_path__
    __webpack_require__.p = "";
    // Load entry module and return exports
    return __webpack_require__(0);
})([function (module, exports, __webpack_require__) {
    var chunk1=__webpack_require__(1);
    console.log(chunk1);
}, function (module, exports) {
    var chunk1 = 1;
    exports.chunk1 = chunk1;
}]);

不一样的地方就是自执行函数的参数由

[function(module, exports) { 
    var chunk1=1; exports.chunk1=chunk1;
}]

变为

[function (module, exports, __webpack_require__) {
    var chunk1=__webpack_require__(1);
    console.log(chunk1);
}, function (module, exports) {
    var chunk1 = 1;
    exports.chunk1 = chunk1;
}]

其实就是多了一个main模块,不过这个模块没有导出项,而且这个模块依赖于chunk1模块。所以当运行webpack_require(0)的时候,main模块缓存到installedModules[0]上,modules[0].call(也就是调用main模块)的时候,chunk1被缓存到installedModules[1]上,并且导出对象{chunk1:1}给模块main使用

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值