什麼是 Webpack?
實務上由於需要整合各式各樣的開發流程,通常會使用 webpack 或 gulp 等「任務管理工具」,這裡我們介紹用 webpack 來做本地開發方案。
Webpack 是一個 JavaScript 應用程式的「模組打包工具」。它會從進入點(Entry point)開始分析專案結構,以下圖的例子是 main.js ,找出每個模組間的依賴關係,並分析其中是否有瀏覽器不能直接使用的語法(ES6 語法、SCSS 等),甚至檢查程式碼中是否有引入 CSS、圖片檔等,將他們轉換並打包在一起,最後產出瀏覽器可以識別的檔案,方便我們部署到線上。
你可能又會接著問,那什麼是模組?什麼是打包?這篇文章我們會由淺入深地理解這些問題,並了解 Webpack 的用途及它的基本觀念。
模組化
相信大家都有過這樣的經驗,在剛學習前端開發時,總是一支 JavaScript 做到底,把所有的邏輯都塞在同一支檔案裡。
若是小型的 side project,可能還不是什麼大問題,但如果使用這種方式在比較大型的專案中,隨著需求不斷的迭代下,日積月累很可能就會變成一支幾千幾萬行程式碼的大怪物,然後讓接手這份程式碼維護的團隊成員要處理這樣痛苦的技術債。
因此為了方便團隊協作與維護專案,現今的網頁專案大多會採用模組化的方式,將所有的 JavaScript 程式碼,依照功能切成一個個的小模組(module),方便組織與管理。
打包
那有了模組化之後,最後我們要將這麼多個小模組組合起來部署到線上,就需要將他們「打包」起來。
什麼是打包?這裡借用 Webpack 的圖片來說明,左邊的部分就是我們在專案中的許多模組,這些模組依照各自負責的功能會切分成各組父子組件互相依賴,而如何解析這些依賴關係並把最後的結果輸出到右邊的幾支檔案,這件事就是打包要做的事。
另外為了讓專案更容易開發,你可能會還需要做以下這些事:
- 在前端中使用其他人開發好的 NPM 套件。
- 使用 ES6 以上許多方便的 JavaScript 語法。
- 使用 SCSS、less 這些 CSS 預處理器來寫 CSS。
- 將各種類型的檔案(圖片、CSS)引入 JavaScript 中。
而為了要將模組打包、轉譯各種預處理器的語法,我們需要一個工具來幫忙處理這些麻煩事,這個工具就是 Webpack。
延伸閱讀:NPM是什麼?了解Node Package Manager套件管理機
Webpack 的更多用途
而 Webpack 對模組又做了更廣泛的定義,除了 JavaScript 模組外,任何檔案類型像是 CSS、圖片等資源也都被當成模組。
這些廣義的模組,在 Webpack 中可以利用各種 loader 來識別檔案類型並轉譯成瀏覽器看得懂的語法。像是可以做 Babel 設定來轉譯 JavaScript ES6-ES11 的語法,或者轉換 SCSS 或 less 這些 CSS 預處理器語法,或載入專案中的各種圖檔格式。
甚至我們可以透過 NPM 安裝許多第三方的套件,像是 Bootstrap、Font Awesome、Day.js 等等,直接在專案中引入使用。
另外,Webpack 也可以在打包的過程中透過一些工具稱為 plugin 來做到程式碼優化的工作(minify、uglify)。
而現今一些前端框架的 CLI 工具像是 create-react-app 或 Vue CLI,都整合了 Webpack 將專案的打包工作做好通用的預設設定,簡化了許多開發者這部分的負擔,並可以無痛的使用這些框架來有效管理程式碼。
而學習 Webpack 並瞭解它是如何運作的,也將能讓我們更有彈性的調整這些預設設定。
專業前端工程師養成,有系統學習使用Webpack、CSS預處理器
Webpack 基本觀念
上面了解了 Webpack 的各種用途後,最後我們以更深入的方式來整理幾個關於 Webpack 工作方式的基本觀念。
Entry point
從上圖中可以看到會由一個進入點開始,從這個檔案開始找到其他的相關檔案(dependency)。
Webpack 預設的進入點是 src/index.js,可以隨專案調整,也可以設定多個進入點。
Output
輸出指的是 Webpack 在 build 完之後產生的靜態檔結果,預設被放在 dist/ 底下。
這些被輸出的檔案也可被稱為 bundle。
Loader
前面提到 Webpack 可以打包的東西不只是 JS,也可以打包其他諸如 CSS、圖片、文件等資源,而這些就需要藉由 Loader 來處理,只要將這些種類的檔案透過 loader 轉為 module,就能讓專案方便的直接引入。
Plugin
Plugin 是第三方的擴充套件,可以補強一些 Webpack 的功能,舉例像是有些 plugin 可以拿來 uglify、minify、移除未使用的 CSS(PurgeCSS)等,更多的 plugin 可以參考 awesome-webpack 的 plugin list。
其他
另外,在 Webpack 中也可以依照專案進程,切分兩種模式分別是 development 與 production,來分別對開發中的專案或未來上線的版本做設定上的區分。
而強大的 Webpack 除了這些基本的操作外,還可以做到更多事,像是將輸出的 bundle 切成更小的 chunk、模組的動態載入等。
Webpack 在 SPA 和 SSR 中的應用
Webpack在SPA(單頁面應用程式)中的應用
代碼分割與延遲載入
在單頁面應用程式(SPA)中,Webpack的代碼分割和延遲載入功能非常有用。這樣可以在使用者實際需要某個功能的時候才載入相關資源,這樣不僅提升了網站性能,也降低了初始加載時間。
動態匯入與路由優化
Webpack允許進行動態匯入,這一點在SPA中特別有價值。根據不同的路由,你可以動態地加載不同的代碼區塊,這樣可以更有效地利用網絡資源。
開發模式與熱模組替換(HMR)
Webpack提供的開發伺服器和熱模組替換(HMR)讓開發者能夠實時地預覽所有更改,這大大提高了開發效率。
Webpack在SSR(伺服器端渲染)中的應用
代碼重用和最佳化
在伺服器端渲染(SSR)中,Webpack可以幫助你重用客戶端的代碼,並且對其進行優化,這樣可以讓你更高效地管理代碼。
伺服器與客戶端資源整合
Webpack可以統一管理伺服器和客戶端的所有資源,包括JavaScript、CSS、圖片等,這樣使得資源的整合和維護更為方便。
條件性打包
由於SSR中伺服器和客戶端的運行環境可能有所不同,Webpack允許你進行條件性打包,以適應不同環境的需求。
為什麼需要使用Webpack?
程式碼組織和模組化
Webpack允許開發人員將程式碼和資源(如圖像、樣式表等)模組化,使程式碼庫更容易維護和擴展。
資源最優化
透過不同的Loader和Plugins,Webpack能夠對圖像、CSS和JS等進行壓縮和優化,這有助於提高網站性能。
環境變數和條件打包
Webpack允許根据不同環境(開發、測試、生產等)進行條件打包,這提供了高度的靈活性。
代碼分割和Lazy loading
Webpack的代碼分割和Lazy load功能有助於提高網頁的加載速度,進而提升用戶體驗。
Webpack的局限
學習曲線
Webpack提供了大量的配置選項和插件,這可能會讓新手感到困惑或不知所措。
配置複雜性
對於複雜的項目,Webpack的配置可能變得非常繁瑣和難以管理。
起始設定時間
對於簡單的項目,Webpack可能會增加不必要的起始設定時間和複雜性。
社區分裂
由於存在許多其他的打包和任務運行工具(如Gulp、Parcel等),社區資源有時會分散,這可能會影響找到解決方案或最佳實踐的速度。
其他相似工具
除了 Webpack,你可能還有聽過其他相似的工具像是 Parcel、Rollup,或甚至一些任務流程管理工具像是 Gulp、Grunt 等,乍聽之下這麼多五花八門的工具可能會讓前端開發者覺得「老子學不動了」。
這些工具都有各自的優缺點與想解決的問題,但其實核心的概念是差不多的,所以只要熟悉其中一套後,未來碰到其他更新穎的工具其實都大同小異,相信都能很快上手。
結論
最後統整一下,在這篇文章中我們從模組化、打包來了解 Webpack 的用途,並深入理解 Webpack 的工作方式。
而 Webpack 自 2012 年發展至今,已經是個非常複雜的工具,但我們不需要因為各種沒看過的設定而恐慌。只要透過掌握最基本的概念,未來不管碰到任何種類的設定需求,再 google 查詢或參考官方文件來設定即可。
延伸閱讀
這篇文章中並沒有提到太多關於 Webpack 的實務操作,對這部分有需求的讀者可以參考以下資源:
其他 Webpack 教學可參考
關於 JavaScript 模組化的歷史脈絡及內容可參考
- webpack 新手教學之淺談模組化與 snowpack
- 用過 Webpack 之類的打包工具嗎?為什麼需要?
- Webpack 中文指南 – 模塊系統
- JavaScript 模块化七日谈
- 解析 Javascript 模組機制與建置函式庫觀念
- 完全解析 JavaScript import、export
(本文作者是 ALPHA Camp 的助教 前端工程師 Dez)