webpack支持的模块规范有 AMD 、CommonJS、ES2015 import 等规范。不管何种规范大致可以分为同步加载和异步加载两种情况。本文将介绍webpack是如何实现模块管理和加载。
同步加载如下:
import a from './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: {}} */ var installedModules = {}; /** * chunks加载状态记录器 * key 一般为 chunk 索引 * value undefined:未加载 0:已经加载 (客户端特有 null: 准备加载 [resolve, reject]: 加载中) */ var installedChunks = { "app": 0 }
不管是服务端还是客户端同步加载的方法都一样,主要是检测installedModules中是否已经缓存有要加载的module,有则直接返回,否则就创建一个新的module,并执行返回module.exports,具体实现如下:
// 编译后的同步加载 __webpack_require__(/*! ./src/app.js */"./src/app.js"); // 加载模块的方法,即require方法 function __webpack_require__(moduleId) { // 检查当前的module是否已经存在缓存中 if(installedModules[moduleId]) { return installedModules[moduleId].exports; // 直接返回已缓存的 module.exports } // 创建一个新的 module, 并添加到缓存中 var module = installedModules[moduleId] = { i: moduleId, l: false, // 是否已经加载 exports: {} // 暴露的对象 }; // 执行当前 module 的方法 modules[moduleId].call(module.exports, module, module.exports, __webpack_require__); // 标记 module 加载完成状态 module.l = true; // 返回 module 暴露的 exports 对象 return module.exports; }
服务端的异步加载是通过node的require方法加载chunk并返回一个promises对象。所有chunk都是暴露出ids和modules对象,具体实现如下:
// 编译后的异步加载方法 __webpack_require__.e(/*! import() */ 0).then(__webpack_require__.bind(null, /*! ./c.js */ "./src/c.js")) // chunk 0 代码如下(即0.js的代码) exports.ids = [0]; exports.modules = { "./src/c.js": (function(module, __webpack_exports__, __webpack_require__) { "use strict"; __webpack_require__.r(__webpack_exports__); __webpack_exports__["default"] = (function () { console.log('c'); }) }) } // 异步加载模块方法 __webpack_require__.e = function requireEnsure(chunkId) { var promises = []; if(installedChunks[chunkId] !== 0) { var chunk = require("./" + ({}[chunkId]||chunkId) + ".js"); var moreModules = chunk.modules, chunkIds = chunk.ids; for(var moduleId in moreModules) { modules[moduleId] = moreModules[moduleId]; } for(var i = 0; i < chunkIds.length; i++) installedChunks[chunkIds[i]] = 0; } return Promise.all(promises); }
客户端的异步加载是通过JSONP原理进行加载资源,将chunk内容([chunkIds, modules])存到全局的webpackJsonp数组中,并改造webpackJsonp的push方法实现监听chunk加载完成事件。具体实现如下:
// 编译后的异步加载方法 __webpack_require__.e(/*! import() */ 0).then(__webpack_require__.bind(null, /*! ./c.js */ "./src/c.js")) // chunk 0 代码如下(即0.js的代码) (window["webpackJsonp"] = window["webpackJsonp"] || []).push([[0],{ "./src/c.js": (function(module, __webpack_exports__, __webpack_require__) { "use strict"; __webpack_require__.r(__webpack_exports__); __webpack_exports__["default"] = (function () { console.log('c'); }); }) }]); // 加载成功的回调函数 function webpackJsonpCallback(data) { var chunkIds = data[0]; var moreModules = data[1]; // 将本次加载回来的 chunk 标记为加载完成状态,并执行回调 var moduleId, chunkId, i = 0, resolves = []; for(;i < chunkIds.length; i++) { chunkId = chunkIds[i]; if(Object.prototype.hasOwnProperty.call(installedChunks, chunkId) && installedChunks[chunkId]) { resolves.push(installedChunks[chunkId][0]); // 将chunk成功回调添加到要执行的队列中 } installedChunks[chunkId] = 0; // 将chunk标记为加载完成 } // 将本次加载回来的 module 添加到全局的 modules 对象 for(moduleId in moreModules) { if(Object.prototype.hasOwnProperty.call(moreModules, moduleId)) { modules[moduleId] = moreModules[moduleId]; } } // 判断 webpackJsonp 数组原始的push方法是否存在,存在则将数据追加到webpackJsonp中 if(parentJsonpFunction) parentJsonpFunction(data); // 执行所有 chunk 回调 while(resolves.length) { resolves.shift()(); } }; // 加载完成监听方法的实现 var jsonpArray = window["webpackJsonp"] = window["webpackJsonp"] || []; var oldJsonpFunction = jsonpArray.push.bind(jsonpArray); jsonpArray.push = webpackJsonpCallback; jsonpArray = jsonpArray.slice(); for(var i = 0; i < jsonpArray.length; i++) webpackJsonpCallback(jsonpArray[i]); var parentJsonpFunction = oldJsonpFunction; // 异步加载模块方法 __webpack_require__.e = function requireEnsure(chunkId) { var promises = []; var installedChunkData = installedChunks[chunkId]; if(installedChunkData !== 0) { // 0 时表示已经安装完成 if(installedChunkData) { // 加载中 promises.push(installedChunkData[2]); } else { // 创建一个回调的Promise,并将Promise缓存到installedChunks中 var promise = new Promise(function(resolve, reject) { installedChunkData = installedChunks[chunkId] = [resolve, reject]; }); promises.push(installedChunkData[2] = promise); var script = document.createElement('script'); var onScriptComplete; script.charset = 'utf-8'; script.timeout = 120; if (__webpack_require__.nc) { script.setAttribute("nonce", __webpack_require__.nc); } script.src = jsonpScriptSrc(chunkId); var error = new Error(); onScriptComplete = function (event) { // 加载完成回调 // 避免IE内存泄漏。 script.onerror = script.onload = null; clearTimeout(timeout); // 关闭超时定时器 var chunk = installedChunks[chunkId]; if(chunk !== 0) { // 未加载完成 if(chunk) { // 加载中 var errorType = event && (event.type === 'load' "_blank" href="https://github.com/ztMin/notes/blob/master/webpack/webpack-module/dist/client/app.js" rel="external nofollow" >客户端、服务端以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持。
免责声明:本站资源来自互联网收集,仅供用于学习和交流,请遵循相关法律法规,本站一切资源不代表本站立场,如有侵权、后门、不妥请联系本站删除!
《魔兽世界》大逃杀!60人新游玩模式《强袭风暴》3月21日上线
暴雪近日发布了《魔兽世界》10.2.6 更新内容,新游玩模式《强袭风暴》即将于3月21 日在亚服上线,届时玩家将前往阿拉希高地展开一场 60 人大逃杀对战。
艾泽拉斯的冒险者已经征服了艾泽拉斯的大地及遥远的彼岸。他们在对抗世界上最致命的敌人时展现出过人的手腕,并且成功阻止终结宇宙等级的威胁。当他们在为即将于《魔兽世界》资料片《地心之战》中来袭的萨拉塔斯势力做战斗准备时,他们还需要在熟悉的阿拉希高地面对一个全新的敌人──那就是彼此。在《巨龙崛起》10.2.6 更新的《强袭风暴》中,玩家将会进入一个全新的海盗主题大逃杀式限时活动,其中包含极高的风险和史诗级的奖励。
《强袭风暴》不是普通的战场,作为一个独立于主游戏之外的活动,玩家可以用大逃杀的风格来体验《魔兽世界》,不分职业、不分装备(除了你在赛局中捡到的),光是技巧和战略的强弱之分就能决定出谁才是能坚持到最后的赢家。本次活动将会开放单人和双人模式,玩家在加入海盗主题的预赛大厅区域前,可以从强袭风暴角色画面新增好友。游玩游戏将可以累计名望轨迹,《巨龙崛起》和《魔兽世界:巫妖王之怒 经典版》的玩家都可以获得奖励。
更新日志
- 中国武警男声合唱团《辉煌之声1天路》[DTS-WAV分轨]
- 紫薇《旧曲新韵》[320K/MP3][175.29MB]
- 紫薇《旧曲新韵》[FLAC/分轨][550.18MB]
- 周深《反深代词》[先听版][320K/MP3][72.71MB]
- 李佳薇.2024-会发光的【黑籁音乐】【FLAC分轨】
- 后弦.2012-很有爱【天浩盛世】【WAV+CUE】
- 林俊吉.2012-将你惜命命【美华】【WAV+CUE】
- 晓雅《分享》DTS-WAV
- 黑鸭子2008-飞歌[首版][WAV+CUE]
- 黄乙玲1989-水泼落地难收回[日本天龙版][WAV+CUE]
- 周深《反深代词》[先听版][FLAC/分轨][310.97MB]
- 姜育恒1984《什么时候·串起又散落》台湾复刻版[WAV+CUE][1G]
- 那英《如今》引进版[WAV+CUE][1G]
- 蔡幸娟.1991-真的让我爱你吗【飞碟】【WAV+CUE】
- 群星.2024-好团圆电视剧原声带【TME】【FLAC分轨】