Vue多頁(yè)面配置打包性能優(yōu)化方式(解決加載包太大加載慢問題)
通常我們使用vue-cli開發(fā)多頁(yè)面的時(shí)候,不知道您是否注意一個(gè)問題沒有?
默認(rèn)情況:webpack 會(huì)將多入口通用的組件庫(kù)等,打包一個(gè) vendor 的 chunk js 中
現(xiàn)在假設(shè)有兩個(gè)頁(yè)面:
入口 admin 使用到了element-ui組件庫(kù)和echarts圖表庫(kù),入口 index 使用了iview的組件庫(kù)
一、問題描述及解決方案
1. 多入口存在的問題
那么這樣就會(huì)存在問題:
- 打出來(lái)的chunk-vendor.xxxx.js會(huì)包含element-ui和echarts和iview組件庫(kù),所以 js 體積會(huì)非常大
- chunk-vendor.xxxx.js默認(rèn)是所有node_modules下面的庫(kù)集合
- index 入口只是使用了 iview,由于需要加載chunk-vendor.xxxx.js,所以造成了不必要的加載
- admin 入口 同上 會(huì)額外引入 iview
2. 我的預(yù)期效果
那么針對(duì)以上的問題,我們預(yù)期應(yīng)該是怎樣的呢?
- index 入口和 admin 各自單獨(dú)打包,按需引入各自的庫(kù)
- index 和 admin 公用的庫(kù) 只打包一次
3. 可行方案
針對(duì)以上的需求,我探索出了一下兩種方案:
- 刪除默認(rèn) splitChunk 配置,打公共 chunks,單獨(dú)分離各自的 ui 庫(kù)(做減法)
- 刪除默認(rèn) splitChunk 配置,抽離公共資源(做加法)
二、方案一:打公共 chunks,單獨(dú)分離各自的ui庫(kù)
方案 1: 刪除默認(rèn) splitChunk 配置,打公共 chunks,單獨(dú)分離各自的 ui 庫(kù)
刪除默認(rèn) splitChunk 配置是了取消 webpack 的默認(rèn)配置,因?yàn)?webpack 默認(rèn)的配置是將node_modules下的所用到的庫(kù)打包成一個(gè)chunk-vendor.xxxx.js。
主要分成三步:
- 第一步: 刪除默認(rèn) splitChunk 的配置
- 第二步: 單獨(dú)配出 splitChunk
- 第三部: 為多入口,各自單獨(dú)配置 chunks
詳細(xì)配置如下:
let pages = {
? index: {
? ? entry: "src/main.js",
? ? template: "public/index.html",
? ? // 特別注意:由于各個(gè)入口單獨(dú)分離了chunk之后,需要將對(duì)于的chunk名顯示的列出
? ? chunks: [
? ? ? "index", //注意:這個(gè)是頁(yè)面名稱的chunk,下面的chunk名稱需要對(duì)呀splitChunk對(duì)應(yīng)的名稱
? ? ? "chunk-vendors", //這是node_modules下的chunk
? ? ? "chunk-common", //這是admin和Index入口公用的chunk
? ? ? "chunk-iview" //index的單獨(dú)chunk
? ? ]
? },
? admin: {
? ? entry: "src/admin.js",
? ? template: "public/admin.html",
? ? // 特別注意:由于各個(gè)入口單獨(dú)分離了chunk之后,需要將對(duì)于的chunk名顯示的列出
? ? chunks: [
? ? ? "admin", //注意:這個(gè)是頁(yè)面名稱的chunk,下面的chunk名稱需要對(duì)呀splitChunk對(duì)應(yīng)的名稱
? ? ? "chunk-vendors", //這是node_modules下的chunk
? ? ? "chunk-common", //這是admin和Index入口公用的chunk
? ? ? "chunk-element-ui", //admin的單獨(dú)chunk
? ? ? "chunk-echarts", //admin的單獨(dú)chunk
? ? ? "zrender" //echarts用到了zrender
? ? ]
? }
};
module.exports = {
? pages,
? publicPath: process.env.BASE_URL,
? outputDir: "dist",
? assetsDir: "assets",
? runtimeCompiler: true,
? productionSourceMap: false,
? parallel: true,
? css: {
? ? // 是否提取css 生產(chǎn)環(huán)境可以配置為 true
? ? extract: true
? },
? chainWebpack: config => {
? ? if (process.env.NODE_ENV === "production") {
? ? ? // 刪除系統(tǒng)默認(rèn)的splitChunk
? ? ? config.optimization.delete("splitChunks");
? ? }
? },
? configureWebpack: config => {
? ? // 給輸出的js名稱添加hash
? ? config.output.filename = "[name].[hash].js";
? ? config.output.chunkFilename = "[name].[hash].js";
?
? ? config.optimization = {
? ? ? splitChunks: {
? ? ? ? cacheGroups: {
? ? ? ? ? // 抽離所有入口的公用資源為一個(gè)chunk
? ? ? ? ? common: {
? ? ? ? ? ? name: "chunk-common",
? ? ? ? ? ? chunks: "initial",
? ? ? ? ? ? minChunks: 2,
? ? ? ? ? ? maxInitialRequests: 5,
? ? ? ? ? ? minSize: 0,
? ? ? ? ? ? priority: 1,
? ? ? ? ? ? reuseExistingChunk: true,
? ? ? ? ? ? enforce: true
? ? ? ? ? },
? ? ? ? ? // 抽離node_modules下的庫(kù)為一個(gè)chunk
? ? ? ? ? vendors: {
? ? ? ? ? ? name: "chunk-vendors",
? ? ? ? ? ? test: /[\\/]node_modules[\\/]/,
? ? ? ? ? ? chunks: "initial",
? ? ? ? ? ? priority: 2,
? ? ? ? ? ? reuseExistingChunk: true,
? ? ? ? ? ? enforce: true
? ? ? ? ? },
? ? ? ? ? // 由于Index入口使用了iview,所以講iview單獨(dú)處理出來(lái),這樣admin入口就不會(huì)使用此js
? ? ? ? ? iview: {
? ? ? ? ? ? name: "chunk-iview",
? ? ? ? ? ? test: /[\\/]node_modules[\\/]iview[\\/]/,
? ? ? ? ? ? chunks: "all",
? ? ? ? ? ? priority: 3,
? ? ? ? ? ? reuseExistingChunk: true,
? ? ? ? ? ? enforce: true
? ? ? ? ? },
? ? ? ? ? // 由于admin入口使用了element-ui,所以講element-ui單獨(dú)處理出來(lái),這樣index入口就不會(huì)使用此js
? ? ? ? ? element: {
? ? ? ? ? ? name: "chunk-element-ui",
? ? ? ? ? ? test: /[\\/]node_modules[\\/]element-ui[\\/]/,
? ? ? ? ? ? ? ? ? //根據(jù)你實(shí)際的目錄情況來(lái)決定 /[\\/]node_modules[\\/]_?element-ui(.*)/,
? ? ? ? ? ? chunks: "all",
? ? ? ? ? ? priority: 3,
? ? ? ? ? ? reuseExistingChunk: true,
? ? ? ? ? ? enforce: true
? ? ? ? ? },
? ? ? ? ? // 由于admin入口使用了echarts,所以講echarts單獨(dú)處理出來(lái),這樣index入口就不會(huì)使用此js
? ? ? ? ? echarts: {
? ? ? ? ? ? name: "chunk-echarts",
? ? ? ? ? ? test: /[\\/]node_modules[\\/](vue-)?echarts[\\/]/,
? ? ? ? ? ? chunks: "all",
? ? ? ? ? ? priority: 4,
? ? ? ? ? ? reuseExistingChunk: true,
? ? ? ? ? ? enforce: true
? ? ? ? ? },
? ? ? ? ? // 由于echarts使用了zrender庫(kù),那么需要將其抽離出來(lái),這樣就不會(huì)放在公共的chunk中
? ? ? ? ? zrender: {
? ? ? ? ? ? name: "zrender",
? ? ? ? ? ? test: /[\\/]node_modules[\\/]zrender[\\/]/,
? ? ? ? ? ? chunks: "all",
? ? ? ? ? ? priority: 3,
? ? ? ? ? ? reuseExistingChunk: true,
? ? ? ? ? ? enforce: true
? ? ? ? ? }
? ? ? ? }
? ? ? }
? ? };
? }
};三、方案二:刪除默認(rèn)splitChunk配置,抽離公共資源
其實(shí)告訴你,webpack如果是多入口的話,刪除默認(rèn)的 splitChunk 配置,多入口會(huì)單獨(dú)各自打包,但是公共資源不會(huì)抽取。
針對(duì)以上的情況我們可以通過以下三步達(dá)到優(yōu)化目的:
- 第一步:刪除默認(rèn)的 splitChunk
- 第二步:抽離公共的入口資源
- 第三部:為各自入口單獨(dú)配置 chunks
詳細(xì)配置如下
const BundleAnalyzerPlugin = require("webpack-bundle-analyzer")
? .BundleAnalyzerPlugin;
let pages = {
? index: {
? ? entry: "src/main.js",
? ? template: "public/index.html",
? ? chunks: ["index", "chunk-common"] //分別是入口的名稱,也就是前面的key值,和公共chunk的名稱
? },
? admin: {
? ? entry: "src/admin.js",
? ? template: "public/admin.html",
? ? chunks: ["admin", "chunk-common"] //分別是入口的名稱,也就是前面的key值,和公共chunk的名稱
? }
};
module.exports = {
? pages,
? publicPath: process.env.BASE_URL,
? outputDir: "dist",
? assetsDir: "assets",
? runtimeCompiler: true,
? productionSourceMap: false,
? parallel: true,
? css: {
? ? // 是否提取css 生產(chǎn)環(huán)境可以配置為 true
? ? extract: true
? },
?
? chainWebpack: config => {
? ? // 刪除默認(rèn)的splitChunk
? ? config.optimization.delete("splitChunks");
? },
? configureWebpack: config => {
? ? // js output config
? ? config.output.filename = "[name].[hash].js";
? ? config.output.chunkFilename = "[name].[hash].js";
?
? ? config.optimization = {
? ? ? splitChunks: {
? ? ? ? cacheGroups: {
? ? ? ? ? common: {
? ? ? ? ? ? //抽取所有入口頁(yè)面都需要的公共chunk
? ? ? ? ? ? name: "chunk-common",
? ? ? ? ? ? chunks: "initial",
? ? ? ? ? ? minChunks: 2,
? ? ? ? ? ? maxInitialRequests: 5,
? ? ? ? ? ? minSize: 0,
? ? ? ? ? ? priority: 1,
? ? ? ? ? ? reuseExistingChunk: true,
? ? ? ? ? ? enforce: true
? ? ? ? ? }
? ? ? ? }
? ? ? }
? ? };
? }
};四、方案對(duì)比
方案一: 刪除默認(rèn) splitChunk 配置,打公共 chunks,單獨(dú)分離各自的 ui 庫(kù)(做減法)
優(yōu)點(diǎn):不需要處理公共 chunk,單獨(dú)分離各自的 chunk 缺點(diǎn):如果多入口使用的庫(kù)比較多,需要各自單獨(dú)的抽離
適用場(chǎng)景
適用于:多個(gè)入口頁(yè)面耦合性比較強(qiáng)的(也就是多入口使用的公共資源比較多的),只有少量組件庫(kù)不同
刪除默認(rèn) splitChunk 配置,抽離公共資源(做加法)
優(yōu)點(diǎn):不需要單獨(dú)分離各自的 chunk,只需要處理公共 chunk 即可 缺點(diǎn):如果多入口公共庫(kù)使用的比較多,抽離需要更加細(xì)致化
適用場(chǎng)景
適用于:多個(gè)入口頁(yè)面耦合性比較低的(也就是多入口使用的公共資源比較少,通常是多個(gè)入口沒有任何關(guān)系的)
總結(jié)
以上為個(gè)人經(jīng)驗(yàn),希望能給大家一個(gè)參考,也希望大家多多支持腳本之家。
相關(guān)文章
vue中的get方法\post方法如何實(shí)現(xiàn)傳遞數(shù)組參數(shù)
這篇文章主要介紹了vue中的get方法\post方法如何實(shí)現(xiàn)傳遞數(shù)組參數(shù),具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2022-04-04
Vue?數(shù)據(jù)綁定事件綁定樣式綁定語(yǔ)法示例
這篇文章主要為大家介紹了Vue?數(shù)據(jù)綁定事件綁定樣式綁定語(yǔ)法示例,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪2023-07-07
關(guān)于vuejs中v-if和v-show的區(qū)別及v-show不起作用問題
v-if 有更高的切換開銷,而 v-show 有更高的出事渲染開銷.因此,如果需要非常頻繁的切換,那么使用v-show好一點(diǎn);如果在運(yùn)行時(shí)條件不太可能改變,則使用v-if 好點(diǎn)2018-03-03
VUE2.0自定義指令與v-if沖突導(dǎo)致元素屬性修改錯(cuò)位問題及解決方法
這篇文章主要介紹了VUE2.0自定義指令與v-if沖突導(dǎo)致元素屬性修改錯(cuò)位問題及解決方法,本文給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下2023-07-07

