摘要:打算寫(xiě)幾篇文章如果能堅(jiān)持的話(huà)來(lái)總結(jié)下,文章不是教你怎么使用,而是讓你更好的了解你在使用的是怎么去運(yùn)行的,想來(lái)想去,第一篇就先介紹下生成的文件,是怎么去執(zhí)行的。
謝謝你們看我扯技術(shù),最近在對(duì)webpack2進(jìn)行的配置進(jìn)行梳理和學(xué)習(xí),webpack是在去年使用vue開(kāi)始接觸的,個(gè)人感覺(jué)webpack 融入到編程過(guò)程中,提供了模塊化,將各種類(lèi)型的文件都看成模塊,通過(guò)不同的 loader 進(jìn)行處理和代碼組織,是一個(gè)比較新穎的編程體驗(yàn),應(yīng)該說(shuō)webpack的編程適用場(chǎng)景比較廣泛,能夠比較方便的引入第三方的各種 npm 模塊進(jìn)行使用, 方便快速開(kāi)發(fā)工作。
打算寫(xiě)幾篇文章(如果能堅(jiān)持的話(huà)= =)來(lái)總結(jié)下 webpack,文章不是教你怎么使用webpack,而是讓你更好的了解你在使用的webpack是怎么去運(yùn)行的 ,想來(lái)想去,第一篇就先介紹下webpack生成的文件,是怎么去執(zhí)行的。
首先我們要先通過(guò) webpack 去生成文件(好一句廢話(huà)),文章所有的代碼都會(huì)在文章最后面給出鏈接,下面是本文章使用的代碼的目錄:
我們現(xiàn)在只要關(guān)注js目錄,里面有兩個(gè)入口 app.js、bar.js,然后會(huì)引用 es5,es6中的各種測(cè)試模塊,具體大家可以看代碼。然后代碼一跑!只見(jiàn)命令行蹭蹭蹭跑出來(lái)了好多信息,像下面一樣:
首先我們來(lái)看下生成的信息:
Asset : 這個(gè)一看就明白是生成的文件相對(duì)于配置中output.path的路徑,可以看到圖中生成的文件都是在 output.path底下的;然后我們仔細(xì)看下文件名,比如第一個(gè)0.fb6d7f4.js,是由[name/chunkname].[hash/chunkhash].js組成的,這個(gè)可以在output.filename 中配置,關(guān)于hash和chunkhash的區(qū)別,這個(gè)后面會(huì)專(zhuān)門(mén)通過(guò)一篇文章進(jìn)行簡(jiǎn)介。
Size : 這個(gè)就沒(méi)啥好說(shuō)的,就是生成文件的大小
Chunks : 我們會(huì)看到有些 Chunks是兩個(gè)數(shù)字,有些是一個(gè),其實(shí)還可能出現(xiàn)更多,經(jīng)過(guò)我的一堆實(shí)驗(yàn)= =,發(fā)現(xiàn)Chunks中的第一個(gè)數(shù)字,就是這個(gè)文件的 ChunkId,而后面的是當(dāng)前這個(gè)文件依賴(lài)的文件的ChunkId,從圖中我們可以看到,第一個(gè)文件的ChunkId是0,它依賴(lài)的是ChunkId為3的manifest.a890c12.js
Chunk Names : 這個(gè)就是這個(gè)生成文件的chunkName,可以用于文件命名,可以看到如果沒(méi)有在entry中指定,那么chunkName會(huì)等于chunkId
程序加載流程了解了生成的信息,接下來(lái)我們把項(xiàng)目跑起來(lái)(可以用 anywhere 跑項(xiàng)目),通過(guò)chrome developer tool可以看到請(qǐng)求情況
可以看到請(qǐng)求了頁(yè)面html之后,按順序分別加載了 manifest,index,0,2文件,這里我們先來(lái)分析下文件的分割和加載流程。
分割可以看到頁(yè)面的 js 被分割成為了4個(gè)文件,通常來(lái)說(shuō),一個(gè)項(xiàng)目定義了一個(gè) entry point,
webpack會(huì)以這個(gè)entry point作為入口,進(jìn)行代碼回溯,如果存在System.import或者是require.ensure的異步模塊調(diào)用,webpack會(huì)對(duì)使用的模塊進(jìn)行多帶帶打包,比如文件中的0、2這兩個(gè) js,如果沒(méi)有異步模塊調(diào)用,那么會(huì)將所有的代碼生成在一個(gè)文件中,webpack 為了使得打包的代碼進(jìn)行優(yōu)化,可以使用CommonsChunkPlugin插件對(duì)代碼進(jìn)行處理,將庫(kù)文件多帶帶打包,通過(guò)規(guī)則生成對(duì)應(yīng)的 chunk 文件,其中的manifest為 默認(rèn)的 chunk,其中包含了打包文件的runtime信息,還有webpackJsonp模塊加載的封裝庫(kù),所有的生成模塊都是采用webpackJsonp進(jìn)行封裝的。
從上面的圖中可以看到,瀏覽器按順序分別加載了 manifest,index,0,2文件,其中manifest相當(dāng)于webpack的runtime工具,用于做模塊加載,其他文件是邏輯文件; manifest中封裝了webpackJsonpCallback方法和__webpack_require__方法,下面我們來(lái)進(jìn)行分析:
webpackJsonpCallback(chunkIds, moreModules, executeModule):webpackJsonpCallback是chunk封裝的包裝方法,webpack在生成每一個(gè)chunk的時(shí)候都是通過(guò)這個(gè)方法進(jìn)行包裝的,我們?cè)谏厦婵吹降?chunksId,會(huì)作為第一個(gè)參數(shù),被包含進(jìn)這個(gè)chunk的module會(huì)被以數(shù)組的形式傳入第二個(gè)參數(shù)moreModules中,如果這個(gè)chunk中包含可以執(zhí)行的modules,需要將 moduleId傳入第三個(gè)參數(shù) executeModule中,下面是 這個(gè)方法的代碼片段:
這個(gè)方法主要做了下面幾件事:
加載chunk
我們可以看到這個(gè)方法用第一個(gè)循環(huán)分別將chunkIds處理進(jìn)入installedChunks對(duì)象中,installedChunks對(duì)象用于記錄chunk的加載情況,分別用0表示當(dāng)前的chunkId已經(jīng)加載完成,用一個(gè)長(zhǎng)度為3的數(shù)組表示當(dāng)前的chunk正在加載中,數(shù)據(jù)中其實(shí)存儲(chǔ)著加載過(guò)程中的resolve方法、reject方法和pormise對(duì)象,這種只在通過(guò)require.ensure或者是System.import才會(huì)出現(xiàn)。因此我們可以看到,第一個(gè)for循環(huán)中判斷如果chunkId在 installedChunks 中存在且不為0,則判斷是異步加載的模塊已經(jīng)加載成功,將chunk的resolve方法傳入resolves數(shù)組,然后后面運(yùn)行,然后將chunk對(duì)應(yīng)的狀態(tài)設(shè)置為0。如果判斷之后不存在,這認(rèn)為這是一個(gè)同步加載的chunk,直接設(shè)置為0,表示chunk已經(jīng)加載完畢。
加載 module
加載 module 的邏輯比較簡(jiǎn)單,判斷純不存在這個(gè)module之后,將 其寫(xiě)入modules參數(shù)之中
運(yùn)行需要執(zhí)行的module
如果executeModule存在,則對(duì)其中對(duì)應(yīng)moduleId的模塊進(jìn)行運(yùn)行
__webpack_require__: 這個(gè)對(duì)象包含了多個(gè)方法,主要用于module和chunk的加載,處理和運(yùn)行,下面我們一個(gè)一個(gè)分析:
__webpack_require__(moduleId) :代碼如下
這個(gè)方法接收一個(gè)moduleId,構(gòu)建一個(gè) module 對(duì)象存入installedModules中,并且初始化這個(gè) module, 最后返回module.export
__webpack_require__.e(chunkId) : 這個(gè)方法用于通過(guò)異步的方式加載 chunk 文件,代碼如下:
這個(gè)方法總體來(lái)說(shuō)就是加載一個(gè) script 文件,生成一個(gè) promise對(duì)象,當(dāng) script 加載完成后運(yùn)行,又會(huì)執(zhí)行前面的webpackJsonpCallback注冊(cè)chunk,然后promise.resolve。這里面需要注意的是紅框里面的東西,這個(gè)涉及到一個(gè)優(yōu)化點(diǎn),如果沒(méi)有在使用CommonsChunkPlugin多帶帶打包manifest,那么一般來(lái)說(shuō)他會(huì)和你指定的其他庫(kù)通過(guò)CommonsChunkPlugin打包在一起,那么你會(huì)發(fā)現(xiàn)即使你只是修改了庫(kù)之外的邏輯,庫(kù)文件生成的文件的hash或者是chunkhash也是會(huì)變的,原因就在于manifest中紅框部分是動(dòng)態(tài)生成的,導(dǎo)致文件的 hash 產(chǎn)生變化,不利于緩存,因此建議多帶帶打包manifest
__webpack_require__.oe:定義一個(gè)統(tǒng)一的錯(cuò)誤處理函數(shù)
__webpack_require__.p:這個(gè)是和webpack的output.publicPath對(duì)應(yīng)的值
__webpack_require__.o: Object.prototype.hasOwnProperty的封裝
前面幾個(gè)方法在 ES5的情景下面已經(jīng)足夠運(yùn)行這個(gè)模塊系統(tǒng),我們都知道webpack2加入了對(duì)ES6 MODULE的支持,下面幾個(gè)__webpack_require__是為ES6使用的:
__webpack_require__.d:代碼如下:
這個(gè)是用于ES6中命名的export比如 webpack 遇到這種export,會(huì)對(duì)其用__webpack_require__.d進(jìn)行包裝,變成:
__webpack_require__.i:用于返回一個(gè)正確的上下文的函數(shù)回去,針對(duì)的是export直接為一個(gè)可運(yùn)行方法的時(shí)候
以上就是webpack manifest中的大部分重要的函數(shù),其實(shí)主要就是通過(guò)webpackJsonpCallback來(lái)注冊(cè)載入對(duì)應(yīng)的chunk文件,通過(guò)__webpack_require__來(lái)處理模塊的關(guān)系。
總結(jié)整個(gè)webpack 的在運(yùn)行時(shí)都是通過(guò) manifest去做控制處理的, webpackJsonpCallback對(duì)應(yīng)的是對(duì)加載的chunk文件的處理,__webpack_require__是對(duì)加載模塊的處理,了解這些可以使我們更好的去優(yōu)化我們的代碼,幫助我們?nèi)フ{(diào)試代碼,幫助我們?cè)趶?fù)雜情況下去解決問(wèn)題提供一些其他的思路。
最后附上代碼:先介紹下,webpack-base是我在使用webpack的過(guò)程中自己總結(jié)的一套腳手架,文檔還沒(méi)有完善,如果需要文檔可以在issue里面提,本次的項(xiàng)目在分支上面開(kāi)發(fā),代碼點(diǎn)擊這里
文章版權(quán)歸作者所有,未經(jīng)允許請(qǐng)勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉(zhuǎn)載請(qǐng)注明本文地址:http://m.specialneedsforspecialkids.com/yun/81789.html
摘要:它會(huì)檢測(cè)出最大靜態(tài)子樹(shù)就是不需要?jiǎng)討B(tài)性的子樹(shù)并且從渲染函數(shù)中萃取出來(lái)。這樣在每次重渲染的時(shí)候,它就會(huì)直接重用完全相同的同時(shí)跳過(guò)比對(duì)。需要注意的是,中的操作必須是同步的,不可以存在異步操作的情況。 新增:哈哈,最近又推出了 vue 的文章,在這里放個(gè)鏈接~手把手教你從零寫(xiě)一個(gè)簡(jiǎn)單的 VUE 感謝有人看我扯技術(shù),這篇文章主要介紹最近非常火的vue2前端框架的特點(diǎn)和vue2+vuex2+we...
摘要:它會(huì)檢測(cè)出最大靜態(tài)子樹(shù)就是不需要?jiǎng)討B(tài)性的子樹(shù)并且從渲染函數(shù)中萃取出來(lái)。這樣在每次重渲染的時(shí)候,它就會(huì)直接重用完全相同的同時(shí)跳過(guò)比對(duì)。需要注意的是,中的操作必須是同步的,不可以存在異步操作的情況。 新增:哈哈,最近又推出了 vue 的文章,在這里放個(gè)鏈接~手把手教你從零寫(xiě)一個(gè)簡(jiǎn)單的 VUE 感謝有人看我扯技術(shù),這篇文章主要介紹最近非常火的vue2前端框架的特點(diǎn)和vue2+vuex2+we...
摘要:它會(huì)檢測(cè)出最大靜態(tài)子樹(shù)就是不需要?jiǎng)討B(tài)性的子樹(shù)并且從渲染函數(shù)中萃取出來(lái)。這樣在每次重渲染的時(shí)候,它就會(huì)直接重用完全相同的同時(shí)跳過(guò)比對(duì)。需要注意的是,中的操作必須是同步的,不可以存在異步操作的情況。 新增:哈哈,最近又推出了 vue 的文章,在這里放個(gè)鏈接~手把手教你從零寫(xiě)一個(gè)簡(jiǎn)單的 VUE 感謝有人看我扯技術(shù),這篇文章主要介紹最近非常火的vue2前端框架的特點(diǎn)和vue2+vuex2+we...
摘要:歡迎大家收看聊一聊系列,這一套系列文章,可以幫助前端工程師們了解前端的方方面面不僅僅是代碼從說(shuō)起要想了解,得從一個(gè)新的規(guī)則說(shuō)起。因?yàn)橛脩?hù)沒(méi)有安裝的話(huà),我們強(qiáng)制要求顯示也沒(méi)有辦法。國(guó)內(nèi)有阿里巴巴的平臺(tái),可以選自己喜歡的圖標(biāo)導(dǎo)出。 歡迎大家收看聊一聊系列,這一套系列文章,可以幫助前端工程師們了解前端的方方面面(不僅僅是代碼):https://segmentfault.com/blog/fr...
摘要:歡迎大家收看聊一聊系列,這一套系列文章,可以幫助前端工程師們了解前端的方方面面不僅僅是代碼從說(shuō)起要想了解,得從一個(gè)新的規(guī)則說(shuō)起。因?yàn)橛脩?hù)沒(méi)有安裝的話(huà),我們強(qiáng)制要求顯示也沒(méi)有辦法。國(guó)內(nèi)有阿里巴巴的平臺(tái),可以選自己喜歡的圖標(biāo)導(dǎo)出。 歡迎大家收看聊一聊系列,這一套系列文章,可以幫助前端工程師們了解前端的方方面面(不僅僅是代碼):https://segmentfault.com/blog/fr...
閱讀 1007·2023-04-25 14:45
閱讀 2784·2021-09-30 09:59
閱讀 3129·2021-09-22 15:48
閱讀 2430·2019-08-30 15:55
閱讀 3481·2019-08-30 15:44
閱讀 550·2019-08-29 14:07
閱讀 3417·2019-08-26 13:45
閱讀 543·2019-08-26 11:31