淺談webpack之plugin,webpack-manifest-plugin源碼解讀

經過解讀webpack-manifest-plugin,瞭解下plugin機制

先簡單說一下這個插件的功能,生成一份資源清單的json文件,以下css

clipboard.png
若是是服務器端構造的html,就能夠根據當前的manifest,引入css和js文件,並且這個文件是必須的,不然服務器端壓根不知道hash以後的JS文件名字和CSS名字。html

簡單說下webpack執行,取得webpack.config.js的配置和默認配置合併,而後執行plugin,這裏的執行其實只是簡單的綁定hooks,並不是執行裏面的邏輯,先看下源代碼,再給你們擼一擼這裏面的細節。webpack

clipboard.png

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

clipboard.png

在webpack開始編譯以前,就能觸發beforeRun鉤子,webpack-manifest-plugin就用到了當前的hook。所以雖然plugin註冊的早,但真正的執行順序在於它綁定的究竟是什麼樣的鉤子。無關於它在webpack配置中plugin裏面的順序。數組


上面都是前置知識,下面經過解讀一個plugin源碼來鞏固下。服務器

clipboard.png

先看一段簡單的源碼。
這裏他註冊了好幾個鉤子,咱們一個一個來講。
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);
      });
    });

clipboard.png

到這裏webpack-manifest-plugin的主功能就差很少了,將上面獲得的各類hash後的name保存到對象裏面,key就是chunk名(不必定準),但key具體是什麼不重要,到時候服務器端遍歷json的時候,判斷value的後綴便可,究竟是js,css或者其餘什麼的一目瞭然。
webpack-manifest-plugin還有一些細節處理,好比取到了publicPath,結合拿到的fileName,組成了文件的真正地址。

plugin其實還能夠展開不少內容講,但官網都有,不少時候也不用咱們去寫plugin,網上大把,咱們只須要知道,他的基本原理便可。hooks,訂閱發佈等。

相關文章
相關標籤/搜索