啓動webpack構建的準備工做

摘要

webpack本質是一個工具,這個工具的內部體系其實很是龐大複雜,它在支持高度可配置的同時(可以使用自定義的打包方式及loader和plugin),又作到了開箱即用(咱們在使用webpack的時候幾乎能夠什麼都不配置)。node

若是咱們本身寫一個工具,咱們會怎麼開啓用戶的使用之旅,怎麼引導用戶去進行正確的配置和使用,怎麼收集用戶的配置,怎麼判斷用戶輸入的配置符合規範,怎麼去友好提示用戶進行正確配置,怎麼設置默認配置。。。 這一章,咱們來看看webpack是怎麼作的。webpack


命令行腳本


一切開始於webpack的安裝,執行'npm install webpack'以後,找到node_modules下的webpack,在package.json裏邊,注意兩個屬性:"main"和"bin",前者是模塊的主入口文件,咱們在項目裏邊reqire('webpack')時,引入的其實就是main屬性所指向的文件,後者是可執行的node腳本,咱們在控制檯執行'npm run webpack'的時候,執行的就是這個文件。web


在這個可執行文件裏邊,主要作了一件事,獲取webpack的CLI工具包並執行,有兩個選擇供咱們安裝,官方更推薦webpack-cli,webpack-command已經再也不維護(webpack4版本之前,webpack和webpack-cli是放在一塊兒的)。npm


這個腳本里邊,做者使用了node提供的require模塊,經過在一個try...catch語句裏執行require.resolve('模塊名'),來判斷是否安裝了CLI包;經過判斷本地是否存在yarn.lock文件來判斷是否使用的yarn;使用child_process模塊執行命令;使用readline模塊獲取用戶輸入的命令。json

不過這個地方有一個可優化的小點,就是在提示用戶未安裝CLI工具時,是經過遍歷數組CLIs,判斷數組對象的recommended字段,然而在真正安裝包的時候,用的是經過寫死的包名webpack-cli。這可能會致使之後不管如何修改對象的recommended屬性,安裝的都是webpack-cli。數組


webpack-cli


咱們在摘要裏邊最後提的幾個問題,答案都在webpack-cli裏邊。緩存

webpack-cli自己提供了幾個命令任務:init、info、server、migrate等,輸入不一樣的命令(eg. webpack-cli init),都會觸發判斷、安裝、執行相應模塊的操做,具體步驟跟webpack的命令行腳本差很少。咱們看下包裏的文件:markdown



第一階段 options獲取

配置參數的獲取,主要依賴yargs模塊,它主要用來管理命令行參數。函數


第一步,定義一個options數組,用來存放收集到的配置數據,這些數據包括webpack運行的全部配置信息,至關因而啓動webpack的一把鑰匙;工具

第二步,肯定配置渠道,webpack-cli支持從命令行輸入文件地址或者經過本地文件進行配置,前者直接拿到文件的路徑;後者經過正則匹配,使用find-sync模塊同步地查找本地配置文件,來配置文件路徑。這裏有一個技巧,因爲webpack支持不一樣語言的配置,所以就須要處理獲取文件的格式並引入相應的loader(此處使用了interpret模塊),文件格式有幾十種,代碼先將文件格式按長度由短到長進行排序,將'.js'排在第一位,由於大部分仍是js文件,這樣在遍歷查找的時候每每第一步就能夠查到返回,大大提高了效率,且indexOf第二個參數傳的很巧妙,如圖:


第三步,require配置文件並收集(而不是解析)配置數據,由於webpack支持多種配置類型,好比導出一個函數、一個Promise、一個或多個多個配置對象等,此時,全部的配置數據收集完畢;

第四步,獲取最終的標準配置對象,拿到配置數據後,先進行校驗,配置字段不符合規範的話,會提示報錯信息並終止程序,校驗函數是webpack提供的(依賴Ajv模塊);其次,解析配置數據,經過一系列的函數處理,將webpack須要的配置字段依次地寫入options,同時作一些默認處理,好比設置默認的main入口;一些特定模式的配置會對應一些插件,它會默認去添加這些插件,好比配置熱更新模式的話會會默認在plugins裏邊添加HotModuleReplacementPlugin插件;最後,根據命令行輸入的其餘參數,繼續豐富options對象,好比咱們經常使用的監聽模式,就會將options.watch設置爲true。


第二階段 啓動webpack

通過第一階段,啓動webpack的這把"鑰匙"就打造好了。

第一步,肯定輸出信息。輸入信息有了,那麼輸出的bundle信息呢,咱們能夠給stats一個字符串,去指定任意一種模式(webpack提供了6種輸出模式),或給stats一個對象,去更細粒度地控制是否要展現某一個特定的字段;

第二步,實例化webpack並傳入options對象,賦給compiler,這個compiler就是webpack的化身了,掌控者webpack執行整個的生命週期。根據用戶自定義的配置,決定如何監控編譯進度,從而在compiler對象提供的鉤子上訂閱一些事件。同時定義了一個lastHash變量,它存儲的是每一輪webpack編譯對應的hash值,只有當這個值變化的時候纔會執行一些操做,這樣就避免了浪費,同時,若是是非監聽模式,在compiler.close()的回調裏邊會清除緩存。最後,根據配置狀況,去執行compiler.watch() 或者 compiler.run()。至此,初始化工做就差很少完成了,剩下的交給了webpack模塊。這個第二步,都匯聚在這張圖:

相關文章
相關標籤/搜索