




版權(quán)說明:本文檔由用戶提供并上傳,收益歸屬內(nèi)容提供方,若內(nèi)容存在侵權(quán),請進(jìn)行舉報或認(rèn)領(lǐng)
文檔簡介
第一文快速弄懂webpack動態(tài)import原理目錄前言例子1.模塊加載2.jsonp動態(tài)加載script3.執(zhí)行異步腳本4.webpackJsonpCallback5.執(zhí)行異步模塊代碼流程圖總結(jié)
前言
在vue中我們經(jīng)常用到動態(tài)導(dǎo)入頁面組件,那么它是如何實(shí)現(xiàn)的呢,本文將通過簡單的案例,快速了解實(shí)現(xiàn)原理
例子
//index.js
import('./test').then(fn={
console.log(fn.default());
})
//test.js
exportdefaultfunctionfunc(){
return1
}
打包后的代碼包含兩個文件bundle.js和0.js
點(diǎn)擊展開bundle.js
/******/(function(modules){//webpackBootstrap
/******///installaJSONPcallbackforchunkloading
/******/functionwebpackJsonpCallback(data){
/******/varchunkIds=data[0];
/******/varmoreModules=data[1];
/******/
/******/
/******///add"moreModules"tothemodulesobject,
/******///thenflagall"chunkIds"asloadedandfirecallback
/******/varmoduleId,chunkId,i=0,resolves=[];
/******/for(;ichunkIds.length;i++){
/******/chunkId=chunkIds[i];
/******/if(Ototype.hasOwnProperty.call(installedChunks,chunkId)installedChunks[chunkId]){
/******/resolves.push(installedChunks[chunkId][0]);
/******/}
/******/installedChunks[chunkId]=0;
/******/}
/******/for(moduleIdinmoreModules){
/******/if(Ototype.hasOwnProperty.call(moreModules,moduleId)){
/******/modules[moduleId]=moreModules[moduleId];
/******/}
/******/}
/******/if(parentJsonpFunction)parentJsonpFunction(data);
/******/
/******/while(resolves.length){
/******/resolves.shift()();
/******/}
/******/
/******/};
/******/
/******/
/******///Themodulecache
/******/varinstalledModules={};
/******/
/******///objecttostoreloadedandloadingchunks
/******///undefined=chunknotloaded,null=chunkpreloaded/prefetched
/******///Promise=chunkloading,0=chunkloaded
/******/varinstalledChunks={
/******/"main":0
/******/};
/******/
/******/
/******/
/******///scriptpathfunction
/******/functionjsonpScriptSrc(chunkId){
/******/return__webpack_require__.p+""+chunkId+".bundle.js"
/******/}
/******/
/******///Therequirefunction
/******/function__webpack_require__(moduleId){
/******/
/******///Checkifmoduleisincache
/******/if(installedModules[moduleId]){
/******/returninstalledModules[moduleId].exports;
/******/}
/******///Createanewmodule(andputitintothecache)
/******/varmodule=installedModules[moduleId]={
/******/i:moduleId,
/******/l:false,
/******/exports:{}
/******/};
/******/
/******///Executethemodulefunction
/******/modules[moduleId].call(module.exports,module,module.exports,__webpack_require__);
/******/
/******///Flagthemoduleasloaded
/******/module.l=true;
/******/
/******///Returntheexportsofthemodule
/******/returnmodule.exports;
/******/}
/******/
/******///Thisfilecontainsonlytheentrychunk.
/******///Thechunkloadingfunctionforadditionalchunks
/******/__webpack_require__.e=functionrequireEnsure(chunkId){
/******/varpromises=[];
/******/
/******/
/******///JSONPchunkloadingforjavascript
/******/
/******/varinstalledChunkData=installedChunks[chunkId];
/******/if(installedChunkData!==0){//0means"alreadyinstalled".
/******/
/******///aPromisemeans"currentlyloading".
/******/if(installedChunkData){
/******/promises.push(installedChunkData[2]);
/******/}else{
/******///setupPromiseinchunkcache
/******/varpromise=newPromise(function(resolve,reject){
/******/installedChunkData=installedChunks[chunkId]=[resolve,reject];
/******/});
/******/promises.push(installedChunkData[2]=promise);
/******/
/******///startchunkloading
/******/varscript=document.createElement('script');
/******/varonScriptComplete;
/******/
/******/script.charset='utf-8';
/******/script.timeout=120;
/******/if(__webpack_require__.nc){
/******/script.setAttribute("nonce",__webpack_require__.nc);
/******/}
/******/script.src=jsonpScriptSrc(chunkId);
/******/
/******///createerrorbeforestackunwoundtogetusefulstacktracelater
/******/varerror=newError();
/******/onScriptComplete=function(event){
/******///avoidmemleaksinIE.
/******/script.onerror=script.onload=null;
/******/clearTimeout(timeout);
/******/varchunk=installedChunks[chunkId];
/******/if(chunk!==0){
/******/if(chunk){
/******/varerrorType=event(event.type==='load''missing':event.type);
/******/varrealSrc=eventevent.targetevent.target.src;
/******/error.message='Loadingchunk'+chunkId+'failed.\n('+errorType+':'+realSrc+')';
/******/='ChunkLoadError';
/******/error.type=errorType;
/******/error.request=realSrc;
/******/chunk[1](error);
/******/}
/******/installedChunks[chunkId]=undefined;
/******/}
/******/};
/******/vartimeout=setTimeout(function(){
/******/onScriptComplete({type:'timeout',target:script});
/******/},120000);
/******/script.onerror=script.onload=onScriptComplete;
/******/document.head.appendChild(script);
/******/}
/******/}
/******/returnPromise.all(promises);
/******/};
/******/
/******///exposethemodulesobject(__webpack_modules__)
/******/__webpack_require__.m=modules;
/******/
/******///exposethemodulecache
/******/__webpack_require__.c=installedModules;
/******/
/******///definegetterfunctionforharmonyexports
/******/__webpack_require__.d=function(exports,name,getter){
/******/if(!__webpack_require__.o(exports,name)){
/******/Object.defineProperty(exports,name,{enumerable:true,get:getter});
/******/}
/******/};
/******/
/******///define__esModuleonexports
/******/__webpack_require__.r=function(exports){
/******/if(typeofSymbol!=='undefined'Symbol.toStringTag){
/******/Object.defineProperty(exports,Symbol.toStringTag,{value:'Module'});
/******/}
/******/Object.defineProperty(exports,'__esModule',{value:true});
/******/};
/******/
/******///createafakenamespaceobject
/******///mode1:valueisamoduleid,requireit
/******///mode2:mergeallpropertiesofvalueintothens
/******///mode4:returnvaluewhenalreadynsobject
/******///mode8|1:behavelikerequire
/******/__webpack_require__.t=function(value,mode){
/******/if(mode1)value=__webpack_require__(value);
/******/if(mode8)returnvalue;
/******/if((mode4)typeofvalue==='object'valuevalue.__esModule)returnvalue;
/******/varns=Object.create(null);
/******/__webpack_require__.r(ns);
/******/Object.defineProperty(ns,'default',{enumerable:true,value:value});
/******/if(mode2typeofvalue!='string')for(varkeyinvalue)__webpack_require__.d(ns,key,function(key){returnvalue[key];}.bind(null,key));
/******/returnns;
/******/};
/******/
/******///getDefaultExportfunctionforcompatibilitywithnon-harmonymodules
/******/__webpack_require__.n=function(module){
/******/vargetter=modulemodule.__esModule
/******/functiongetDefault(){returnmodule['default'];}:
/******/functiongetModuleExports(){returnmodule;};
/******/__webpack_require__.d(getter,'a',getter);
/******/returngetter;
/******/};
/******/
/******///Ototype.hasOwnProperty.call
/******/__webpack_require__.o=function(object,property){returnOtotype.hasOwnProperty.call(object,property);};
/******/
/******///__webpack_public_path__
/******/__webpack_require__.p="";
/******/
/******///onerrorfunctionforasyncloading
/******/__webpack_require__.oe=function(err){console.error(err);throwerr;};
/******/
/******/varjsonpArray=window["webpackJsonp"]=window["webpackJsonp"]||[];
/******/varoldJsonpFunction=jsonpArray.push.bind(jsonpArray);
/******/jsonpArray.push=webpackJsonpCallback;
/******/jsonpArray=jsonpArray.slice();
/******/for(vari=0;ijsonpArray.length;i++)webpackJsonpCallback(jsonpArray[i]);
/******/varparentJsonpFunction=oldJsonpFunction;
/******/
/******/
/******///Loadentrymoduleandreturnexports
/******/return__webpack_require__(__webpack_require__.s="./src/index.js");
/******/})
/************************************************************************/
/******/({
/***/"./src/index.js":
/*!**********************!*\
!***./src/index.js***!
\**********************/
/*!nostaticexportsfound*/
/***/(function(module,exports,__webpack_require__){
eval("__webpack_require__.e(/*!import()*/0).then(__webpack_require__.bind(null,/*!./test*/\"./src/test.js\")).then(function(fn){\nconsole.log(fn[\"default\"]());\n});\n\n//#sourceURL=webpack:///./src/index.js");
/***/})
/******/});
點(diǎn)擊展開0.js
(window["webpackJsonp"]=window["webpackJsonp"]||[]).push([[0],{
/***/"./src/test.js":
/*!*********************!*\
!***./src/test.js***!
\*********************/
/*!exportsprovided:default*/
/***/(function(module,__webpack_exports__,__webpack_require__){
"usestrict";
eval("__webpack_require__.r(__webpack_exports__);\n/*harmonyexport(binding)*/__webpack_require__.d(__webpack_exports__,\"default\",function(){returnfunc;});\nfunctionfunc(){\nreturn1;\n}\n\n//#sourceURL=webpack:///./src/test.js");
/***/})
}]);
1.模塊加載
webpack通過__webpack_require__加載模塊代碼
//bundle.js
function__webpack_require__(moduleId)
//如果模塊已經(jīng)加載,直接返回模塊導(dǎo)出
if(installedModules[moduleId]){
returninstalledModules[moduleId].exports;
//模塊導(dǎo)出和模塊信息
varmodule=installedModules[moduleId]={
i:moduleId,
l:false,
exports:{}
//執(zhí)行模塊代碼
modules[moduleId].call(module.exports,module,module.exports,__webpack_require__)
module.l=true//標(biāo)記模塊已經(jīng)加載完成
returnmodule.exports;
}
__webpack_require__('index.js')
然后執(zhí)行index.js編譯后的代碼,如下。
Promise.all(
__webpack_require__.e(0)
).then(
__webpack_require__.bind(null,"./src/test.js")
).then(function(fn){
console.log(fn.default());
}));
2.jsonp動態(tài)加載script
先一步步來,看下__webpack_require__.e這個方法,它是最先調(diào)用的。
//bundle.js
__webpack_require__.e=functionrequireEnsure(chunkId){
varpromises=[]
varinstalledChunkData=installedChunks[chunkId];
//如果這個chunk已經(jīng)加載過了就不需要加載了
if(installedChunkData!==0){//0means"alreadyinstalled"
if(installedChunkData){
promises.push(installedChunkData[2]);
}else{
//為這個chunk創(chuàng)建一個promise
varpromise=newPromise(function(resolve,reject){
//記錄這個chunk對應(yīng)promise的resolve和reject方法
installedChunkData=installedChunks[chunkId]=[resolve,reject];
//promises數(shù)組里添加這個chunk對應(yīng)的promise
promises.push(installedChunkData[2]=promise)
//==============動態(tài)創(chuàng)建script=================
varscript=document.createElement('script');
varonScriptComplete
script.charset='utf-8';
script.timeout=120;
if(__webpack_require__.nc){
script.setAttribute("nonce",__webpack_require__.nc);
script.src=jsonpScriptSrc(chunkId)
//createerrorbeforestackunwoundtogetusefulstacktracelater
varerror=newError();
//=================================================
onScriptComplete=function(event){
//avoidmemleaksinIE.
script.onerror=script.onload=null;
clearTimeout(timeout);
varchunk=installedChunks[chunkId];
if(chunk!==0){
if(chunk){
varerrorType=event(event.type==='load''missing':event.type);
varrealSrc=eventevent.targetevent.target.src;
error.message='Loadingchunk'+chunkId+'failed.\n('+errorType+':'+realSrc+')';
='ChunkLoadError';
error.type=errorType;
error.request=realSrc;
chunk[1](error);
installedChunks[chunkId]=undefined;
vartimeout=setTimeout(function(){
onScriptComplete({type:'timeout',target:script});
},120000);
script.onerror=script.onload=onScriptComplete;
document.head.appendChild(script);
returnPromise.all(promises);
};
總結(jié)一下,上述代碼做的事情
如果chunk沒有被加載過,會為這個chunk創(chuàng)建一個promise對象將promise對象存在promises數(shù)組中將promise的resolve和reject存在installedChunks[chunkId]中
3.執(zhí)行異步腳本
經(jīng)過上面的過程,會動態(tài)加載0.js的腳本代碼
(window["webpackJsonp"]=window["webpackJsonp"]||[]).push([[0],{
"./src/test.js":
(function(module,__webpack_exports__,__webpack_require__){
"usestrict";
eval("__webpack_require__.r(__webpack_exports__);\n/*harmonyexport(binding)*/__webpack_require__.d(__webpack_exports__,\"default\",function(){returnfunc;});\nfunctionfunc(){\nreturn1;\n}\n\n//#sourceURL=webpack:///./src/test.js");
/***/})
}]);
可以看到window上有一個webpackJsonp數(shù)組,那么這個東西是從哪里來的呢?,我們來看下面的代碼。
//bundle.js
varjsonpArray=window["webpackJsonp"]=window["webpackJsonp"]||[];
varoldJsonpFunction=jsonpArray.push.bind(jsonpArray);
jsonpArray.push=webpackJsonpCallback;
jsonpArray=jsonpArray.slice();
for(vari=0;ijsonpArray.length;i++)webpackJsonpCallback(jsonpArray[i]);
varparentJsonpFunction=oldJsonpFunction;
其實(shí)一開始初始化時已經(jīng)覆蓋實(shí)現(xiàn)了webpackJsonp.push方法
(window["webpackJsonp"]=window["webpackJsonp"]||[]).push([[0],{
//test.js引入的模塊代碼
//等價于
webpackJsonpCallback([[0],{
溫馨提示
- 1. 本站所有資源如無特殊說明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請下載最新的WinRAR軟件解壓。
- 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請聯(lián)系上傳者。文件的所有權(quán)益歸上傳用戶所有。
- 3. 本站RAR壓縮包中若帶圖紙,網(wǎng)頁內(nèi)容里面會有圖紙預(yù)覽,若沒有圖紙預(yù)覽就沒有圖紙。
- 4. 未經(jīng)權(quán)益所有人同意不得將文件中的內(nèi)容挪作商業(yè)或盈利用途。
- 5. 人人文庫網(wǎng)僅提供信息存儲空間,僅對用戶上傳內(nèi)容的表現(xiàn)方式做保護(hù)處理,對用戶上傳分享的文檔內(nèi)容本身不做任何修改或編輯,并不能對任何下載內(nèi)容負(fù)責(zé)。
- 6. 下載文件中如有侵權(quán)或不適當(dāng)內(nèi)容,請與我們聯(lián)系,我們立即糾正。
- 7. 本站不保證下載資源的準(zhǔn)確性、安全性和完整性, 同時也不承擔(dān)用戶因使用這些下載資源對自己和他人造成任何形式的傷害或損失。
最新文檔
- 金融合同信托合同(一)8篇
- 糧油購銷合同范本與糧食買賣合同3篇
- 官方的二手房買賣定金合同10篇
- 隧道勞務(wù)施工合同3篇
- 電商設(shè)計職業(yè)規(guī)劃
- 學(xué)校食堂衛(wèi)生管理規(guī)范
- 健康促進(jìn)照護(hù)課件
- 2025遼寧體育運(yùn)動職業(yè)技術(shù)學(xué)院輔導(dǎo)員考試試題及答案
- 2025贛西科技職業(yè)學(xué)院輔導(dǎo)員考試試題及答案
- 2025眉山職業(yè)技術(shù)學(xué)院輔導(dǎo)員考試試題及答案
- 倍智tas人才測評系統(tǒng)題庫及答案
- 2025年體彩應(yīng)聘考試試題及答案
- 2023年新高考(新課標(biāo))全國2卷數(shù)學(xué)試題真題(含答案解析)
- 涉密人員保密審查表
- Unit2Lesson3GettingToTheTop課件-高中英語北師大版(2019)選擇性必修第一冊
- 卡通風(fēng)青春畢業(yè)季PPT模板課件
- 《804泄爆墻安裝施工方案》
- 環(huán)境及理化因素?fù)p傷救護(hù)
- 大氣污染控制工程課程設(shè)計---電除塵器設(shè)計說明書
- 上泰pH計SUNTEX-PC-3110操作說明書
- 專業(yè)大戶、家庭農(nóng)場情況調(diào)查表
評論
0/150
提交評論