這是一個系列的文章,目前一共有3篇,是原做者在去年開始連載的系列教程, 我看了一下沒看太懂, 翻譯出來,你們探討一下, 這個是第二部分, 第一部分是webpack 的各個包的功能介紹.就不翻譯了.想看的就按原文連接 你就能找到所有的系列vue
就算這篇教程和上一篇教程都是關於如何向webpack貢獻代碼的,可是我想先花費一些時間給大家說一下你將會在不少項目中看見的範例(不少項目指的應該是 webpack 裏面分佈的包)webpack
注意: 對於想向webpack 貢獻代碼的小夥伴, 或者想本身寫插件的小夥伴,這對大家尤爲有用.git
就像上一部分說的,tapable 是webpack 的核心構建塊,(webpack是又不少個塊組成的),類和對象都繼承tapable是tapable 的實例,下面有一個很是簡單的例子.github
const Tapable = require('tapable'); class Compiler extends Tapable { constructor() { this.foo = "43"; this.applyPluginsAsync("run", this, function(err, done) { if (done) {this.doRunStuffAfterSuccess()} } this.applyPlugins("done", stats); } }
tapable 添加了插件能夠掛鉤進去的事件觸發功能, 你能夠在你使用的任何webpack庫中搜索this.applyPlugins 找到掛鉤的事件.(通常是插件源碼)web
一個webpack 插件的樣子最好描述成一個實現了 apply() 方法的類,這個方法會在tapable 實例(一般指Compiler)的初始化事件鉤子中被調用,體驗一下下面的例子.設計模式
class MyFirstPlugin { apply(compiler) { compiler.plugin("run", function(compiler, cb) { console.log("webpack is about to start bundling"); cb(); // cb() signals to the compiler that this asnyc hook is finished. }); compiler.plugin("done", function(stats) { console.log("webpack is finished bundling"); }); } }
這裏有幾個關鍵的點架構
.plugins
函數,而後指定事件的名字,和一個執行你的邏輯的回調.tapable實例經過調用apply方法,傳入一個nwe 出來的插件實例來註冊插件,例如,若是咱們要註冊上面的插件,咱們只須要這樣寫,compiler.apply(new MyFirstPlugin())
app
webpack 的插件都是設計成單一目的的,也就是一個插件只能有一個功能.觀察下面的代碼;異步
var SingleEntryPlugin = require("./SingleEntryPlugin"); var MultiEntryPlugin = require("./MultiEntryPlugin"); function EntryOptionPlugin() {} module.exports = EntryOptionPlugin; EntryOptionPlugin.prototype.apply = function(compiler) { compiler.plugin("entry-option", function(context, entry) { function itemToPlugin(item, name) { if(Array.isArray(item)) return new MultiEntryPlugin(context, item, name); else return new SingleEntryPlugin(context, item, name); } if(typeof entry === "string" || Array.isArray(entry)) { compiler.apply(itemToPlugin(entry, "main")); } else if(typeof entry === "object") { Object.keys(entry).forEach(function(name) { compiler.apply(itemToPlugin(entry[name], name)); }); } return true; }); };
EntryOptionPlugin’s
惟一的目的就是要鉤(這裏的勾是鉤子函數的概念)進去compiler實例,以得到全部在配置文件裏面定義的對象的入口點,而後轉換爲SingleEntryPlugin
實例 或者MultiEntryPlugin
實例的值,而後把這些插件傳遞迴compiler.aaply()
去註冊他們.函數
學習源碼,寫你本身的插件,問問題,作筆記,使用這些難以置信(估計做者在這裏幽默了一番,這些方法並不難以執行)的方法,你不只能學會屬於本身的技能,還可讓你成爲webpack的下一個貢獻者,最後在一天結束的時候,感到頗有趣.
如今你在webpack 和他的插件系統如何工做上有必定的瞭解,讓咱們來看一下被webpack 使用的tapable.
run
和 emit
這樣的事件.Compiler
類返回Compilation‘s
, 這是你的應用的依賴圖的入口,Compilation
包含了optimize-modules
, seal
and optimize-chunk-assets
這樣的鉤子,全部的優化,和總體程序的編譯,和工具,都會在Compilation
執行..
這個插件建立的.插入webpack解析器的插件,是用於定製模塊解析策略(詳情請了解策略模式)的,你的webpack的配置的resolve
對象的全部屬性對應於已經應用的指定的插件解析器.resolver
, loader
和 NormalModule
的建立物綁定在一塊兒,你會用到的生命週期鉤子包括before-resolve
, after-resolve
, 和 create-module
, 除此以外,loaders 針對每個模塊運行,他能夠從他們的原的文件,轉換成能夠被添加進入webpack的 chunk
的東西(例如vue-loader 就會把vue文件轉換成 對象)MainTemplate
(運行時 綁定(bundle)包裝器), ChunkTemplate
等等....(這裏我建議大家看原版吧,實在翻譯不出)acorn
ast 分析器 提供功能的tapable 實例.前面全部的類均可以發出Tapable事件所以能夠爲他們編寫插件.
譯者注: 原文下面都是一些讓你努力學習,每天向上,讓你選擇一個源碼去看,而後是最緊要系你以爲開心,之類的話,我選擇不譯.
tapable 庫已經通過更新, 上面提到的方法已經廢棄了,可是基本架構並無改變, 具體請關注github的tapable倉庫