webpack進階-工做原理

webpack雖然使用簡單,可是它對於使用者就是一個黑盒。webpack

魯迅說:若是你對一個事物原理不瞭解,那麼你不可能熟練駕馭它。web

若是有不熟悉webpack基本使用的小夥伴們,能夠查看我以前的分享,能夠狠狠的點擊這裏:https://segmentfault.com/a/11...segmentfault

一. 流程概覽

  1. 校驗options參數是否合法,options參數和命令行中的參數合併
  2. 實例化Compiler對象,初始化全部配置插件 (compiler類繼承自Tapable),掛載hooks。
  3. 依次調用plugin的 apply 方法,讓插件能夠監聽後續的全部事件節點。
  4. 執行compiler.run方法,此方法實際上實例化Tapable中的AsyncSeriesHook(['compiler'])
  5. 找到主入口,入口可能會有多個,這個取決config文件是否配置多個entry
  6. 建立compilation對象,執行對應的回調。 包括: 進入每個entry -> 使用loader進行編譯 -> acorn解析AST -> 遞歸執行全部文件 -> 所有執行完成後執行compilation seal方法,對每一個chunk進行整理,優化,封裝。
  7. Tapable廣播emit事件,全部文件編譯完成而且輸出,這個時候還在內存中,能夠獲取全部文件信息和chunk的各類信息
  8. 文件寫入磁盤完成,Tapable廣播afterEmit事件
  9. 完成 編譯,Tapable廣播Done事件

二. Tapable

咱們能夠把webpack理解爲一條生產線,須要通過一系列處理流程後才能將源文件轉換成輸出結果。這條生產線上的每一個處理流程的職責都是單一的,多個流程之間會存在依賴關係,只有完成當前處理後才能交給下一個流程去處理。promise

咱們的插件就像一個插入到生產線中的一個功能,在特定的時機對生產線上的資源會作處理。webpack它是經過 Tapable來組織這條複雜的生產線的。數據結構

webpack在運行的過程當中會廣播事件,插件只須要關心監聽它的事件,就能加入到這條生產線中。而後會執行相關的操做。webpack的事件流機制它能保證了插件的有序性,使整個系統的擴展性好。事件流機制使用了觀察者模式來實現的。app

總的來講,tapable暴露了3種hooks:異步

  • tap (同步鉤子)
  • tapAsync (異步鉤子)
  • tapPromise(異步promise鉤子)

經常使用事件流以下:

事件名稱 說明
entryOption 初始化options
run 開始編譯
make 從entry開始,遞歸分析依賴,並對依賴進行build
build-module 使用loader加載文件,並build模塊
normal-module-loader 對loader的文件進行acorn編譯,生成抽象語法樹AST
program 開始對AST進行遍歷,當遇到require時觸發call require事件
seal 全部依賴build完成,開始對chunk進行優化(抽取公共模塊、加hash等)
optimize-chunk-assets 壓縮代碼
emit 把各個chunk輸出到結果文件

三. compiler

compiler對象 是Compiler類的實例對象, 而Compiler類繼承自Tapable,webpack在啓動時,會實例化一次compiler,後續每次文件的改動,都會建立一個compilation對象。優化

Compiler 負責文件監聽和啓動編譯。Compiler 實例中包含了完整的 Webpack 配置,全局只有一個 Compiler 實例ui

compiler對象,大體數據結構以下:spa

image.png

咱們在開發自定義插件時,webpack會調用插件類的apply方法,傳入compiler,咱們就能夠在tapable廣播事件流時,自定義作一些事件啦~

掌握webpack的工做原理,對咱們後續開發本身的loader, plugin有極大的好處。後面我將分享,如何開發本身的plugin。碼字不易,多多關注~😙

相關文章
相關標籤/搜索