webpack编译结果分析

667 阅读2分钟

合并

webpack 模块化中的各个模块的代码不会污染全局

webpack在打包时通过入口文件将所有需要加载的模块合并到一个js文件中,把每一个模块的代码放到函数中,通过函数作用域的方式解决模块化中的代码污染全局。

// a.js
console.log('module a');
module.exports.a = '123'
console.log(this); // module.export
// 入口文件 index.js
console.log('index module');
var { a } = require('./a');
console.log(a);

合并之后生成的模块,key是模块的路径,value是一个函数,函数中是该模块的代码

// module
{
    './src/index.js': function (module, exports, require) {
        console.log('index module');
        var { a } = require('./a');
        console.log(a);
    },
    './src/a.js': function (module, exports, require) {
        console.log('module a');
        module.exports.a = 'a';
        console.log(this); // module.export
    },
}

执行

webpack会将代码放到立即执行函数中执行(避免全局污染),重写了require函数=__webpack_require

代码会先执行__webpack_require 加载入口文件的函数并执行,这个函数相当于运行一个模块,并得到模块的导出结果。将函数所需要的参数都是提前定义好的变量和函数,最后将该模块导出的数据返回,返回的模块数据会返回到require执行的位置。

(function (modules) {
    // __webpack_require 函数相当于运行一个模块,得到模块的导出结果。
    function __webpack_require(moduleId) {
        var func = modules[moduleId]; // 得到该模块对应的函数
        var module = {
            exports: {}
        };
        func.call(module.exports, module, module.exports, __webpack_require);
        return module.exports;
    }

    __webpack_require('./src/index.js'); // __webpack_require 函数相当于运行一个模块,得到模块的导出结果。
})({
    './src/index.js': function (module, exports, require) {
        console.log('index module');
        var { a } = require('./src/a.js'); // {a: 'a'} 这里会调用__webpack_require 并返回这个模块导出的结果
        console.log(a);
    },
    './src/a.js': function (module, exports, require) {
        console.log('module a');
        module.exports.a = 'a';
        console.log(this); // module.export
    },
});

缓存

webpack同一个模块只会加载一边,不会被反复加载执行,所以需要缓存加载过的模块

moduleExports用于缓存加载过的模块导出的数据,判断如果当前模块被加载过,则返回当前这个模块缓存的数据,否则继续执行,并会在执行结束后缓存这个模块的导出结果

// 完整代码
(function (modules) {
    var moduleExports = {}; //用于缓存模块的导出结果
    // __webpack_require 函数相当于运行一个模块,得到模块的导出结果。
    function __webpack_require(moduleId) {
        if(moduleExports[moduleId]) {
            return moduleExports[moduleId];
        }
        var func = modules[moduleId]; // 得到该模块对应的函数
        var module = {
            exports: {}
        };
        func.call(module.exports, module, module.exports, __webpack_require);
        moduleExports[moduleId] = module.exports;
        return module.exports;
    }

    __webpack_require('./src/index.js'); // __webpack_require 函数相当于运行一个模块,得到模块的导出结果。
})({
    './src/index.js': function (module, exports, require) {
        console.log('index module');
        var { a } = require('./src/a.js');
        console.log(a);
    },
    './src/a.js': function (module, exports, require) {
        console.log('module a');
        module.exports.a = 'a';
        console.log(this); // module.export
    },
});