国产探花免费观看_亚洲丰满少妇自慰呻吟_97日韩有码在线_资源在线日韩欧美_一区二区精品毛片,辰东完美世界有声小说,欢乐颂第一季,yy玄幻小说排行榜完本

首頁(yè) > 編程 > JavaScript > 正文

詳解webpack4之splitchunksPlugin代碼包分拆

2019-11-19 12:24:50
字體:
來(lái)源:轉(zhuǎn)載
供稿:網(wǎng)友

本文講解的是最近在做的一個(gè)多頁(yè)面項(xiàng)目,結(jié)合webpack4的splitChunks進(jìn)行代碼包分拆的過(guò)程

項(xiàng)目框架

項(xiàng)目有home和topic兩個(gè)入口文件,主要包括:

  • react、mobx、antd作為項(xiàng)目的基本框架,
  • echarts和d3(畫圖)是項(xiàng)目中部分頁(yè)面用到比較大的組件庫(kù)
  • src下的工作的組件和代碼
  • 其他的非公共代碼。

兩個(gè)入口文件都用react-loadable做了異步加載

import Loadable from 'react-loadable';...const LoadableLogin = Loadable({ loader: () => import('../../common/components/login'), loading: Loading,});...

webpack部分配置相關(guān)如下:

module.exports = { ... mode: 'production', entry: { // 多入口 home: './src/home', topic: './src/topic', }, output: { path: config.build.assetsRoot, filename: '[name].js', publicPath: process.env.NODE_ENV === 'production' ? config.build.assetsPublicPath : config.dev.assetsPublicPath, }, plugins: [ new HtmlWebpackPlugin({ // home頁(yè)面  filename: 'home.html',  template: './template.html', }), new HtmlWebpackPlugin({ // topic頁(yè)面  filename: 'topic.html',  template: './template.html',  inject: true, }), ], ...}

splitChunks

chunks:

  • all: 不管文件是動(dòng)態(tài)還是非動(dòng)態(tài)載入,統(tǒng)一將文件分離。當(dāng)頁(yè)面首次載入會(huì)引入所有的包
  • async: 將異步加載的文件分離,首次一般不引入,到需要異步引入的組件才會(huì)引入。
  • initial:將異步和非異步的文件分離,如果一個(gè)文件被異步引入也被非異步引入,那它會(huì)被打包兩次(注意和all區(qū)別),用于分離頁(yè)面首次需要加載的包。

minSize: 文件最小打包體積,單位byte,默認(rèn)30000

比如說(shuō)某個(gè)項(xiàng)目下有三個(gè)入口文件,a.js和b.js和c.js都是100byte,當(dāng)我們將minSize設(shè)置為301,那么webpack就會(huì)將他們打包成一個(gè)包,不會(huì)將他們拆分成為多個(gè)包。

比如說(shuō)某個(gè)項(xiàng)目下有三個(gè)入口文件,a.js和b.js和c.js都是100byte,當(dāng)我們將minSize設(shè)置為301,那么webpack就會(huì)將他們打包成一個(gè)包,不會(huì)將他們拆分成為多個(gè)包。

automaticNameDelimiter: 連接符

假設(shè)我們生成了一個(gè)公用文件名字叫vendor,a.js,和b.js都依賴他,并且我們?cè)O(shè)置的連接符是"~"那么,最終生成的就是 vendor~a~b.js

maxInitialRequests 入口點(diǎn)處的最大并行請(qǐng)求數(shù),默認(rèn)為3

如果我們?cè)O(shè)置為1,那么每個(gè)入口文件就只會(huì)打包成為一個(gè)文件

maxAsyncRequests 最大異步請(qǐng)求數(shù)量,默認(rèn)5

如果我們?cè)O(shè)置為1,那么每個(gè)入口文件就只會(huì)打包成為一個(gè)文件

優(yōu)先級(jí)關(guān)系

maxInitialRequest / maxAsyncRequests <maxSize <minSize。

cacheGroups 定制分割包的規(guī)則

test可以配置正則和寫入function作為打包規(guī)則。其他屬性均可繼承splitChunks,這里必須說(shuō)一下 priority,設(shè)置包的打包優(yōu)先級(jí),非常重要! (后面結(jié)合實(shí)踐)

minChunks

最少引入的次數(shù)

實(shí)踐

我們以一個(gè)最簡(jiǎn)單的配置開始,將公共代碼打包出來(lái)

 splitChunks: {  chunks: 'all', // initial、async和all  minSize: 30000, // 形成一個(gè)新代碼塊最小的體積  maxAsyncRequests: 5, // 按需加載時(shí)候最大的并行請(qǐng)求數(shù)  maxInitialRequests: 3, // 最大初始化請(qǐng)求數(shù)  automaticNameDelimiter: '~', // 打包分割符  name: true,  cacheGroups: {  vendors: { // 打包兩個(gè)頁(yè)面的公共代碼   minChunks: 2, // 引入兩次及以上被打包   name: 'vendors', // 分離包的名字   chunks: 'all'  },  } },

兩個(gè)入口文件的公共代碼被打包到vendor文件夾下面,包括echarts d3 amcharts等一些三方包和src下的公共代碼。

這當(dāng)然不是我們想要的結(jié)果!存在以下問(wèn)題:

  • 其實(shí)當(dāng)我們進(jìn)入網(wǎng)站,一般第一步都是進(jìn)入一個(gè)登陸頁(yè)面,需要的只是項(xiàng)目的基本框架代碼,例如react,react-dom.antd等,我們可以用all(或者initial)將它們單獨(dú)打包,作為首頁(yè)必須載入的包
  • 我們打包的公共包,首次加載頁(yè)面的時(shí)候,只想把同步加載的加載進(jìn)來(lái),所以需要一個(gè)同步的Common包
  • 像echarts,d3,以及一些src下面一些異步加載的包,將它們利用async將打包成一個(gè)獨(dú)立異步加載包

我們修改cacheGroups為:

 cacheGroups: {  vendors: { // 項(xiàng)目基本框架等   chunks: 'all',   test: /(react|react-dom|react-dom-router|babel-polyfill|mobx)/,   priority: 100,   name: 'vendors',  },  'async-commons': { // 異步加載公共包、組件等   chunks: 'async',   minChunks: 2,   name: 'async-commons',   priority: 90,  },  commons: { // 其他同步加載公共包   chunks: 'all',   minChunks: 2,   name: 'commons',   priority: 80,  },  }

這次webpack幫我們打出來(lái)的包主要有:

  • async-common:是兩個(gè)入口文件都異步加載的三方包和利用react-loader做的懶加載代碼,有echarts,d3等
  • vendors: 包括react,react-dom,antd等
  • commons: 引用超過(guò)兩次的同步代碼

這里說(shuō)兩個(gè)需要注意的地方:

  • 注意這里我們priority的設(shè)置,vendors>async-commons>commons,我們首先將react,react-dom等優(yōu)先打包出來(lái),然后再打包公共部分,如果將vendors的優(yōu)先級(jí)設(shè)置小于兩個(gè)Common的優(yōu)先級(jí),那么react,react-dom將會(huì)打包到common包,將不會(huì)再生成vendors包。
  • 如果我們這里將commons的配置去掉,將會(huì)生成一個(gè)topic~home的包,我們配置了async-common提取出異步加載的公共包后,將會(huì)默認(rèn)將同步加載的公共包打包生成以automaticNameDelimiter連接符‘~'生成的名字'topic~home'包,內(nèi)容其實(shí)和commons包內(nèi)容完全一樣,

ok!按照我們的要求,這樣首次頁(yè)面加載只會(huì)引入vendors,commons包,而不會(huì)引入async-common包,還是挺棒的!追求更精致的我們,再認(rèn)真想想,是不是還可以做一些更好的優(yōu)化?

到目前為止我們打包文件的打包是這樣的:

用gzip壓縮后,最大的async-common包有391kb。公司說(shuō)最近因?yàn)橐恍顩r,布置到生產(chǎn)后速度慢的時(shí)候,有時(shí)候只能有20kb/s的下載速度==。。。。于是繼續(xù)split!

分析一下:

  • async-common中包含了自己寫的src組件和第三方組件
  • async-common中比較大是echarts,zrender(echarts引入)和d3,結(jié)合項(xiàng)目來(lái)說(shuō),只有部分頁(yè)面我們需要echarts(d3同),所以我們可以考慮將d3和echarts這兩個(gè)比較大的包提取出來(lái),等到某個(gè)頁(yè)面需要的時(shí)候,再讓其異步加載,這樣就大大減小了async-common的體積了。

修改

cacheGroups: {  vendors: { // 基本框架   chunks: 'all',   test: /(react|react-dom|react-dom-router|babel-polyfill|mobx)/,   priority: 100,   name: 'vendors',  },  d3Venodr: { // 將體積較大的d3單獨(dú)提取包,指定頁(yè)面需要的時(shí)候再異步加載   test: /d3/,   priority: 100, // 設(shè)置高于async-commons,避免打包到async-common中   name: 'd3Venodr',   chunks: 'async'  },  echartsVenodr: { // 異步加載echarts包   test: /(echarts|zrender)/,   priority: 100, // 高于async-commons優(yōu)先級(jí)   name: 'echartsVenodr',   chunks: 'async'  },  'async-commons': { // 其余異步加載包   chunks: 'async',   minChunks: 2,   name: 'async-commons',   priority: 90,  },  commons: { // 其余同步加載包   chunks: 'all',   minChunks: 2,   name: 'commons',   priority: 80,  },  }

當(dāng)然,每次修改后,需要在htmlWebpackPlugin中配置chunk需要的包

 plugins: [ new HtmlWebpackPlugin({ // home頁(yè)面  filename: 'home.html',  template: './template.html',  chunks: ['vendors', 'commons', 'home'], }), new HtmlWebpackPlugin({ // topic頁(yè)面  filename: 'topic.html',  template: './template.html',  chunks: ['vendors', 'commons', 'topic'], }), ],

后期還做了其他的拆分和優(yōu)化,大概最大的包保持在100k左右,當(dāng)然也不建議拆的特別小,因?yàn)闉g覽器http1可能一次性支持6次下載文件,太多可能會(huì)適得其反。大家可以根據(jù)自己的項(xiàng)目做不同的拆分方法,總而言之,就是為了讓項(xiàng)目更完美的在線上運(yùn)行,給用戶更好的體驗(yàn)~

以上就是本文的全部?jī)?nèi)容,希望對(duì)大家的學(xué)習(xí)有所幫助,也希望大家多多支持武林網(wǎng)。

發(fā)表評(píng)論 共有條評(píng)論
用戶名: 密碼:
驗(yàn)證碼: 匿名發(fā)表
主站蜘蛛池模板: 车险| 上虞市| 陵川县| 桦甸市| 巴楚县| 重庆市| 大石桥市| 星子县| 辽阳县| 新源县| 安阳县| 达孜县| 龙井市| 申扎县| 图木舒克市| 肇庆市| 修文县| 清涧县| 正定县| 阿合奇县| 英吉沙县| 汉中市| 五华县| 洪洞县| 嘉义市| 黔江区| 铜陵市| 桦甸市| 石狮市| 南涧| 和林格尔县| 邓州市| 阿坝| 天祝| 新邵县| 二连浩特市| 依安县| 平潭县| 宜都市| 龙海市| 藁城市|