You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
// expose the modules object (__webpack_modules__)__webpack_require__.m=__webpack_modules__;/* webpack/runtime/ensure chunk */(()=>{__webpack_require__.f={};// This file contains only the entry chunk.// The chunk loading function for additional chunks__webpack_require__.e=(chunkId)=>{returnPromise.all(Object.keys(__webpack_require__.f).reduce((promises,key)=>{__webpack_require__.f[key](chunkId,promises);returnpromises;},[]));};})();/* webpack/runtime/global 获得this*/(()=>{__webpack_require__.g=(function(){if(typeofglobalThis==='object')returnglobalThis;try{returnthis||newFunction('return this')();}catch(e){if(typeofwindow==='object')returnwindow;}})();})();/* webpack/runtime/get javascript chunk filename */(()=>{// This function allow to reference async chunks__webpack_require__.u=(chunkId)=>{// return url for filenames based on templatereturn""+chunkId+".js";};})();/* webpack/runtime/load script JSONPscript标签的方式异步模块加载函数,真正动态去加载js文件*/(()=>{varinProgress={};vardataWebpackPrefix="webpack_step1:";// loadScript function to load a script via script tag__webpack_require__.l=(url,done,key,chunkId)=>{//存在正在加载相同的模块则存入回调函数,待js文件加载完再执行if(inProgress[url]){inProgress[url].push(done);return;}varscript,needAttach;//判断是否该模块的js文件已经加载过,加载过则重新if(key!==undefined){varscripts=document.getElementsByTagName("script");for(vari=0;i<scripts.length;i++){vars=scripts[i];if(s.getAttribute("src")==url||s.getAttribute("data-webpack")==dataWebpackPrefix+key){script=s;break;}}}// 动态创建srcipt标签,使用jsonp的模式异步加载if(!script){needAttach=true;script=document.createElement('script');script.charset='utf-8';script.timeout=120;if(__webpack_require__.nc){script.setAttribute("nonce",__webpack_require__.nc);}script.setAttribute("data-webpack",dataWebpackPrefix+key);script.src=url;}// js加载的处理:1.js加载出错,2.js加载完毕,执行回调 3.js加载超时// 3种情况满足一种均会进行删除该scrpit标签inProgress[url]=[done];varonScriptComplete=(prev,event)=>{// avoid mem leaks in IE.script.onerror=script.onload=null;clearTimeout(timeout);vardoneFns=inProgress[url];deleteinProgress[url];script.parentNode&&script.parentNode.removeChild(script);doneFns&&doneFns.forEach((fn)=>(fn(event)));if(prev)returnprev(event);};// 加载超时(2分钟)处理vartimeout=setTimeout(onScriptComplete.bind(null,undefined,{type: 'timeout',target: script}),120000);// 其他情况处理script.onerror=onScriptComplete.bind(null,script.onerror);script.onload=onScriptComplete.bind(null,script.onload);needAttach&&document.head.appendChild(script);};})();/* webpack/runtime/publicPath 获得公共路径*/(()=>{varscriptUrl;if(__webpack_require__.g.importScripts)scriptUrl=__webpack_require__.g.location+"";vardocument=__webpack_require__.g.document;if(!scriptUrl&&document){if(document.currentScript)scriptUrl=document.currentScript.srcif(!scriptUrl){varscripts=document.getElementsByTagName("script");if(scripts.length)scriptUrl=scripts[scripts.length-1].src}}// When supporting browsers where an automatic publicPath is not supported you must specify an output.publicPath manually via configuration// or pass an empty string ("") and set the __webpack_public_path__ variable from your code to use your own logic.if(!scriptUrl)thrownewError("Automatic publicPath is not supported in this browser");scriptUrl=scriptUrl.replace(/#.*$/,"").replace(/\?.*$/,"").replace(/\/[^\/]+$/,"/");__webpack_require__.p=scriptUrl;})();(()=>{// no baseURI// 该对象用户缓存已经加载和正在加载的chunk,在入口文件(把入口文件也当做一个chunk)中初始化,初始化后包含了入口chunk的状态,// 此例中入口chunk的Id为web,webpack分配chunkId是0开始计数递增的,实际上入口chunk的Id一定是最大的,从上面的代码中值0表示当前的入口chunk已经加载了。// undefined = chunk not loaded, null = chunk preloaded/prefetched// Promise = chunk loading, 0 = chunk loadedvarinstalledChunks={"web": 0};__webpack_require__.f.j=(chunkId,promises)=>{// JSONP chunk loading for javascriptvarinstalledChunkData=__webpack_require__.o(installedChunks,chunkId) ? installedChunks[chunkId] : undefined;//判断是否已加载if(installedChunkData!==0){// 0 means "already installed".// 正在加载则存入promises等待加载完毕 a Promise means "currently loading".if(installedChunkData){promises.push(installedChunkData[2]);}else{if(true){// all chunks have JS// setup Promise in chunk cache 将加载的模块缓存,将其缓存到installedChunks及推到promisesvarpromise=newPromise((resolve,reject)=>{installedChunkData=installedChunks[chunkId]=[resolve,reject];});promises.push(installedChunkData[2]=promise);// start chunk loadingvarurl=__webpack_require__.p+__webpack_require__.u(chunkId);// create error before stack unwound to get useful stacktrace latervarerror=newError();//加载完毕回调函数,处理异步加载js出错varloadingEnded=(event)=>{if(__webpack_require__.o(installedChunks,chunkId)){installedChunkData=installedChunks[chunkId];if(installedChunkData!==0)installedChunks[chunkId]=undefined;if(installedChunkData){varerrorType=event&&(event.type==='load' ? 'missing' : event.type);varrealSrc=event&&event.target&&event.target.src;error.message='Loading chunk '+chunkId+' failed.\n('+errorType+': '+realSrc+')';error.name='ChunkLoadError';error.type=errorType;error.request=realSrc;installedChunkData[1](error);}}};__webpack_require__.l(url,loadingEnded,"chunk-"+chunkId,chunkId);}elseinstalledChunks[chunkId]=0;}}};// no prefetching// no preloaded// no HMR// no HMR manifest// no deferred startup// install a JSONP callback for chunk loadingvarwebpackJsonpCallback=(parentChunkLoadingFunction,data)=>{var[chunkIds,moreModules,runtime]=data;// add "moreModules" to the modules object,// then flag all "chunkIds" as loaded and fire callbackvarmoduleId,chunkId,i=0,resolves=[];// 遍历需要执行的chunkfor(;i<chunkIds.length;i++){chunkId=chunkIds[i];// 如果该chunk正在加载中状态if(__webpack_require__.o(installedChunks,chunkId)&&installedChunks[chunkId]){// 暂存该chunk对应Promise的resolve方法resolves.push(installedChunks[chunkId][0]);}// 将该chunk的状态置为加载完成installedChunks[chunkId]=0;}// 遍历这些chunk依赖的模块并缓存模块到modules对象中,这个对象是在入口文件的最外层方法当做参数传入的for(moduleIdinmoreModules){if(__webpack_require__.o(moreModules,moduleId)){__webpack_require__.m[moduleId]=moreModules[moduleId];}}if(runtime)runtime(__webpack_require__);// 将加载的chunk存入chunkLoadingGlobalif(parentChunkLoadingFunction)parentChunkLoadingFunction(data);// 将加载的chunk对应的Promise fullfill掉,这时就会加载import().then的代码while(resolves.length){resolves.shift()();}}//全局加载的chunkvarchunkLoadingGlobal=self["webpackChunkwebpack_step1"]=self["webpackChunkwebpack_step1"]||[];//如果已经存在全局加载的chank模块信息,则遍历去加载chunkLoadingGlobal.forEach(webpackJsonpCallback.bind(null,0));//将全局加载的chunk的push函数修改成webpackJsonpCallback,并将chunkLoadingGlobal以前的push函数作为第一个预置参数,将后续加载的异步模块存到chunkLoadingGlobalchunkLoadingGlobal.push=webpackJsonpCallback.bind(null,chunkLoadingGlobal.push.bind(chunkLoadingGlobal));// no deferred startup})();
简单打包
文件介绍
运行时分析
webpack执行打包后生成的js文件是一个立即执行函数,其参数modules为一个对象{},包含我们所有要打包的文件。
这个立即执行函数主要分为以下部分:
模块加载执行流程:
__webpack_require__
加载模块,接受的参数是moduleId
(文件路径),返回的是模块的exports
exports
,不存在则创建一个模块并缓存__webpack_modules__
中模块函数exports
打包后模块解析
含有异步加载的打包
文件介绍
运行时分析
异步打包的模块,多出了以下方法
__webpack_require__.f.j
方法加载模块。installedChunks
中(webpackJsonpCallback会调用),还处理其他拦截相同文件加载、加载文件的url、加载异常回调的等,最后会调用__webpack_require__.l
加载js文件。installedChunks
中的对应模块的Promise fullfill掉,执行引入异步加载import().then的代码 2.将异步模块存到__webpack_modules__
这个全局注册模块集合中。模块加载执行流程:
__webpack_require__.e
->__webpack_require__.f.j
->__webpack_require__.l
, 使用动态创建script标签的形式 下载模块文件,下载完毕后最终__webpack_require__.e
的会返回一个的promise的实例(Promise.all)self["webpackChunkwebpack_step1"].push
方法,该方法已经在入口文件加载时重置成为了webpackJsonpCallback
函数,用来触发引入该异步模块的回调(将第一步的Promise.all状态修改成fullfilled)和缓存该异步模块。import('').then()
格式,则在__webpack_require__.e
执行完毕返回,会执行__webpack_require__
去引入对应的异步模块文件打包后的模块解析解析
runtime.js
从上面的打包可以看出,在入口
web.js
文件中,包含了webpack的运行环境(具体作用就是模块解析, 加载) 和 模块信息清单,在webpack中称为runtime
,模块信息清单在每次有模块变更(hash 变更)时都会变更, 所以我们想把这部分代码单独打包出来, 配合后端缓存策略, 这样就不会因为某个模块的变更导致包含模块信息的模块(通常会被包含在最后一个 bundle 中)缓存失效。在
webpack.config.js
就可以配置:这样子实现,则模块的和runtime就会分别打包,我们都知道js标签的加载顺序会影响到相关js的执行,这里我们的模块必须依赖
runtime.js
,如果模块js先加载,而runtime.js
而后才加载,会不会导致问题呢?经测试是不会,其实就跟我们之前的异步加载js模块类似,还记得全局变量
chunkLoadingGlobal
么?webpack 运行时内部维护了一个数组变量, 这个变量被挂载在 window 对象上:
无论是 runtime 还是普通的 chunk 都会在IIFE函数中试图去读取这个属性, 如果没有读取到就为其赋值一个数组.
runtime的立即执行函数中, 会判断如果
window["webpackChunkwebpack_step1"]
的是否已包含内容, 如果有,也就意味着 runtime 加载之前有其他 chunk 加载了, 此时 runtime 就会读取这个数组中的内容然后在进行解析上之前加载完成的 chunk 。The text was updated successfully, but these errors were encountered: