webpack 可謂是讓人欣喜又讓人憂,功能強大但需要一定的學習成本。在探尋 webpack 外掛程式機制前,首先需要了解一件有意思的事情,webpack 外掛程式機制是整個 webpack 工具的骨架,而 webpack 本身也是利用這套外掛程式機制構建出來的。因此在深入認識 webpack 外掛程式機制後,再來進行專案的相關優化,想必會大有裨益。
先來瞅瞅 webpack 外掛程式在專案中的運用
const myplugin = require('myplugin')
const webpack = require('webpack')
webpack()
那麼符合什麼樣的條件能作為 webpack 外掛程式呢?一般來說,webpack 外掛程式有以下特點:
獨立的 js 模組,暴露相應的函式
compiler 物件上掛載了相應的 webpack 事件鉤子
事件鉤子的**函式裡能拿到編譯後的 compilation 物件,如果是非同步鉤子還能拿到相應的 callback
下面結合**來看看:
function myplugin(options) {}
// 3.compiler 物件上掛載了相應的 webpack 事件鉤子 4.事件鉤子的**函式裡能拿到編譯後的 compilation 物件
compiler.plugin('emit', (compilation, callback) => )
}// 1.獨立的 js 模組,暴露相應的函式
module.exports = myplugin
這樣子,webpack 外掛程式的基本輪廓就勾勒出來了,此時疑問點有幾點,
const webpack = (options, callback) =>
...}
疑問 2:compiler 物件是什麼呢?
疑問 3:compiler 物件上的事件鉤子是怎樣的?
疑問 4:事件鉤子的**函式裡能拿到的 compilation 物件又是什麼呢?
這些疑問也是本文的線索,讓我們乙個個探索。
compiler 即 webpack 的編輯器物件,在呼叫 webpack 時,會自動初始化 compiler 物件,原始碼如下:
// webpack/lib/webpack.js
const compiler = require("./compiler")
const webpack = (options, callback) =>
...}
終上,compiler 物件中包含了所有 webpack 可配置的內容,開發外掛程式時,我們可以從 compiler 物件中拿到所有和 webpack 主環境相關的內容。
compilation 物件代表了一次單一的版本構建和生成資源。當執行 webpack 時,每當檢測到乙個檔案變化,一次新的編譯將被建立,從而生成一組新的編譯資源。乙個編譯物件表現了當前的模組資源、編譯生成資源、變化的檔案、以及被跟蹤依賴的狀態資訊。
結合原始碼來理解下上面這段話,首先 webpack 在每次執行時會呼叫compiler.run()
(原始碼位置),接著追蹤 oncompiled 函式傳入的 compilation 引數,可以發現 compilation 來自建構函式 compilation。
// webpack/lib/compiler.js
const compilation = require("./compilation");
newcompilation(params)
再介紹完 compiler 物件和 compilation 物件後,不得不提的是 tapable 這個庫,這個庫暴露了所有和事件相關的 pub/sub 的方法。而且函式 compiler 以及函式 compilation 都繼承自 tapable。
事件鉤子其實就是類似 mvvm 框架的生命週期函式,在特定階段能做特殊的邏輯處理。了解一些常見的事件鉤子是寫 webpack 外掛程式的前置條件,下面列舉些常見的事件鉤子以及作用:
鉤子作用
引數型別
after-plugins
設定完一組初始化外掛程式之後
compiler
sync
after-resolvers
設定完 resolvers 之後
compiler
sync
run在讀取記錄之前
compiler
async
compile
在建立新 compilation 之前
compilationparams
sync
compilation
compilation 建立完成
compilation
sync
emit
在生成資源並輸出到目錄之前
compilation
async
after-emit
在生成資源並輸出到目錄之後
compilation
async
done
完成編譯
stats
sync
完整地請參閱官方文件手冊,同時瀏覽相關原始碼 也能比較清晰地看到各個事件鉤子的定義。
拿 emit 鉤子為例,下面分析下外掛程式呼叫原始碼:
compiler.plugin('emit', (compilation, callback) => )
此處呼叫的 plugin 函式源自上文提到的 tapable 庫,其最終呼叫棧指向了 hook.tapasync(),其作用類似於 eventemitter 的 on,原始碼如下:
// tapable.js
options => ;
if(options.async)
hook.tapasync(tapopt, options.fn); // 將外掛程式中非同步鉤子的**函式注入
else
hook.tap(tapopt, options.fn);
return true;
}};
有注入必有觸發的地方,原始碼中通過 callasync 方法觸發之前注入的非同步事件,callasync 類似 eventemitter 的 emit,相關原始碼如下:
this.hooks.emit.callasync(compilation, err => );
一些深入細節這裡就不展開了,說下關於閱讀比較大型專案的原始碼的兩點體會,
結合上述知識點的分析,不難寫出自己的 webpack 外掛程式,關鍵在於想法。為了統計專案中 webpack 各包的有效使用情況,在 fork webpack-visualizer 的基礎上對**公升級了一番,專案位址。效果如下:
外掛程式核心**正是基於上文提到的 emit 鉤子,以及 compiler 和 compilation 物件。**如下:
class analyzewebpackplugin )
const self = this
compiler.plugin("emit", function (compilation, callback) ) // 獲取各個模組的狀態
let stringifiedstats = json.stringify(stats)
// 服務端渲染
let html = `
analyzewebpackplugin`
compilation.assets[`$`] =
callback()
})}}
看清楚真正的 webpack 外掛程式
webpack 官網
DISCUZ 外掛程式機制
1 參考 2 由第一點中的官方提供的參考庫可以基本可以了解怎麼去開發乙個外掛程式。這裡簡述幾點重要的 一 配置檔案中config global.php中加上 config plugindeveloper 1 就可以在後台 應用 外掛程式 中設計新外掛程式。將上述變數中的值設定成為2,就可以看disc...
jQuery 外掛程式機制
簡介 利用jquery提供的 fn.extend 和 extend 方法,擴充套件 extend 擴充套件jquery的類方法 作用 1.合併物件 var a var b 後面加到前面,屬性相同的後面覆蓋前面的屬性 console.log extend a,b 2.擴充套件jquery類方法 var...
jQuery外掛程式機制
為了擴充套件jquery庫函式,jquery提供了兩種方式 jquery.extend object 擴充套件jquery物件本身,主要是用來擴充套件jquery全域性函式 呼叫時直接 函式名 引數 如下例子 jquery.fn.extend object 擴充套件 jquery 元素集,主要用於擴...