W3Cschool
恭喜您成為首批注冊用戶
獲得88經(jīng)驗值獎勵
插件是 webpack 生態(tài)的關鍵部分, 它為社區(qū)用戶提供了一種強有力的方式來直接觸及 webpack 的編譯過程(compilation process)。 插件能夠 hook 到每一個編譯(compilation)中發(fā)出的關鍵事件中。 在編譯的每個階段中,插件都擁有對 ?compiler
? 對象的完全訪問能力, 并且在合適的時機,還可以訪問當前的 ?compilation
? 對象。
讓我們首先從 tapable 工具開始, 它為 webpack 插件接口提供了核心能力的。
這個小型庫是 webpack 的一個核心工具,但也可用于其他地方, 以提供類似的插件接口。 在 webpack 中的許多對象都擴展自 ?Tapable
? 類。 它對外暴露了 ?tap
?,?tapAsync
? 和 ?tapPromise
? 等方法, 插件可以使用這些方法向 webpack 中注入自定義構(gòu)建的步驟,這些步驟將在構(gòu)建過程中觸發(fā)。
請查閱文檔了解更多知識。 理解上面的的三種 ?tap
? 方法, 以及提供這些方法的鉤子(hooks)對于編寫插件來說是至關重要的。 那些擴展自 ?Tapable
? 的對象(例如:compiler), 以及其提供的鉤子(hooks)和每個鉤子的類型(例如:?同步鉤子(SyncHook)
?)值得關注。
根據(jù)使用不同的鉤子(hooks)和 ?tap
? 方法, 插件可以以多種不同的方式運行。 這個工作方式與 Tapable 提供的鉤子(hooks)密切相關。 compiler hooks 分別記錄了 Tapable 內(nèi)在的鉤子, 并指出哪些 tap 方法可用。
所以,依賴于使用的 ?tap
? 方法的不同, 插件可能會以不同的方式運行。 例如:當你鉤入到 ?編譯(compile)
? 階段時,只有同步的 ?tap
? 方法可以使用。
compiler.hooks.compile.tap('MyPlugin', (params) => {
console.log('以同步方式觸及 compile 鉤子。');
});
然而,對于可以使用 ?AsyncHook
? 的 ?run
? 階段, 則需使用 ?tapAsync
? 或 ?tapPromise
?(以及 ?tap
?)方法。
compiler.hooks.run.tapAsync(
'MyPlugin',
(source, target, routesList, callback) => {
console.log('以異步方式觸及運行鉤子。');
callback();
}
);
compiler.hooks.run.tapPromise('MyPlugin', (source, target, routesList) => {
return new Promise((resolve) => setTimeout(resolve, 1000)).then(() => {
console.log('以異步的方式觸發(fā)具有延遲操作的鉤子。');
});
});
compiler.hooks.run.tapPromise(
'MyPlugin',
async (source, target, routesList) => {
await new Promise((resolve) => setTimeout(resolve, 1000));
console.log('以異步的方式觸發(fā)具有延遲操作的鉤子。');
}
);
這些需求(story)的含義在于, 我們可以有多種方式 hook 到 compiler 中,可以讓各種插件都以合適的方式去運行。
為了便于其他插件的編譯過程中可以 ?tap
? 到, 你可以這樣做:
WeakMap
? for compilation hooks:const compilationHooks = new WeakMap<Compilation, MyHooks>();
interface MyHooks {
custom: SyncHook<[number, string]>;
}
static getCompilationHooks(compilation: Compilation) : MyHooks {
let hooks = compilationHooks.get(compilation);
if(hooks === undefined) {
compilationHooks.set(compilation, hooks = {
custom: new SyncHook()
});
}
return hooks;
}
const hooks = MyPlugin.getCompilationHooks(compilation);
hooks.custom.call(1, 'hello');
import MyPlugin from 'my-plugin';
const hooks = MyPlugin.getCompilationHooks(compilation);
hooks.custom.tap('OtherPlugin', (n, s) => {
// magic
});
再次聲明, 查看 ?tapable
? 文檔 來了解更多不同的鉤子類(hook class),以及它們是如何工作的。
插件能夠通過 ?ProgressPlugin
? 這個在默認情況下將信息打印到標準錯誤輸出(stderr)的插件來進行進度報告。如果想要使用這個功能,只需要在使用 webpack CLI 的時候傳入 ?--progress
? 參數(shù)。
如果想要自定義打印輸出,只需要傳遞不同的參數(shù)到 ?ProgressPlugin
? 的? reportProgress
? 方法。
如果想要報告進度,插件必須在 ?tap
? 到 hook 的時候使用 ?context: true
? 選項。
compiler.hooks.emit.tapAsync(
{
name: 'MyPlugin',
context: true,
},
(context, compiler, callback) => {
const reportProgress = context && context.reportProgress;
if (reportProgress) reportProgress(0.95, 'Starting work');
setTimeout(() => {
if (reportProgress) reportProgress(0.95, 'Done work');
callback();
}, 1000);
}
);
?reportProgress
? 方法在被調(diào)用的時候會傳入以下的參數(shù):
reportProgress(percentage, ...args);
percentage
?:此參數(shù)未使用。作為代替,?ProgressPlugin
? 插件會基于當前的鉤子(hook)計算進度。...args
?:任意數(shù)量的字符串,這些字符串會傳遞給 ?ProgressPlugin
? 插件并報告給用戶。注意:
只有 compiler 和 compilation 鉤子的子集才支持 ?
reportProgress
? 方法。
日志的 API 在 webpack 4.37 版本后提供支持。當 ?logging
? 在 ?統(tǒng)計配置(stats configuration)
? 中可用和(或)當 ?infrastructure logging
? 可用的時候,插件會通過各自的記錄格式(stats,infrastructure)打印信息。
compilation.getLogger('PluginName')
? 來做記錄。這種形式的記錄保存在統(tǒng)計數(shù)據(jù)(Stats)中并做相應的格式化。它能夠被用戶過濾和導出。compilation.getInfrastructureLogger('PluginName')
? 來做記錄。使用 ?infrastructure
? 的形式并不會被保存在統(tǒng)計數(shù)據(jù)(Stats)中,因此也不會被格式化。它通常直接將記錄載入到 console/dashboard/GUI 中。它能夠被用戶過濾。compilation.getLogger
? ? ?compilation.getLogger('PluginName') : console
? 來檢測是否支持記錄,以此來在不支持 ?compilation.getLogger
? 方法的舊版本 webpack 中提供降級方法。查看 ?compiler hooks
? 部分, 了解所有可用的? compiler
? 鉤子以及它們提供的參數(shù)的詳細列表。
Copyright©2021 w3cschool編程獅|閩ICP備15016281號-3|閩公網(wǎng)安備35020302033924號
違法和不良信息舉報電話:173-0602-2364|舉報郵箱:jubao@eeedong.com
掃描二維碼
下載編程獅App
編程獅公眾號
聯(lián)系方式:
更多建議: