webpack入口模块加载原理

72 阅读1分钟

前端出现了模块化,所以使得我们可以将前端的功能划分为一个一个的小模块,通过模块之间的相互引用来实现功能;这样的好处就是代码会更加容易阅读和维护;

但是浏览器是没有模块化的概念的,浏览器只能执行原始的js文件,不会做模块化的处理,因此webpack的出现主要是为了解决这个问题,当然它还可以解决其他的问题(浏览器的兼容,代码的转译等等)

webpack会默认以src/index作为入口文件进行文件之间的依赖关系分析,将所有的js文件(也就是一个一个的小模块)打包为一个js文件,同时还要避免命名冲入的问题;

webpack的模块加载实现思路大概是这样的:

例如文件index.js中引入了a.js模块

var a = require('./a.js')
console.log(a)

a.js

module.exports = 'a'

webpack从index.js入口文件进行打包编译之后输出一个main.js文件

(function (modules){
    var moduleExports = {} // 模块结果缓存
    // require函数的执行会返回一个模块的结果
    function __webpack_require(moduleId){
        // 判断有无缓存,如果有该模块的缓存,直接读取
        if(moduleId){
            return moduleExports[moduleId]
        }
        // 如果没有模块的缓存
        var func = modules[moduleId] // 获取模块函数
        var module = {
            exports:{}
        }
        func(module, module.exports, __webpack_require); // 执行模块函数
        var result = module.exports; // 获取导出结果
        moduleExports[moduleId] = result // 将导出结果缓存
        return result; // 返回导出结果
    }
    // 执行入口模块,并得到模块的导出结果
    return __webpack_require('./src/index.js')
})({
  './src/a.js': function (module, exports){ // 每个模块文件以一个函数的形式进行传递,这样的好处就是避免的命名冲突;
        eval("module.exports = \"a\";\n ")
    },
  './src/index.js': function (module, exports, __webpack_require){
        eval("var a = __webpack_require(\"./src/a.js\")\n")
    }
})