在上一篇文章Tapable中介紹了其概念和一些原理用法,和此次討論分析webpack plugin的關聯很大。下面從實現一個插件入手。
function FileListPlugin(options) {} FileListPlugin.prototype.apply = function(compiler) { compiler.plugin('emit', function(compilation, callback) { var filelist = 'In this build:\n\n'; for (var filename in compilation.assets) { filelist += ('- '+ filename +'\n'); } compilation.assets['filelist.md'] = { source: function() { return filelist; }, size: function() { return filelist.length; } }; callback(); }); }; module.exports = FileListPlugin;
說明 demo例子參考了webpack的官方文檔,使用這個簡短的demo做爲咱們分析的入口,一步一步來分析。
首先咱們寫插件都是這種結構形式,只有這樣webpack才能解析。而上面這個簡短的插件的做用是將build後asset目錄下的全部的文件遍歷後取出文件名,而後生成一個filelist.md文件。
原型上爲何要有apply方法呢?由於在安裝插件時,apply方法會被 webpack compiler 調用一次。調用的目的是爲了註冊你的邏輯,指定一個綁定到 webpack 自身的事件鉤子。webpack
webpack的事件鉤子有不少以下所示,列舉幾個比較重要經常使用的的,加深下印象git
- compile 編譯器開始編譯
- compilation 編譯器開始一個新的編譯過程
- emit 在生成資源並輸出到目錄以前
- done 完成編譯
查看更多事件鉤子
在上一篇文章中分析談到過compiler是繼承自tapable,正是由於它mix了Tapable 類,才具有註冊和調用插件功能,而執行plugin方法其實就至關hook.tap(tapOpt, options.fn)進行存儲, 而後webpack在啓動運行期間,到達某個階段,就會觸發調用相應的事件。額外傳入一個 callback 回調函數,只有在插件中操做是異步的時候才須要,同步操做不須要傳入和執行這個callback。
還有一點須要注意的是compiler和compilation區別?github
compiler 對象表明了完整的 webpack 環境配置。這個對象在啓動 webpack 時被一次性創建,並配置好全部可操做的設置,包括 options,loader 和 plugin。當在 webpack 環境中應用一個插件時,插件將收到此 compiler 對象的引用。可使用它來訪問 webpack 的主環境。compilation 對象表明了一次資源版本構建。當運行 webpack 開發環境中間件時,每當檢測到一個文件變化,就會建立一個新的 compilation,從而生成一組新的編譯資源。一個 compilation 對象表現了當前的模塊資源、編譯生成資源、變化的文件、以及被跟蹤依賴的狀態信息。compilation 對象也提供了不少關鍵時機的回調,以供插件作自定義處理時選擇使用。web
const FileListPlugin = require('fileList'); module.exports = { entry: './src/main.js', output:{ path: path.join(__dirname,'dist'), filename: '[name].js' }, plugins: [ new FileListPlugin({options: true}) ] }
輸出結果
segmentfault
demo完整連接api
參考連接app
https://doc.webpack-china.org...
https://doc.webpack-china.org...
https://webpack.js.org/contri...異步