從 Webpack 到 Ykit —— 前端工程構建實踐

在 JavaScript 應用越發多樣化和越發複雜的趨勢下,也給構建帶來了越來越多的挑戰。在公司級別的環境下,搭建一個基礎環境就要耗費半天,已經輸在了起跑線上。我們希望有一個工具來使開發同學專注於研發本身。本文會介紹基於 Webpack 實現的構建工具 Ykit,以及它在去哪兒網的實踐。

Webpack 是現在最流行的前端構建工具之一。它具備高可配置性的特點,你可以用它來構建 React、Angular、Vue 等等各種類型的 Javascript 應用。它的構建過程十分靈活,支持使用各種模塊加載器和插件進行個性化定製。

Webpack 工作示意圖

然而從另一方面來講,Webpack 的高靈活性也帶來了配置過於複雜,對初學者不友好等問題。在公司內部我們希望開發同學能更加專注於研發本身,擺脫掉繁冗的配置文件並且避免一些實際使用中的陷阱 。在本文中會介紹基於 Webpack 實現的構建工具 Ykit,它在 Webpack 基礎上進行了哪些優化,以及它在公司中的應用現狀。

1. 背景——各自爲戰時期

在 Ykit 出來之前,公司裏的開發同學使用過各種各樣的構建工具。有 Gulp、Grunt、Webpack 以及一些類似的工具等,從這些獨立構建的項目中我們發現了幾個共同的問題:

  • 幾乎每個項目都要通過配置或腳本完成一些特定的工作。比如指定資源輸入輸出路徑、生成資源版本號、配置 HMR 、搭建 mock 服務等等,這些類似的工作經常被重頭到尾實現一遍。這些工作如果可以由統一的工具來實現則可以節省很多開發成本。

  • 缺少構建層面的優化。不管是從打包出來的資源體積以及編譯速度上,不少項目都有很大的提升空間。我們曾試着將其中一個工程的公用庫用 CommonChunks 的方式提取出來,將整體資源體積減小了多一半。這主要是因爲很多時候開發同學只是想短平快地完成一些業務,並不會過多關注流程上的優化。

  • 溝通和學習成本高。跨團隊和跨項目都有可能由於構建工具和流程不一樣而帶來額外的成本。當面對一個缺少文檔的新項目時,一個新來的同學可能是完全懵逼的,要先花好久搭建環境才能把項目運行起來。而項目間工具的不一致也會導致切換環境時要花更多的時間和精力。

溝通不暢

由這些現象我們在想,能不能提供一個統一的工具出來,將這些共性的工作由工具來完成,保持開發體驗的一致性,使得開發同學在構建項目時效率更高並且少踩一些坑。

2. Ykit——多樣化的構建

Ykit 是對 Webapck 的一層封裝,如果要說它最大的特點,就是用插件機制來封裝了各種類型應用的配置,只要選擇安裝合適的插件就可以把一個基本的開發環境搭建好了。

插件

比如說做一個 React 應用,只要安裝上相應的 React 插件就可以直接在代碼裏引用 React 模塊,和編寫 ES6 語法的代碼了。而當你想使用 Ant Design 這個 UI 組件庫,則引入相應它的插件即可。目前公司內外有十幾個不同的插件來滿足多樣化的需求。

除了封裝第三方模塊,插件內部還可以添加很多編譯打包流程上的鉤子,方便完成各種構建流程上的工作。在公司內部的構建流程中有很多固定的任務,比如生成一個單獨存放資源版本號的文件等。這些類似的工作都被納入了一個專門爲公司構建流程設計的插件中,每個項目將其引入之後即不必擔心這些構建流程中的問題。

實際上利用插件還可以做更多更有想象力的事情。比如現在有爲微信小程序量身打造的 Ykit 插件。它內置了初始化腳手架,編譯小程序特定語法,支持引入 npm 包等等功能,目前公司的小程序都是依賴於它來構建。另外也有專門用來製作移動端活動頁的插件,它可以將 psd 設計稿直接生成 html,自動生成雪碧圖,封裝了常用的樣式和動畫庫讓開發者可以高效地完成各種佈局和特效。

總的來說 Ykit 身只是一個殼,真正的多樣化構建依賴於插件。插件都是一個個 npm 模塊,它們將構建過程中的配置和功能進行封裝,使得 Ykit 能滿足多種多樣的需求而又不會互相沖突,同時保持了開發體驗的相對一致性。

3. 如何使構建更快?

Webpack 一直容易被人詬病的就是它的構建速度慢。官方雖然也給出了許多優化策略,但是一些優化只對特定類型的項目有效果,對於其他項目則效果有限,而對於開發者來說有時並沒有時間和精力去一個個嘗試到自己的項目中。而這些工作由 Ykit 來做卻是非常合適的。

接觸 Webpack 的同學應該不難發現 Webpack 總是第一次構建很慢。啓動項目時要等好久才能把頁面打開,這是因爲 Webpack 會把所有的資源都打包一遍。如果項目中有 10 個 JS,而第一次打開的頁面只請求了其中一個,那麼也要等所有資源作爲一個整體打包完成之後返回那其中的一個。

Ykit 在這裏進行了一次入口過濾。當本地服務接收到頁面的請求時,會帶着所請求的資源去項目中找,生成一個只含有所請求的資源入口的 Webpack 實例,打包完成後立即返回結果。實際情況還要比這個更復雜一些,比如所請求的資源有可能只是打包的副產品而不在配置入口中,Ykit 對這些情況都進行了處理。最後達到的效果是頁面請求哪個資源纔會打包哪個資源,即便是對於很大型的工程來說第一次打開的速度也會相對來說可以接受。

本地服務資源打包優化

另一個在 Webpack 中很耗時的操作是壓縮資源,Ykit 並沒有採用它內置的 UglifyJS 插件,而是採用多進程去壓縮,與此同時這也解決了較大型應用使用 Webpack 壓縮資源時內存溢出的問題。對於資源數量多的項目有比較顯著的提升。之前有一個資源數在 70 個左右的項目,使用多進程壓縮之後將它的構建時間從 75s 減少到了 25s。

最後一些就是在 Ykit 插件中內置的優化了。插件其實是很適合來做這種工作的,因爲針對不同類型應用優化的策略也不一樣。比如使用 Babel 來編譯 es6 代碼的時候可以採用 Happypack 替代原有的 Loader 進行打包。去哪兒有一套移動端的開發框架 Hy2,它內部的依賴庫很多。我們在它的插件中使用了 Happypack、 DLLPlugin 等優化策略,將首次打包的時間從 10~20s 減少到了 3~4s 。不同插件可以針對自己的場景進行深度優化,使每一種類型的應用都變得更高效。

4. 現狀和未來

在公司中各個業務線都已經開始在使用 Ykit 構建和發佈,截止到目前上線的項目有 80 多個。在未來我們還會着眼更多的場景,就像現在爲小程序提供的腳手架和開發工具,在以後可能會有更多這樣的模式,使得搭建各種各樣的開發環境都變得更加簡單,讓開發同學更少地去花精力在構建這件事而更加專注於研發本身。

現在 Ykit 已經開源(Github:YMFE/ykit https://github.com/YMFE/ykit),歡迎爲它貢獻代碼和編寫更多的插件:)

本文來自 Qunar 技術沙龍,作者居玉皓,去哪兒網高級前端工程師。主要從事平臺技術服務設施的搭建,Qunar React Native 開發者,現階段負責前端統一構建解決方案 Ykit。熱愛開源社區,是 Avalon 開源組件庫 OniUI 的代碼貢獻者和維護者。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章