亚洲激情专区-91九色丨porny丨老师-久久久久久久女国产乱让韩-国产精品午夜小视频观看

溫馨提示×

溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊×
其他方式登錄
點擊 登錄注冊 即表示同意《億速云用戶服務條款》

Webpack打包慢怎么辦

發布時間:2021-06-21 15:33:04 來源:億速云 閱讀:152 作者:小新 欄目:web開發

這篇文章主要介紹Webpack打包慢怎么辦,文中介紹的非常詳細,具有一定的參考價值,感興趣的小伙伴們一定要看完!

前言

這幾天寫騰訊實習生 Mini 項目的時候用上了 React 全家桶,當然同時引入了 Webpack 作為打包工具。但是開發過程中遇到一個很棘手的問題就是,React 加上 React-Router、superagent、eventproxy 這些第三方輪子一共有好幾百個 module,Webpack 的打包速度極慢。這對于開發是非常不好的體驗,同時效率也極低。

問題分析

我們先來看一下完全沒有任何優化的時候,Webpack 的打包速度(使用了jsx和babel的loader)。

下面是我們的測試文件:

//test.js
var react = require('react');
var ReactAddonsCssTransitionGroup = require('react-addons-css-transition-group');
var reactDOM = require('react-dom');
var reactRouter = require('react-router');
var superagent = require("superagent");
var eventproxy = require("eventproxy");

運行

webpack test.js

在我的2015款RMBP13,i5處理器,全SSD下,性能是這樣的:

Webpack打包慢怎么辦

沒錯你沒有看錯,這幾個第三方輪子加起來有整整668個模塊,全部打包需要20多秒。

這意味著什么呢?你每次對業務代碼的修改,gulp 或者 Webpack 監測到后都會重新打包,你要足足等20秒才能看到自己的修改結果。

但是需要重新打包的只有你的業務代碼,這些第三方庫是完全不用重新打包的,它們的存在只會拖累打包性能。所以我們要找一些方法來優化這個過程。

配置externals

Webpack 可以配置 externals 來將依賴的庫指向全局變量,從而不再打包這個庫,比如對于這樣一個文件:

import React from 'react';
console.log(React);

如果你在 Webpack.config.js 中配置了externals:

module.exports = {
 externals: {
  'react': 'window.React'
 }
 //其它配置忽略...... 
};

等于讓 Webpack 知道,對于 react 這個模塊就不要打包啦,直接指向 window.React 就好。不過別忘了加載 react.min.js,讓全局中有 React 這個變量。

我們來看看性能,因為不用打包 React 了所以速度自然超級快,包也很小:

Webpack打包慢怎么辦

配置externals的缺陷

問題如果就這么簡單地解決了的話,那我就沒必要寫這篇文章了,下面我們加一個 react 的動畫庫 react-addons-css-transition-group 來試一試:

import React from 'react';
import ReactAddonsCssTransitionGroup from 'react-addons-css-transition-group';
console.log(React);

對,你沒有看錯,我也沒有截錯圖,新加了一個很小很小的動畫庫之后,性能又爆炸了。從模塊數來看,一定是 Webpack 又把 react 重新打包了一遍。

我們來看一下為什么一個很小很小的動畫庫會導致 Webpack 又傻傻地把 react 重新打包了一遍。找到 react-addons-css-transition-group 這個模塊,然后看看它是怎么寫的:

// react-addons-css-transition-group模塊
// 入口文件 index.js
module.exports = require('react/lib/ReactCSSTransitionGroup');

這個動畫模塊就只有一行代碼,唯一的作用就是指向 react 下面的一個子模塊,我們再來看看這個子模塊是怎么寫的:

// react模塊
// react/lib/ReactCSSTransitionGroup.js
var React = require('./React');
var ReactTransitionGroup = require('./ReactTransitionGroup');
var ReactCSSTransitionGroupChild = require('./ReactCSSTransitionGroupChild');
//....剩余代碼忽略

這個子模塊又反回去依賴了 react 整個庫的入口,這就是拖累 Webpack 的罪魁禍首。

總而言之,問題是這樣產生的:

  1. Webpack 發現我們依賴了 react-addons-css-transition-group

  2. Webpack 去打包 react-addons-css-transition-group 的時候發現它依賴了 react 模塊下的一個叫 ReactTransitionGroup.js 的文件,于是 Webpack 去打包這個文件。

  3. ReactTransitionGroup.js 依賴了整個 react 的入口文件 React.js,雖然我們設置了 externals ,但是 Webpack 不知道這個入口文件等效于 react 模塊本身,于是我們可愛又敬業的 Webpack 就把整個 react 又重新打包了一遍。

讀到這里你可能會有疑問,為什么不能把這個動畫庫也設置到 externals 里,這樣不是就不用打包了嗎?

問題就在于,這個動畫庫并沒有提供生產環境的文件,或者說這個庫根本沒有提供 react-addons-css-transition-group.min.js 這個文件。

這個問題不只存在于 react-addons-css-transition-group 中,對于 react 的大多數現有庫來說都有這個依賴關系復雜的問題。

初級解決方法

所以對于這個問題的解決方法就是,手工打包這些 module,然后設置 externals ,讓 Webpack 不再打包它們。

我們需要這樣一個 lib-bundle.js 文件:

window.__LIB["react"] = require("react");
window.__LIB["react-addons-css-transition-group"] = require("react-addons-css-transition-group");
// ...其它依賴包

我們在這里把一些第三方庫注冊到了 window.__LIB 下,這些庫可以作為底層的基礎庫,免于重復打包。

然后執行 webpack lib-bundle.js lib.js,得到打包好的 lib.js。然后去設置我們的 externals :

var webpack = require('webpack');
module.exports = {
 externals: {
  'react': 'window.__LIB["react"]',
  'react-addons-css-transition-group': 'window.__LIB["react-addons-css-transition-group"]',
  // 其它庫
 }
 //其它配置忽略...... 
};

這時由于 externals 的存在,Webpack 打包的時候就會避開這些模塊超多,依賴關系復雜的庫,把這些第三方 module 的入口指向預先打包好的 lib.js 的入口 window.__LIB,從而只打包我們的業務代碼。

終極解決方法

上面我們提到的方法本質上就是一種動態鏈接庫(dll)”的思想,這在 windows 系統下面是一種很常見的思想。一個dll包,就是一個很純凈的依賴庫,它本身不能運行,是用來給你的 app 或者業務代碼引用的。

同樣的 Webpack 最近也新加入了這個功能:webpack.DllPlugin。使用這個功能需要把打包過程分成兩步:

  1. 打包ddl包

  2. 引用ddl包,打包業務代碼

首先我們來打包ddl包,首先配置一個這樣的 ddl.config.js:

const webpack = require('webpack');

const vendors = [
 'react',
 'react-dom',
 'react-router',
 // ...其它庫
];

module.exports = {
 output: {
  path: 'build',
  filename: '[name].js',
  library: '[name]',
 },
 entry: {
  "lib": vendors,
 },
 plugins: [
  new webpack.DllPlugin({
   path: 'manifest.json',
   name: '[name]',
   context: __dirname,
  }),
 ],
};

webpack.DllPlugin 的選項中:

  1. path 是 manifest.json 文件的輸出路徑,這個文件會用于后續的業務代碼打包;

  2. name 是dll暴露的對象名,要跟 output.library 保持一致;

  3. context 是解析包路徑的上下文,這個要跟接下來配置的 webpack.config.js 一致。

運行Webpack,會輸出兩個文件一個是打包好的 lib.js,一個就是 manifest.json,它里面的內容大概是這樣的:

{
 "name": "vendor_ac51ba426d4f259b8b18",
 "content": {
  "./node_modules/react/react.js": 1,
  "./node_modules/react/lib/React.js": 2,
  "./node_modules/react/node_modules/object-assign/index.js": 3,
  "./node_modules/react/lib/ReactChildren.js": 4,
  "./node_modules/react/lib/PooledClass.js": 5,
  "./node_modules/react/lib/reactProdInvariant.js": 6,
  // ............
 }
}

接下來我們就可以快樂地打包業務代碼啦,首先寫好打包配置文件 webpack.config.js:

const webpack = require('webpack');
module.exports = {
 output: {
  path: 'build',
  filename: '[name].js',
 },
 entry: {
  app: './src/index.js',
 },
 plugins: [
  new webpack.DllReferencePlugin({
   context: __dirname,
   manifest: require('./manifest.json'),
  }),
 ],
};

webpack.DllReferencePlugin 的選項中:

  1. context 需要跟之前保持一致,這個用來指導 Webpack 匹配 manifest 中庫的路徑;

  2. manifest 用來引入剛才輸出的 manifest.json 文件。

DllPlugin 本質上的做法和我們手動分離這些第三方庫是一樣的,但是對于包極多的應用來說,自動化明顯加快了生產效率。

以上是“Webpack打包慢怎么辦”這篇文章的所有內容,感謝各位的閱讀!希望分享的內容對大家有幫助,更多相關知識,歡迎關注億速云行業資訊頻道!

向AI問一下細節

免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。

AI

崇礼县| 南郑县| 田东县| 门源| 张家川| 佛学| 金平| 新昌县| 大同县| 高台县| 阳西县| 正镶白旗| 得荣县| 安泽县| 汨罗市| 甘德县| 同江市| 景德镇市| 格尔木市| 富裕县| 奉贤区| 简阳市| 白玉县| 申扎县| 二手房| 马公市| 康乐县| 大姚县| 高陵县| 尉氏县| 阿拉善盟| 石柱| 新余市| 大庆市| 宜良县| 新乡市| 方山县| 博罗县| 海伦市| 合江县| 明星|