我們經常使用到webpack的插件功能,那如何開發一個自定義的插件呢?首先創建插件比創建 loader 更加高級,webpack 插件由以下組成:
- 一個 JavaScript 命名函數。
- 在插件函數的 prototype 上定義一個 apply 方法。
- 指定一個綁定到 webpack 自身的事件鈎子。
- 處理 webpack 內部實例的特定數據。
- 功能完成后調用 webpack 提供的回調。
下面就一點點的帶你開發一個自定義的webpack plugin.
先說說webpack插件中的兩位重要人物,Compiler和Compliation
- compiler 對象代表了完整的 webpack 環境配置。這個對象在啟動 webpack 時被一次性建立,並配置好所有可操作的設置,包括 options,loader 和 plugin。當在 webpack 環境中應用一個插件時,插件將收到此 compiler 對象的引用。可以使用它來訪問 webpack 的主環境。
- compilation 對象代表了一次資源版本構建。當運行 webpack 開發環境中間件時,每當檢測到一個文件變化,就會創建一個新的 compilation,從而生成一組新的編譯資源。一個 compilation 對象表現了當前的模塊資源、編譯生成資源、變化的文件、以及被跟蹤依賴的狀態信息。compilation 對象也提供了很多關鍵時機的回調,以供插件做自定義處理時選擇使用。
基礎插件架構
///src/plugins/helloPlugin.js
// 命名函數。
function HelloPlugin(options) {
// 使用 options 設置插件實例……
console.log(options);
}
//插件函數的 prototype 上定義一個 apply 方法
HelloPlugin.prototype.apply = compiler => {
//hooks
compiler.hooks.done.tap('HelloPlugin', status => {
console.log(status.toJson());
})
// 舊版本的相關鈎子
//compiler.plugin('done' , () => {
// console.log('hello world');
//})
// 設置回調來訪問 compilation 對象:
//compiler.plugin('compilation', compilation => {
// 現在,設置回調來訪問 compilation 中的步驟:
// compilation.plugin('optimize', () => {
console.log('optimize');
//})
//})
}
module.exports = HelloPlugin
//webpack.config.js
const HelloPlugin = require('./src/plugins/helloPlugin')
plugins: [
new HelloPlugin({options:true})
]
這樣基礎架構就搭建完成了.
認識一下事件鈎子
生命周期鈎子函數,是由 compiler 暴露,可以通過如下方式訪問:
compiler.hooks.someHook.tap(...)
取決於不同的鈎子類型,也可以在某些鈎子上訪問 tapAsync 和 tapPromise。
例如
// 在處理來自webpack選項的entry配置后調用
compiler.hooks.entryOption.tap('HelloPlugin', (context, entry) => {
console.log(1,context, entry);
})
也支持自定義鈎子函數
// 自定義hook
const SyncHook = require('tapable').SyncHook;
// 具有 `apply` 方法……
if (compiler.hooks.myCustomHook) throw new Error('Already in use');
compiler.hooks.myCustomHook = new SyncHook(['a', 'b', 'c'])
// 在你想要觸發鈎子的位置/時機下調用……
compiler.hooks.myCustomHook.call(a, b, c);
學會了webpack的事件生命周期鈎子函數,那么下面我們就開始着手寫一個webpack插件.
生成一個展示打包完成后的文件列表,ok,直接上代碼
// 命名函數。
function HelloPlugin(options) {
// 使用 options 設置插件實例……
console.log(options);
}
//插件函數的 prototype 上定義一個 apply 方法
HelloPlugin.prototype.apply = compiler => {
// 在將資產釋放到輸出目錄后調用。
compiler.hooks.emit.tapAsync('HelloPlugin', (compilation, callback) => {
let fileList = `## in this build:\n\n`
console.log(compilation.assets);
const assets = compilation.assets
for(let key in assets){
console.log(key);
fileList+=`${key}\n`
}
compilation.assets['fileList.md'] = {
source:()=>{return fileList},
size:() => {return fileList.length}
}
callback()
})
}
module.exports = HelloPlugin
看,根據不同的webpack生命周期事件鈎子函數,處理不同的邏輯,就可以完成一個webpack的plugin了,你學會了嗎?
關於深入學習請參考:

如果覺得文章不錯,可以給小編發個紅包給予鼓勵.
