提到前端打包工具,毫无疑问想先到的是webpack。但是前端发展地很快,时不时会有新东西出现,打包工具这边之前也出现parcel和rollup。各种工具的碰撞,相互汲取优点,促进技术的发展。
webpack4中支持了零配置的特性,同时对块打包也做了优化, CommonsChunkPlugin
已经被移除了,现在是使用 optimization.splitChunks
代替。
下面就开始介绍splitChunks的内容。
默认情况
首先webpack会根据下述条件自动进行代码块分割:
- 新代码块可以被共享引用,或者这些模块都是来自node_modules文件夹里面
- 新代码块大于30kb(min+gziped之前的体积)
- 按需加载的代码块,并行请求最大数量应该小于或者等于5
- 初始加载的代码块,并行请求最大数量应该小于或等于3
块打包默认情况下只会影响按需加载模块,因为对初始块也进行优化打包会影响HTML中的script标签数,增加请求数。
接下来看些例子来理解默认情况的打包。
模块全部是同步引入
// indexA.js import React from 'react' import ReactDOM from 'react-dom' import _ from 'lodash' console.log(_.join(['a', 'b'], '~')) ReactDOM.render( <div>SplitChunk</div>, document.getElementById('root') )
默认情况只会影响按需加载模块,所以所有内容全部被打包到一起了。
有模块动态导入
这里首先使用符合ECMAScript 提案 的 import() 语法
// indexA.js import React from 'react' import ReactDOM from 'react-dom' import _ from 'lodash' import(/* webpackChunkName: "async-jquery" */ 'jquery').then(component => { console.log(component) }) console.log(_.join(['a', 'b'], '~')) ReactDOM.render( <div>SplitChunk</div>, document.getElementById('root') )
这里jquery使用动态导入,打包结果中可以看到jquery被单独打包了
react按需加载
同样的我们试要react按需加载,使用react-router提供的按需加载方案
AsyncModule模块按上面方案异步加载Dashboard
import React from 'react' import ReactDOM from 'react-dom' import {BrowserRouter, Route} from 'react-router-dom' import AsyncModule from './AsyncModule.jsx' import _ from 'lodash' import $ from 'jquery' console.log(_.join(['a', 'b'], '~')) ReactDOM.render( <div> <BrowserRouter> <Route path='/' component={AsyncModule} /> </BrowserRouter> </div>, document.getElementById('root') )
从打包结果可以看到按需加载的模块被打包到0.js去了。
讲完了webpack默认情况下对打包块的优化,接下来看splitChunks配置项。
配置项
相关配置项:
module.exports = { //... optimization: { splitChunks: { chunks: 'async', minSize: 30000, minChunks: 1, maxAsyncRequests: 5, maxInitialRequests: 3, automaticNameDelimiter: '~', name: true, cacheGroups: {} } } }
- chunks: 表示哪些代码需要优化,有三个可选值:initial(初始块)、async(按需加载块)、all(全部块),默认为async
- minSize: 表示在压缩前的最小模块大小,默认为30000
- minChunks: 表示被引用次数,默认为1
- maxAsyncRequests: 按需加载时候最大的并行请求数,默认为5
- maxInitialRequests: 一个入口最大的并行请求数,默认为3
- automaticNameDelimiter: 命名连接符
- name: 拆分出来块的名字,默认由块名和hash值自动生成
- cacheGroups: 缓存组。缓存组的属性除上面所有属性外,还有test, priority, reuseExistingChunk
- test: 用于控制哪些模块被这个缓存组匹配到
- priority: 缓存组打包的先后优先级
- reuseExistingChunk: 如果当前代码块包含的模块已经有了,就不在产生一个新的代码块
配置项基本就上面这些,我们重点来看下chunks和cacheGroups。
chunks
chunks的取值是有initial, async, all。默认情况下是async,在本文第一部分已经介绍了它的表现,所以现在来看下其它两个的表现。
initial
, all
模式会将所有来自node_modules的模块分配到一个叫vendors的缓存组;所有重复引用至少两次的代码,会被分配到default的缓存组。
// indexA.js import './Dashboard.jsx' // indexB.js import './Dashboard.jsx' // Dashboard.jsx import React from 'react'
// webpack.config.js splitChunks: { chunks: 'initial' }
打包表现正如上面所述,产生了两个代码块vendors, default。
可以通过配置optimization.splitChunks.cacheGroups.default: false禁用default缓存组。
// webpack.config.js splitChunks: { chunks: 'initial', cacheGroups: { default: false } }
至于all和initial的差别,可以看下这篇文章Webpack 4 — Mysterious SplitChunks Plugin (要科学上网)
里面有提到 initial
模式下会分开优化打包异步和非异步模块。而 all
会把异步和非异步同时进行优化打包。也就是说moduleA在indexA中异步引入,indexB中同步引入, initial
下moduleA会出现在两个打包块中,而 all
只会出现一个。
cacheGroups
使用cacheGroups可以自定义配置打包块。
// indexA.js import React from 'react' import ReactDOM from 'react-dom' import _ from 'lodash' import $ from 'jquery' // indexB.js import React from 'react' import ReactDOM from 'react-dom' import('lodash') import $ from 'jquery' // webpack.config.js optimization: { splitChunks: { cacheGroups: { commons: { name: 'commons', chunks: 'initial', minChunks: 2 } } } }
根据开头介绍webapck分割条件,一些公共模块被打包进了commons,自定义打包块的优先级是0,所以现在公共模块会被打包进commons,而不是上述提到的默认打包块vendors(优先级为负)。
但是这边为什么lodash为什么没打包在一起呢?可以回顾下initial和all的区别。接下来实验下all的效果。
// indexA, indexB同上 // webpack.config.js optimization: { splitChunks: { cacheGroups: { commons: { name: 'commons', chunks: 'all', minChunks: 2 } } } }
结果在预期中,lodash被打包在一起了。
提取第三方库
最后看下之前CommonsChunkPlugin常用的分离部分第三方库功能。这边你可以想一下怎么操作。
上面已经提到了设置 chunks: initial || all
都可以提取出第三方库。但是它是把所有第三库提取出来,所以我们在只提取react和react-dom的情况下,需要自定义一个cacheGroup。
// indexA.js import React from 'react' import ReactDOM from 'react-dom' import _ from 'lodash' import $ from 'jquery' // webpack.config.js entry: { indexA: path.join(__dirname, 'src/indexA.js') }, optimization: { splitChunks: { chunks: 'all', cacheGroups: { vendors: { test: /react/, name: 'vendors' } } } }
我们去重写了vendors打包块,只打包匹配react的模块,所以达到了之前CommonsChunkPlugin的功能。
或者
// index.jsx import React from 'react' import ReactDOM from 'react-dom' // webpack.config.js entry: { indexA: path.join(__dirname, 'src/indexA.js'), vendor: ["react", "react-dom"] }, optimization: { splitChunks: { cacheGroups: { vendor: { name: "vendor", chunks: "initial" } } } }
optimization.runtimeChunk
最后提一下runtimeChunk,通过 optimization.runtimeChunk: true
选项,webpack会添加一个只包含运行时(runtime)额外代码块到每一个入口。(译注:这个需要看场景使用,会导致每个入口都加载多一份运行时代码)
总结
webpack4的splitChunks功能是比较强大的,不过推荐还是使用默认模式,或者提取一下第三方库。
以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持。
免责声明:本站资源来自互联网收集,仅供用于学习和交流,请遵循相关法律法规,本站一切资源不代表本站立场,如有侵权、后门、不妥请联系本站删除!
《魔兽世界》大逃杀!60人新游玩模式《强袭风暴》3月21日上线
暴雪近日发布了《魔兽世界》10.2.6 更新内容,新游玩模式《强袭风暴》即将于3月21 日在亚服上线,届时玩家将前往阿拉希高地展开一场 60 人大逃杀对战。
艾泽拉斯的冒险者已经征服了艾泽拉斯的大地及遥远的彼岸。他们在对抗世界上最致命的敌人时展现出过人的手腕,并且成功阻止终结宇宙等级的威胁。当他们在为即将于《魔兽世界》资料片《地心之战》中来袭的萨拉塔斯势力做战斗准备时,他们还需要在熟悉的阿拉希高地面对一个全新的敌人──那就是彼此。在《巨龙崛起》10.2.6 更新的《强袭风暴》中,玩家将会进入一个全新的海盗主题大逃杀式限时活动,其中包含极高的风险和史诗级的奖励。
《强袭风暴》不是普通的战场,作为一个独立于主游戏之外的活动,玩家可以用大逃杀的风格来体验《魔兽世界》,不分职业、不分装备(除了你在赛局中捡到的),光是技巧和战略的强弱之分就能决定出谁才是能坚持到最后的赢家。本次活动将会开放单人和双人模式,玩家在加入海盗主题的预赛大厅区域前,可以从强袭风暴角色画面新增好友。游玩游戏将可以累计名望轨迹,《巨龙崛起》和《魔兽世界:巫妖王之怒 经典版》的玩家都可以获得奖励。
更新日志
- 【雨果唱片】中国管弦乐《鹿回头》WAV
- APM亚流新世代《一起冒险》[FLAC/分轨][106.77MB]
- 崔健《飞狗》律冻文化[WAV+CUE][1.1G]
- 罗志祥《舞状元 (Explicit)》[320K/MP3][66.77MB]
- 尤雅.1997-幽雅精粹2CD【南方】【WAV+CUE】
- 张惠妹.2007-STAR(引进版)【EMI百代】【WAV+CUE】
- 群星.2008-LOVE情歌集VOL.8【正东】【WAV+CUE】
- 罗志祥《舞状元 (Explicit)》[FLAC/分轨][360.76MB]
- Tank《我不伟大,至少我能改变我。》[320K/MP3][160.41MB]
- Tank《我不伟大,至少我能改变我。》[FLAC/分轨][236.89MB]
- CD圣经推荐-夏韶声《谙2》SACD-ISO
- 钟镇涛-《百分百钟镇涛》首批限量版SACD-ISO
- 群星《继续微笑致敬许冠杰》[低速原抓WAV+CUE]
- 潘秀琼.2003-国语难忘金曲珍藏集【皇星全音】【WAV+CUE】
- 林东松.1997-2039玫瑰事件【宝丽金】【WAV+CUE】