webpack是如何实现模块化加载的方法
webpack支持的模块规范有AMD、CommonJS、ES2015import等规范。不管何种规范大致可以分为同步加载和异步加载两种情况。本文将介绍webpack是如何实现模块管理和加载。
同步加载如下:
importafrom'./a'; console.log(a);
异步加载如下:
import('./a').then(a=>console.log(a));
webpacks实现的启动函数,直接将入口程序module传入启动函数内,并缓存在闭包内,如下:
(function(modules){
......
//加载入口模块并导出(实现启动程序)
return__webpack_require__(__webpack_require__.s=0);
})({
0:(function(module,__webpack_exports__,__webpack_require__){
module.exports=__webpack_require__(/*!./src/app.js*/"./src/app.js");
})
})
webpack在实现模块管理上不管服务端还是客户端大致是一样,主要由installedChunks记录已经加载的chunk,installedModules记录已经执行过的模块,具体如下:
/**
*module缓存器
*key为moduleId(一般为文件路径)
*value为module对象{i:moduleId,l:false,exports:{}}
*/
varinstalledModules={};
/**
*chunks加载状态记录器
*key一般为chunk索引
*valueundefined:未加载0:已经加载(客户端特有null:准备加载[resolve,reject]:加载中)
*/
varinstalledChunks={
"app":0
}
不管是服务端还是客户端同步加载的方法都一样,主要是检测installedModules中是否已经缓存有要加载的module,有则直接返回,否则就创建一个新的module,并执行返回module.exports,具体实现如下:
//编译后的同步加载
__webpack_require__(/*!./src/app.js*/"./src/app.js");
//加载模块的方法,即require方法
function__webpack_require__(moduleId){
//检查当前的module是否已经存在缓存中
if(installedModules[moduleId]){
returninstalledModules[moduleId].exports;//直接返回已缓存的module.exports
}
//创建一个新的module,并添加到缓存中
varmodule=installedModules[moduleId]={
i:moduleId,
l:false,//是否已经加载
exports:{}//暴露的对象
};
//执行当前module的方法
modules[moduleId].call(module.exports,module,module.exports,__webpack_require__);
//标记module加载完成状态
module.l=true;
//返回module暴露的exports对象
returnmodule.exports;
}
服务端的异步加载是通过node的require方法加载chunk并返回一个promises对象。所有chunk都是暴露出ids和modules对象,具体实现如下:
//编译后的异步加载方法
__webpack_require__.e(/*!import()*/0).then(__webpack_require__.bind(null,/*!./c.js*/"./src/c.js"))
//chunk0代码如下(即0.js的代码)
exports.ids=[0];
exports.modules={
"./src/c.js":(function(module,__webpack_exports__,__webpack_require__){
"usestrict";
__webpack_require__.r(__webpack_exports__);
__webpack_exports__["default"]=(function(){
console.log('c');
})
})
}
//异步加载模块方法
__webpack_require__.e=functionrequireEnsure(chunkId){
varpromises=[];
if(installedChunks[chunkId]!==0){
varchunk=require("./"+({}[chunkId]||chunkId)+".js");
varmoreModules=chunk.modules,chunkIds=chunk.ids;
for(varmoduleIdinmoreModules){
modules[moduleId]=moreModules[moduleId];
}
for(vari=0;i
客户端的异步加载是通过JSONP原理进行加载资源,将chunk内容([chunkIds,modules])存到全局的webpackJsonp数组中,并改造webpackJsonp的push方法实现监听chunk加载完成事件。具体实现如下:
//编译后的异步加载方法
__webpack_require__.e(/*!import()*/0).then(__webpack_require__.bind(null,/*!./c.js*/"./src/c.js"))
//chunk0代码如下(即0.js的代码)
(window["webpackJsonp"]=window["webpackJsonp"]||[]).push([[0],{
"./src/c.js":(function(module,__webpack_exports__,__webpack_require__){
"usestrict";
__webpack_require__.r(__webpack_exports__);
__webpack_exports__["default"]=(function(){
console.log('c');
});
})
}]);
//加载成功的回调函数
functionwebpackJsonpCallback(data){
varchunkIds=data[0];
varmoreModules=data[1];
//将本次加载回来的chunk标记为加载完成状态,并执行回调
varmoduleId,chunkId,i=0,resolves=[];
for(;i
更多可以查看编译后的代码客户端、服务端
以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持毛票票。
声明:本文内容来源于网络,版权归原作者所有,内容由互联网用户自发贡献自行上传,本网站不拥有所有权,未作人工编辑处理,也不承担相关法律责任。如果您发现有涉嫌版权的内容,欢迎发送邮件至:czq8825#qq.com(发邮件时,请将#更换为@)进行举报,并提供相关证据,一经查实,本站将立刻删除涉嫌侵权内容。