對於webpack的認識始終停留在對腳手架的使用,不得不說腳手架既方便又好用,修改起來也方便,只需要知道webpack中各個配置項的功能,於是對於我們來說,webpack始終就是一個黑盒子,我們完全不清楚里面是如何去運作的。打包時報錯,就只能借助google來協助幫忙解決問題,至於為什么要這樣解決,什么原理,不管,能解決就好。那么,了解一下基本原理也是有必要。
概念
言歸正傳,我們一起了解一下webpack運行基本原理,首先先明白幾個核心概念,
- Entry:入口,webpack構建的起始
- Module:模塊,webpack里面一切皆模塊,也是代表着文件,從Entry配置的入口文件開始,遞歸找出依賴的模塊
- Chunk:代碼塊,找出遞歸依賴模塊經轉換后組合成代碼塊
- Loader:模塊轉換器,也就是將模塊的內容按照需求裝換成新內容
- Plugin:擴展插件,webpack構建過程中,會在特定的時機廣播對應的事件,而插件可以監聽這些事件的發生
流程
webpack構建流程,詳細過程如下:
- 初始化:從配置文件或是shell讀取與合並參數,得到最終參數,實例化插件new Plugin()
- 開始編譯:通過上一步初始化得到的最終參數,初始化一個Compiler對象,加載插件(依次調用插件中的apply方法),通過執行Compiler.run開始編譯
- 確定入口:根據配置中entry找出所有入口文件
- 編譯模塊:從entry出發,調用配置的loader,對模塊進行轉換,同時找出模塊依賴的模塊(如何找?見下文),依次遞歸,直到所有依賴模塊完成本步驟處理
- 完成模塊編譯:這一步已經使用loader對所有模塊進行了轉換,得到了轉換后的新內容以及依賴關系
- 輸出資源: 根據入口與模塊之間的依賴關系,組裝成一個個chunk代碼塊,並且生成文件輸出列表
- 輸出成功:根據配置中的輸出路徑和文件名,將文件寫入文件系統,完成構建
事件
整個構建流程會發生很多的事件,來供Plugin監聽,這些事件具體的可以分為三個階段,分別是初始化階段
、編譯階段
、輸出階段
,那么具體有哪些事件,這里按階段分別介紹,
初始化階段
事件 | 作用 |
---|---|
初始化 | 從配置文件或是shell讀取與合並參數,得到最終參數,依次實例化插件new Plugin() |
實例化Compiler | 通過上一步初始化得到的最終參數,初始化一個Compiler對象,負責監聽文件和啟動編譯,全局只有一個Compiler對象 |
加載插件 | 依次調用插件中的apply方法,同時也會將Compiler實例傳入,就可以調用Webpack提供的api,Compiler實例可以說是就是Webpack的實例 |
environment | 將node.js風格的文件系統應用到compiler對象,便可以直接通過compiler來對文件進行操作 |
entry-option | 讀取配置中的entry,依次實例化出對應EntryPlugin,為后面該entry的遞歸解析工作做准備 |
after-plugins | 調完所有內置和配置的插件的apply方法 |
after-resolvers | 根據配置初始化resolvers,resolvers負責在文件系統中尋找制定路徑的文件 |
編譯階段
事件 | 作用 |
---|---|
run | 啟動一次新的編譯,調用Compiler.run() |
watch-run | 和run類似,區別在於它是在監聽模式下進行編譯的,這個事件可以獲取哪些文件發生了變化從而導致新的一次編譯 |
compile | 告訴插件新的一次編譯即將啟動,並且給插件帶上compiler對象 |
compilation | 每當檢測到文件的變化,都會有一次新的compilation被創建,一個compilation對象包含了當前的模塊資源、編譯生成的資源、變化的文件等等的屬性和方法,同時記住,在很多事件的的回調中都會將compilation傳入,以便使用 |
make | 一個新的Compilation創建完畢,那么就會從entry配置中開始讀取文件,使用配置好的loader對文件進行編譯,編譯完后再找出文件依賴的文件,遞歸地去編譯和解析 |
after-compile | 一次Compilation執行完成 |
invalid | 文件編譯錯誤等異常觸發該事件,不會導致webpack退出 |
Compilation的事件
事件 | 作用 |
---|---|
build-moudle | 使用對應的loader去轉換一個模塊 |
normal-module-loader | 在用loader轉換一個模塊后,會使用acorn解析轉換后的內容輸出對應的抽象語法樹(ast),以便webpack后面分析代碼使用 |
program | 從配置的入口開始,分析生成的ast,遇到require等導入語句時,便會將其加入依賴模塊列表,並且對找出的依賴進行遞歸分析,最終可以弄清所有依賴關系 |
seal | 所有模塊及其依賴的模塊都通過Loader轉換完成,根據依賴關系生成chunk |
輸出階段
事件 | 作用 |
---|---|
should-emit | 所有需要輸出的文件都生成,准備輸出,詢問哪些文件需要輸出,哪些不需要輸出 |
emit | 確定好要輸出哪些文件后,並執行文件輸出,可以在這里獲取和修改輸出的內容 |
after-emit | 文件輸出完畢 |
done | 完成一次完整的編譯和輸出流程 |
failed | 編譯和輸出過程中運到異常,導致webpack退出,會直接到這個步驟,可以在這里獲取具體原因 |
總結
Webpack是很好的前端資源加載和打包工具,在webpack里一切皆模塊
,很好地處理文件之間的依賴關系,這里我們介紹的是些理論性的知識,了解基本概念,知道整個流程是怎么樣的,webpack是串行流水線運行的,工作期間會有很多廣播事件,來供插件使用,這里我們介紹了各個階段的事件以及作用,具體代碼表示形式,后續文章會引入。