記錄一次Webpack插件優化的經歷

去年12月份,我一個才畢業半年的前端新人接觸了Webpack。跟着網上教程學習時,遇到了一個難題:文件名加上hash編碼後,屢次打包會有以前殘留的文件。 css

當時看的那篇文章,並無提到clean-webpack-plugin,因此我就傻傻的手動刪除。還很奇怪爲何這麼嚴重的問題沒人說過……其實就是當時google的關鍵字有問題,沒搜到正確的結果。前端

不過也是那次誤打誤撞,讓我開始維護一個本身的Webpack插件——webpack-remove-hashed-files。具體功能能夠看我以前的文章webpack

原本這個插件吧,功能也不是很複雜,因此我開發好初版後就沒管了。只有後面收到一封郵件,按要求我新增了白名單的功能。接着就擱置了三個月吧。git

不過呢,昨天在新項目裏須要用到幾個本地的圖片,因而就發現了一個buggithub

就是說,我在項目中原本要用file-loader去處理js和css中引入的本地圖片,將他們打包到dist文件夾下。而後呢,我打算把它們都放在dist/assets/images子文件夾下。因而就配置file-loader,option爲{name: 'assets/images/[name].[ext]'}web

然而就是這個配置致使個人刪除插件出了問題。segmentfault

原本我插件的設計是遍歷dist目錄,將全部文件的文件名與Webpack的compliation.assets的鍵名比較,若是文件名可以對應於某一個鍵名,說明是本次打包的內容,將其保留。其餘的都刪除。這是不考慮白名單的思路。數組

可是,不知道爲何,file-loader處理後的文件,在assets中是以相似於assets/images/a.jpg的鍵名保存的,這就致使遍歷dist文件夾時,我是用a.jpgassets/images/a.jpg作比較。雖然這是同一個文件,但實際上被誤認爲兩個文件,從而致使刪除bug。學習

那麼我該怎麼解決呢?測試

首先要明確問題出現所涉及到的兩個角色:file-loaderwebpack-remove-hashed-files。其次,可以修改的是file-loader的options與刪除插件的源碼。而個人目的就是要把全部圖片都存放在dist/assets/images文件夾下,因此file-loader的options是不能修改的,應該重構插件的源碼來適應file-loader的配置。

說實話,昨天想了一天才解決好這個問題。由於一直沒明白,file-loader究竟是怎麼作到又改文件名又能建立個新文件夾的……

繼續說怎麼修改刪除插件的源碼吧。我苦思冥想N個小時後,決定推翻之前的判斷邏輯。由於我想到了一個更簡單的判斷因素,並且這個因素纔是刪除插件的核心,只是一直被我忽略了。那就是【文件路徑】。

compliation.assets中,每一鍵對應一個文件對象,其中有一個字段existsAt代表打包後的文件所在的絕對路徑。那麼咱們先將這些路徑保存到一個數組dirArrays中,而後在遍歷dist下全部文件時,在dirArrays中搜索每一個不在白名單中的文件的絕對路徑,若是存在則保留;不存在則說明不是本次打包的內容,應該刪除。

聽上去是否是既不影響原有功能,並且還能解決file-loader的bug問題?另外還比以前的邏輯要簡單一些。

至於爲何說文件路徑是刪除插件的核心?由於插件實質上作了兩件事:比較assets與dist中全部文件、刪除非本次打包產生的文件。本來只有在刪除時纔要調用fs.unlink方法,傳入文件路徑參數。而如今在比較的時候就使用了文件路徑。說明它貫穿了本插件的全部流程,說是核心也不爲過了。

以上就是本次優化插件的完整記錄了,總結一下就是本身造的輪子要多測試多維護,這樣纔能有理由寫推廣的文章,讓更多人去使用hhh。

另外,在遇到bug後我分析了一下競品clean-webpack-plugin,發現它的思路跟去年我看得時候相比,仍是默認在生命週期emit時遍歷目標文件夾dist,若是文件不在白名單裏就直接刪除。這點也是它可以不受file-loader影響的緣由。

但也是我一開始文章中說過的,本次打包與上一次打包也許只有一個文件被修改,實際上只要刪除舊的這一個文件就行,但clean-webpack-plugin是將全部文件都刪除了。我以爲這一點在大項目中仍是會致使打包時間問題的,因此就本身造了個輪子。

還發現了一點,就是判斷了是否有compiler.hooks,這是Webpack 4的新特性。後面我再修補下這個問題。

最後,感謝閱讀。

相關文章
相關標籤/搜索