先簡單說一下這個插件的功能,生成一份資源清單的json文件,以下css
若是是服務器端構造的html,就能夠根據當前的manifest,引入css和js文件,並且這個文件是必須的,不然服務器端壓根不知道hash以後的JS文件名字和CSS名字。html
簡單說下webpack執行,取得webpack.config.js的配置和默認配置合併,而後執行plugin,這裏的執行其實只是簡單的綁定hooks,並不是執行裏面的邏輯,先看下源代碼,再給你們擼一擼這裏面的細節。webpack
compiler實例會做爲參數傳遞,能夠看到new 以後,他就馬上去遍歷的plugin,而後plugin.apply(compiler)去執行了當前的plugin。難道說
plugin在這裏就執行了?說對也不對,看一段最簡單的plugin的demoweb
apply(compiler) { compiler.hooks.compilation.tap('xxx', (compilation) => { do something }); }
官網的demo,用的compiler.plugin,但這個方法已經不推薦使用了,用hooks代替,更語義化一點。
看上面的代碼,apply執行後,其實只是在對應的hooks上註冊了一個方法而已,xxx能夠理解爲一個plugin的標識。註冊方法以後,當webpack執行了當前的hooks,那麼掛載正在當前hooks上的方法就會被執行。
這個有點相似於發佈訂閱模式了。
綜上所述,webpack在 compiler被建立的以後,馬上就去遍歷了plugin,就是想要儘早的註冊方法,不然掛載在一些hooks上的方法就沒辦法被正確觸發。好比json
在webpack開始編譯以前,就能觸發beforeRun鉤子,webpack-manifest-plugin就用到了當前的hook。所以雖然plugin註冊的早,但真正的執行順序在於它綁定的究竟是什麼樣的鉤子。無關於它在webpack配置中plugin裏面的順序。數組
上面都是前置知識,下面經過解讀一個plugin源碼來鞏固下。服務器
先看一段簡單的源碼。
這裏他註冊了好幾個鉤子,咱們一個一個來講。
compiler.hooks.webpackManifestPluginAfterEmit = new SyncWaterfallHook(['manifest']); 這裏是自定義一個hooks,webpack容許自定義hooks,這個hooks是幹嗎的,這是給其餘組件用的,意思就是,我註冊了一個這樣的hooks,其餘組件就能經過tap綁定對應的方法,僅此而已。app
compiler.hooks.compilation.tap(pluginOptions, function (compilation) { compilation.hooks.moduleAsset.tap(pluginOptions, moduleAsset); });
hooks.compilation,compilations是compiler衆多的hooks的一個,官網的解釋是:編譯(compilation)建立以後,執行插件。簡單的能夠理解爲某段編譯過程(一個文件或者一個chunk),一次webpack,會觸發屢次的compilation, 而compilation下面又有N多的hooks,具體有哪些能夠看官網,這裏的moduleAsset,官網的解釋是:一個模塊中的一個資源被添加到編譯中。好比圖片資源。
moduleAsset回調函數接收到了兩個參數,一個是filename,就是hash後的圖片名字,將filename,保存到一個全局對象中。但這裏的資源並不包括JS,CSS,須要在其餘的hooks中處理。函數
compiler.hooks.emit.tap(pluginOptions, emit);
emit的鉤子官網解釋是:生成資源到 output 目錄以前。 說白了就是把構建好的JS和CSS文件寫入到dist目錄以前觸發的hooks。
一樣的emit函數裏面可以拿到 compilation。 compilation.chunks是一個數組,表明着每個chunk,一般是entry裏面定義的文件,以及經過splitChunks,拆開的chunk。chunk裏面能拿到一個files字段,裏面存到就是生成的css和js名字。spa
compiler.hooks.emit.tap('xxx', (compilation) => { compilation.chunks.forEach((chunk) => { console.log(chunk.files); }); });
到這裏webpack-manifest-plugin的主功能就差很少了,將上面獲得的各類hash後的name保存到對象裏面,key就是chunk名(不必定準),但key具體是什麼不重要,到時候服務器端遍歷json的時候,判斷value的後綴便可,究竟是js,css或者其餘什麼的一目瞭然。
webpack-manifest-plugin還有一些細節處理,好比取到了publicPath,結合拿到的fileName,組成了文件的真正地址。
plugin其實還能夠展開不少內容講,但官網都有,不少時候也不用咱們去寫plugin,網上大把,咱們只須要知道,他的基本原理便可。hooks,訂閱發佈等。