【筆記】Tapable原始碼解析圖以及webpack怎樣實現一個外掛plugin
阿新 • • 發佈:2020-08-05
Tapable原始碼解析圖,如圖所示:
一個webpack plugin由一下幾個步驟組成:
- 一個JavaScript類函式。
- 在函式原型 (prototype)中定義一個注入
compiler
物件的apply
方法。 apply
函式中通過compiler插入指定的事件鉤子,在鉤子回撥中拿到compilation物件- 使用compilation操縱修改webapack內部例項資料。
- 非同步外掛,資料處理完後使用callback回撥
開發webpack外掛還需要了解其中兩個核心的物件引用Compiler 和 Compilation,這裡需要理解清楚他們的含義。
compiler
物件代表了完整的 webpack 環境配置。這個物件在啟動 webpack 時被一次性建立,並配置好所有可操作的設定,包括 options,loader 和 plugin。當在 webpack 環境中應用一個外掛時,外掛將收到此 compiler 物件的引用。可以使用它來訪問 webpack 的主環境。compilation
物件代表了一次資源版本構建。當執行 webpack 開發環境中介軟體時,每當檢測到一個檔案變化,就會建立一個新的 compilation,從而生成一組新的編譯資源。一個 compilation 物件表現了當前的模組資源、編譯生成資源、變化的檔案、以及被跟蹤依賴的狀態資訊。compilation 物件也提供了很多關鍵時機的回撥,以供外掛做自定義處理時選擇使用。
實現一個如下需求的外掛,針對某個打包生成的JS,對其內容的頭部新增一個eslint語法檢測的忽略說明,那樣eslint就不會檢測當前打包的js,如下程式碼:
class ignoreEslintPlugin { constructor(options) {this.options = options; } apply(compiler) { compiler.hooks.emit.tap('ignoreEslintPlugin', (compilation) => { var topInfo = '/* eslint-disable */\n'; var content = topInfo + compilation.assets[this.options.filename].source(); // console.info(chalk.green(content)) compilation.assets[this.options.filename] = { source: () => content, size: () => content.length } }) } }
呼叫方式:
new ignoreEslintPlugin({filename: 'common.js'})
我們看下上面程式碼中的這個結構:
compiler.hooks.emit.tap('ignoreEslintPlugin', (compilation) => {
})
這一步主要是使用核心物件compiler的emit鉤子,通過.tap方法註冊到webpack中,在輸出構建產物到dist目錄之前執行。 在這裡列出compiler物件的生命週期鉤子
-> beforeRun 清除快取
-> run 註冊快取資料鉤子
-> beforeCompile
-> compile 開始編譯
-> make 從入口分析依賴以及間接依賴模組,建立模組物件
-> buildModule 模組構建
-> normalModuleFactory 構建
-> seal 構建結果封裝, 不可再更改
-> afterCompile 完成構建,快取資料
-> emit 輸出到dist目錄
參考地址:怎樣編寫一個簡單的webpack外掛