原文連接: https://survivejs.com/webpack...
翻譯計劃: https://segmentfault.com/a/11...
涉及到的未翻譯單詞javascript
Webpack 是模塊打包器。它能夠在打包的同時使用任務運行器。然而,因爲社區開發的 webpack 插件,打包器和任務運行器之間的界限變得模糊。有時,這些插件甚至獨立於 webpack 使用,例如清理構建目錄或部署構建使用的插件。
(譯者注:grunt 之類的任務運行器,就是自動幫你走一次如「組合兩個 js 文件--壓縮 js--壓縮 css」這樣流程的工具)css
Webpack 也能夠在其餘環境中的使用,例如 Ruby on Rails。儘管它的名字帶有 web,但 webpack 並不只限於 web。它也能夠打包其餘東西,這點在 Build Targets 章節中會提到。java
T> 若是你想更詳細地瞭解構建工具及其歷史,請查看附錄 Comparison of Build Tools。node
使用 webpack 構建工程,至少包括 input 和 output。打包處理從用戶定義的 entry 開始。entry 自己就是模塊,它能夠經過 import 指向其餘模塊。react
當你使用 webpack 打包項目時,它會遍歷 import,構建項目的依賴關係圖,而後根據配置文件中的設定生成 output。你還能夠定義分割點,以在項目代碼內拆分出單獨的 bundle(包)。webpack
Webpack 支持開箱即用的 ES2015,CommonJS 和 AMD 模塊標準。loader 機制也適用於 CSS,經過 css-loader 在 css 文件中使用 @import
和 url()
。你還能夠找到某些實現特定功能的插件,例如壓縮,國際化,HMR等。git
T> 依賴圖是描述節點如何相互關聯的有向圖。這個圖是經過文件之間的引用(require
,import
)構建的。Webpack 會在不執行資源的狀況下靜態遍歷這些資源,並生成建立 bundle 所需的依賴圖。github
Webpack 從 entry 開始運行。entry 一般是 JavaScript 模塊,webpack 從這裏開始遍歷處理。在此過程當中,webpack 根據 loader 配置轉換每一個匹配到的模塊。web
Entry 自己就是一個模塊。當 webpack 遇到 entry,webpack 會在文件系統匹配相關文件。除了 node_modules 以外,webpack 還能夠對特定目錄執行查找。也能夠調整 webpack 匹配文件擴展名的方式,也能夠爲目錄定義 aliases(別名)。這方面在 Consuming Packages 章節有更詳細的介紹。npm
若是 webpack 正確解析文件,對應 loader 會處理匹配的文件,不一樣的 loader 對模塊內容應用的轉換各不相同。若是解析失敗,webpack 會報運行時錯誤。
loader 能夠經過多種方式匹配待處理文件,如文件類型和文件的位置。 Webpack 甚至可讓你按 import 位置分類,不一樣位置 import 的文件採用不一樣的轉換方法。
對 webpack loader 執行相同的解析過程。 你能夠在選擇 loader 時使用相同的邏輯。因爲這個緣由,Loader 已經解析了本身的配置。若是 webpack 查找 loader 失敗,則會引起運行時錯誤。
T> Webpack 的解釋底層依賴於 enhanced-resolve 包。
Webpack 將在構造依賴圖時解析它遇到的每一個模塊。若是 entry 包含依賴項,則將針對每一個依賴項遞歸執行該過程,直到遍歷完成爲止。 Webpack 能夠針對任何文件類型執行此過程,這與 Babel 或 Sass 編譯器等專用工具不一樣。
Webpack 能夠控制對不一樣資源的處理方式。例如,能夠把資源內聯到 JavaScript 包以免過多的網絡請求(譯者注:例如圖片轉 base64)。Webpack 還容許你使用 CSS 模塊等技術將樣式與組件結合,並避免標準 CSS 樣式問題。這種靈活性是 webpack 價值的體現。
儘管 webpack 主要用於打包 JavaScript,但它能夠捕獲圖像或字體等資源,併爲它們抽取爲單獨的文件。Entry 只是打包處理的起點。 webpack 生成的內容徹底取決於你配置它的方式。
Webpack 會下到上、從右到左地(styleLoader(cssLoader('./main.css'))
)處理匹配成功的加載器,模塊會依次經過 loader 的處理。最後,你將得到 webpack 輸出的包。Loader Definitions 章節詳細介紹了該主題。
若是全部 loader 都成功運行,則 webpack 會在最後一個包中包含源。 Plugins 能夠在打包過程的不一樣階段攔截運行時事件。
雖然 loader 能夠作不少事情,但它們不能爲高級任務提供足夠的動力。Plugins 能夠攔截 webpack 提供的運行時事件。一個很好的例子是由 MiniCssExtractPlugin
執行的包提取,當與 loader 一塊兒使用時,從包中提取 CSS 文件並將其提取到單獨的文件中。若是沒有這一步,CSS 將在生成的 JavaScript 中內聯,由於 webpack 默認將全部代碼視爲 JavaScript。CSS 提取將在 Separating CSS 一章中討論。
每一個模塊都通過處理以後,webpack 生成 output。output 包括一個引導腳本,其中包含一個指引瀏覽器執行該項目的 manifest 文件。能夠將 manifest 提取到單獨的文件中,本書後面會有相關介紹。output 會根據你使用的 build target 而有所不一樣(Web 不是惟一選擇)。
這並非打包過程的所有內容。例如,你能夠作代碼拆分,webpack 會在程序運行到所需功能時才加載的單獨包。這個話題會在 Code Splitting 章節中討論。
webpack 的核心依賴於配置。如下是根據官方 webpack 教程改編的配置示例證實:
webpack.config.js
const webpack = require("webpack"); module.exports = { // Where to start bundling entry: { app: "./entry.js", }, // Where to output output: { // Output to the same directory path: __dirname, // Capture name from the entry using a pattern filename: "[name].js", }, // How to resolve encountered imports module: { rules: [ { test: /\.css$/, use: ["style-loader", "css-loader"], }, { test: /\.js$/, use: "babel-loader", exclude: /node_modules/, }, ], }, // What extra processing to perform plugins: [ new webpack.DefinePlugin({ ... }), ], // Adjust module resolution algorithm resolve: { alias: { ... }, }, };
Webpack 的配置模型有時候會讓人感受霧裏看花,由於配置文件太龐大,屬性太多。除非你理解每個屬性的意義,不然很難理解 webpack 在作什麼。讓你徹底理解 webpack 配置的使用,是本書存在的主要目的之一。
使用 webpack 能夠爲每一個包的名稱注入一個哈希值(例如,app.d587bbd6.js),以便在版本更新後使客戶端上舊版本的包無效(從新下載)。包(bundle)拆分可讓客戶端在理想狀況下僅從新加載一小部分數據。
你可能使用過 LiveReload 或 BrowserSync 等工具。這些工具會在你進行更改時自動刷新瀏覽器。熱模塊更換(HMR)則更先進,在使用 React 的狀況下,應用程序能夠在不強制刷新頁面的狀況下更新應用。雖然這聽起來沒什麼特別,但它能夠在實踐中大有不一樣。
HMR 不是webpack獨有的功能,經過 livereactload 也能夠在 Browserify 中使用 HMR。
Webpack 能夠以多種方式拆分代碼。你甚至能夠在應用程序執行時動態加載代碼。由於依賴能夠根據須要即時加載,因此延遲加載特別適用於體積龐大的應用。
即便是小型應用也能夠得益於代碼拆分,由於它容許用戶更快地得到可用的東西。畢竟,性能是評價一個應用的重要標準,瞭解這項技術是值得的。
Webpack 學習曲線比較陡峭。可是有了它,項目的長期維護能夠節省多少時間和精力,因此這是一個很是值得學習的工具。爲了更好地瞭解 Webpack 與其餘工具的比較,請查看官網上與其餘工具的比較。
Webpack 不是萬能的。但它確實很好地解決了打包問題。在開發過程當中須要擔憂的問題又少了一件。活用 package.json 和 webpack,走遍天下都不怕。
總結一下:
在本書的下一部分中,你將學習使用 webpack 構建開發配置,同時瞭解更多相關概念。
T> 若是你對 webpack 仍有疑問或者不明白咱們爲何須要一個打包器,請閱讀Why would I use a Webpack?。