一文快速弄懂webpack動態(tài)import原理_第1頁
一文快速弄懂webpack動態(tài)import原理_第2頁
一文快速弄懂webpack動態(tài)import原理_第3頁
一文快速弄懂webpack動態(tài)import原理_第4頁
一文快速弄懂webpack動態(tài)import原理_第5頁
已閱讀5頁,還剩12頁未讀, 繼續(xù)免費(fèi)閱讀

下載本文檔

版權(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)用戶因使用這些下載資源對自己和他人造成任何形式的傷害或損失。

評論

0/150

提交評論