- 原文地址:OPTIMIZING WEBPACK FOR FASTER REACT BUILDS
- 原文作者:Jonathan Rowny
- 譯文出自:掘金翻譯計劃
- 本文永久連結:github.com/xitu/gold-m…
- 譯者:Starrier
- 校對者:lcx-seima、sishenhei7
如果您的 Webpack 構建緩慢且有大量的庫 —— 別擔心,有一種方法可以提高增量構建的速度!Webpack 的 DLLPlugin
允許您將所有的依賴項構建到一個檔案中。這是一個取代分塊的很好選擇。該檔案稍後將由您的主 Webpack 配置,甚至可以在共享同一組依賴項的其他專案上使用。典型的 React 應用程式可能包含幾十個供應商庫,這取決於您的 Flux、外掛、路由和其他工具(如 lodash
)。我們將通過允許 Webpack 跳過 DLL 中包含的任何引用來節省寶貴的構建時間。
本文假設您已經熟悉典型的 Webpack 和 React 設定。如果沒有,請檢視 SurviveJS 在 Webpack 和 React 方面的優秀內容,當您的構建時間逐步增加時,請回到本文。
第 1 步,列出您的供應商
構建和維護 DLL 的最簡單的方法是在您的專案中建立一個 JS 檔案 —— vendors.js
,其中引入您使用的所有庫。例如,在我們最近的專案中,我們的 vendors.js
檔案內容如下:
require("classnames");
require("dom-css");
require("lodash");
require("react");
require("react-addons-update");
require("react-addons-pure-render-mixin");
require("react-dom");
require("react-redux");
require("react-router");
require("redux");
require("redux-saga");
require("redux-simple-router");
require("redux-storage");
require("redux-undo");
複製程式碼
這是我們將要“構建”的 DLL 檔案,它沒有任何功能,只是匯入我們使用的庫。
注意: 您也可以在這裡使用 ES6 風格的 import
,但是我們需要用 Bable 來構建 DLL。您仍然可以像您習慣的那樣,在您的主專案中使用 import
和其他所有 ES2015 語法糖。
第 2 步,構建 DLL
現在我們可以建立一個 Webpack 配置來構建 DLL。這將從您的應用程式主 Webpack 配置中完全分離,並且會影響部分檔案。它不會被您的 Webpack 中介軟體、Webpack 伺服器或其他任何東西呼叫(手動或通過預構建除外)。
我們稱之為 webpack.dll.js
var path = require("path");
var webpack = require("webpack");
module.exports = {
entry: {
vendor: [path.join(__dirname, "client", "vendors.js")]
},
output: {
path: path.join(__dirname, "dist", "dll"),
filename: "dll.[name].js",
library: "[name]"
},
plugins: [
new webpack.DllPlugin({
path: path.join(__dirname, "dll", "[name]-manifest.json"),
name: "[name]",
context: path.resolve(__dirname, "client")
}),
new webpack.optimize.OccurenceOrderPlugin(),
new webpack.optimize.UglifyJsPlugin()
],
resolve: {
root: path.resolve(__dirname, "client"),
modulesDirectories: ["node_modules"]
}
};
複製程式碼
這是典型的 Webpack 配置,除了 webpack.DLLPlugin
以外,它包含 name、context 和 mainifest 路徑。mainifest 非常重要,它為其他 Webpack 配置提供了您到已經構建模組的對映。context 是客戶端原始碼的根,而 name 是入口的名稱,在本例中是“供應商”。繼續嘗試使用命令 webpack --config=webpack.dll.js
執行這個構建。最後,您應該得到一個包含模組的排列對映 —— dll\vendor-manifest.json
已經包含了您所有供應商庫的精簡包 —— dist\dll\dll.vendor.js
。
第 3 步,構建專案
**注意:**下述示例不包含 sass、assets、或熱載入程式。如果您已經在配置中使用了,它們仍然可以正常工作。
現在我們需要做的就是新增 DLLReferencePlugin
,並將其指向我們已經構建的 DLL。您的 webpack.dev.js
可能是如下模樣:
var path = require("path");
var webpack = require("webpack");
module.exports = {
cache: true,
devtool: "eval", //or cheap-module-eval-source-map
entry: {
app: path.join(__dirname, "client", "index.js")
},
output: {
path: path.join(__dirname, "dist"),
filename: "[name].js",
chunkFilename: "[name].js"
},
plugins: [
//Typically you'd have plenty of other plugins here as well
new webpack.DllReferencePlugin({
context: path.join(__dirname, "client"),
manifest: require("./dll/vendor-manifest.json")
}),
],
module: {
loaders: [
{
test: /\.jsx?$/,
loader: "babel",
include: [
path.join(__dirname, "client") //important for performance!
],
query: {
cacheDirectory: true, //important for performance
plugins: ["transform-regenerator"],
presets: ["react", "es2015", "stage-0"]
}
}
]
},
resolve: {
extensions: ["", ".js", ".jsx"],
root: path.resolve(__dirname, "client"),
modulesDirectories: ["node_modules"]
}
};
複製程式碼
我們還做了一些其他事來提高效能,包括:
- 確保我們有
cache: true
- 確保 Babel 在查詢中載入程式有
cacheDirectory:true
- 在 bable loader 中使用
include
(您應該在所有的 loader 中這樣做) - 將 devTool 設定為
eval
,因為我們正在為構建時間優化#nobugs
第 4 步,包含 DLL
此時,您已經生成了一個供應商 DLL 檔案,並且您的 Webpack 構建並生成 app.js 檔案。您需要在模版中提供幷包含這兩個檔案,但 DLL 應該是第一位的。您可能已經使用 HtmlWebpackPlugin
設定了模版。因為我們不關心熱過載 DLL,所以除了在主 app.js 之前包含 <script src="dll/dll.vendor.js"></script>
之外,您實際上不需要做任何事。如果您使用的是 webpack-middleware
或者您自己定製化的伺服器,則還需要確保為 DLL 提供服務。此時,一切都應該按原樣執行,但是使用 Webpack 進行增量構建的速度應該非常快。
第 5 步,構建指令碼
我們可以使用 NPM 和 package.json
新增一些為我們構建的簡單指令碼。要清除 dist
資料夾,請繼續執行 npm i rimraf --saveDev
。現在可以新增到您的 package.json 中了:
"scripts": {
"clean": "rimraf dist",
"build:webpack": "webpack --config config.prod.js",
"build:dll": "webpack --config config.dll.js",
"build": "npm run clean && npm run build:dll && npm run build:webpack",
"watch": "npm run build:dll && webpack --config config.dev.js --watch --progress"
}
複製程式碼
現在您可以執行 npm run watch
。如果您喜歡手動執行 build:dll
,則可以將其從監視指令碼中刪除,以便更快地啟動。
就這樣,夥計們!
我希望這能讓您深入瞭解 InVision 如何使用 Webpack 的 DLLPlugin
來提高構建速度。如果您有任何問題或想法,歡迎發表評論。
掘金翻譯計劃 是一個翻譯優質網際網路技術文章的社群,文章來源為 掘金 上的英文分享文章。內容覆蓋 Android、iOS、前端、後端、區塊鏈、產品、設計、人工智慧等領域,想要檢視更多優質譯文請持續關注 掘金翻譯計劃、官方微博、知乎專欄