Webpack 本質是一個模塊化打包工具,通過“萬物皆模塊”這種設計思想,巧妙地實現了整個前端項目的模塊化。
Webpack 解決的問題
如何在前端項目中更高效地管理和維護項目中的每一個資源。
模塊化的演進過程
- Stage 1 - 文件劃分方式
- Stage 2 - 命名空間方式
- Stage 3 - IIFE
- Stage 4 - IIFE 依賴參數
模塊加載的問題
更爲理想的方式應該是在頁面中引入一個 JS 入口文件,其餘用到的模塊可以通過代碼控制,按需加載進來。
模塊化規範的出現
早期制定前端模塊化標準時,並沒有直接選擇 CommonJS 規範(CommonJS 約定的是以同步的方式加載模塊),而是專門爲瀏覽器端重新設計了一個規範,叫做 AMD
( Asynchronous Module Definition) 規範,即異步模塊定義規範。同期還推出了一個非常出名的庫,叫做 Require.js
,它除了實現了 AMD 模塊化規範,本身也是一個非常強大的模塊加載器。
在 AMD 規範中約定每個模塊通過
define()
函數定義,這個函數默認可以接收兩個參數,第一個參數是一個數組,用於聲明此模塊的依賴項;第二個參數是一個函數,參數與前面的依賴項一一對應,每一項分別對應依賴項模塊的導出成員,這個函數的作用就是爲當前模塊提供一個私有空間。如果在當前模塊中需要向外部導出成員,可以通過return
的方式實現。// AMD 規範定義一個模塊 define(['jquery', './module2.js'], function ($, module2) { return { start: function () { $('body').animate({ margin: '200px' }) module2() } } })
除此之外,Require.js 還提供了一個
require()
函數用於自動加載模塊,用法與 define() 函數類似,區別在於 require() 只能用來載入模塊,而 define() 還可以定義模塊。當 Require.js 需要加載一個模塊時,內部就會自動創建script
標籤去請求並執行相應模塊的代碼。// AMD 規範載入一個模塊 require(['./modules/module1.js'], function (module1) { module1.start() })
同期出現的規範還有淘寶的 Sea.js
,只不過它實現的是另外一個標準,叫作 CMD
,這個標準類似於 CommonJS,在使用上基本和 Require.js 相同,可以算上是重複的輪子。但隨着前端技術的發展,Sea.js 後來也被 Require.js 兼容了。
模塊化的標準規範
在 Node.js 環境中,我們遵循 CommonJS
規範來組織模塊。
在瀏覽器環境中,我們遵循 ES Modules
規範。
模塊打包工具的出現
模塊化可以幫助我們更好地解決複雜應用開發過程中的代碼組織問題,但是隨着模塊化思想的引入,我們的前端應用又會產生了一些新的問題,比如:
- 首先,我們所使用的 ES Modules 模塊系統本身就存在環境兼容問題。儘管現如今主流瀏覽器的最新版本都支持這一特性,但是目前還無法保證用戶的瀏覽器使用情況。所以我們還需要解決兼容問題。
- 其次,模塊化的方式劃分出來的模塊文件過多,而前端應用又運行在瀏覽器中,每一個文件都需要單獨從服務器請求回來。零散的模塊文件必然會導致瀏覽器的頻繁發送網絡請求,影響應用的工作效率。
- 最後,在實現 JS 模塊化的基礎上的發散。隨着應用日益複雜,在前端應用開發過程中不僅僅只有 JavaScript 代碼需要模塊化,HTML 和 CSS 這些資源文件也會面臨需要被模塊化的問題。而且從宏觀角度來看,這些文件也都應該看作前端應用中的一個模塊,只不過這些模塊的種類和用途跟 JavaScript 不同。
對於開發過程而言,模塊化肯定是必要的,所以我們需要在前面所說的模塊化實現的基礎之上引入更好的方案或者工具,去解決上面提出的 3 個問題,讓我們的應用在開發階段繼續享受模塊化帶來的優勢,又不必擔心模塊化對生產環境所產生的影響。
接下來我們先對這個更好的方案或者工具提出一些設想:
-
第一,它需要具備編譯代碼的能力,也就是將我們開發階段編寫的那些包含新特性的代碼轉換爲能夠兼容大多數環境的代碼,解決我們所面臨的環境兼容問題。
-
第二,能夠將散落的模塊再打包到一起,這樣就解決了瀏覽器頻繁請求模塊文件的問題。這裏需要注意,只是在開發階段才需要模塊化的文件劃分,因爲它能夠幫我們更好地組織代碼,到了實際運行階段,這種劃分就沒有必要了。
-
第三,它需要支持不同種類的前端模塊類型,也就是說可以將開發過程中涉及的樣式、圖片、字體等所有資源文件都作爲模塊使用,這樣我們就擁有了一個統一的模塊化方案,所有資源文件的加載都可以通過代碼控制,與業務代碼統一維護,更爲合理。
針對上面第一、第二個設想,我們可以藉助 Gulp
之類的構建系統配合一些編譯工具和插件去實現,但是對於第三個可以對不同種類資源進行模塊化的設想,就需要使用前端模塊打包工具
。
Webpack:A bundler for javascript and friends(一個 JavaScript 和周邊的打包工具)
Webpack 以模塊化思想爲核心,幫助開發者更好的管理整個前端工程。