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(发邮件时,请将#更换为@)进行举报,并提供相关证据,一经查实,本站将立刻删除涉嫌侵权内容。