代码均放在 git仓库
Webpack 4给我们带来了一些改变。包括更快的打包速度,引入了SplitChunksPlugin插件来取代(之前版本里的)CommonsChunksPlugin插件。在这篇文章中,你将学习如何分割你的输出代码,从而提升我们应用的性能。
SplitChunks插件( webpack 4.x以前使用CommonsChunkPlugin
)允许我们将公共依赖项提取到现有的 entry chunk
或全新的代码块中。
代码分割的理念
首先搞明白: webpack里的代码分割是个什么鬼? 它允许你将一个文件分割成多个文件。如果使用的好,它能大幅提升你的应用的性能。其原因是基于浏览器会缓存你的代码这一事实。每当你对某一文件做点改变,访问你站点的人们就要重新下载它。然而依赖却很少变动。如果你将(这些依赖)分离成单独的文件,访问者就无需多次重复下载它们了。
使用webpack生成一个或多个包含你源代码最终版本的“打包好的文件”(bundles),(概念上我们当作)它们由(一个一个的)chunks组成。
首先 webpack 总共提供了三种办法来实现 Code Splitting,如下:
- 入口配置:entry 入口使用多个入口文件;
- 抽取公有代码:使用 SplitChunks 抽取公有代码;
- 动态加载 :动态加载一些代码。
这里我们姑且只讨论使用 SplitChunks 抽取公有代码。
splitChunks配置
在src目录下创建三个文件pageA.js、pageB.js和pageC.js。代码详情见文章开头git仓库。
// src/pageA.js var react = require('react'); var reactDom = require('react-dom'); var utility1 = require('../utils/utility1'); var utility2 = require('../utils/utility2'); new Vue(); module.exports = "pageA";
// src/pageB.js var react = require('react'); var reactDom = require('react-dom'); var utility2 = require('../utils/utility2'); var utility3 = require('../utils/utility3'); module.exports = "pageB";
// src/pageC.js var react = require('react'); var reactDom = require('react-dom'); var utility2 = require('../utils/utility2'); var utility3 = require('../utils/utility3'); module.exports = "pageC";
入口文件 && 出口文件
entry: { pageA: "./src/pageA", // 引用utility1.js utility2.js pageB: "./src/pageB", // 引用utility2.js utility3.js pageC: "./src/pageC", // 引用utility2.js utility3.js }, output: { path: path.join(__dirname, "dist"), filename: "[name].[hash:8].bundle.js" },
配置optimization
首先我们配置optimization如下:
optimization: { splitChunks: { chunks: "all", },
执行npm run build打包命令之后,查看dist目录
可以发现,打包出来的除了三个page文件,还存在一个vendors~pageA~pageB~pageC.[hash].bundle.js文件( 此文件中保存了pageA、pageB、pageC和node_modules中共有的size大于30KB的文件 )。事实上这全靠了配置中本身默认固有一个cacheGroups的配置项:
splitChunks: { chunks: "all", cacheGroups: { vendors: { test: /[\\/]node_modules[\\/]/, // 匹配node_modules目录下的文件 priority: -10 // 优先级配置项 }, default: { minChunks: 2, priority: -20, // 优先级配置项 reuseExistingChunk: true } } }
在默认设置中,会将 node_mudules 文件夹中的模块打包进一个叫 vendors的bundle中,所有引用超过两次的模块分配到 default bundle 中。更可以通过 priority 来设置优先级。
参数说明如下:
- chunks:表示从哪些chunks里面抽取代码,除了三个可选字符串值 initial、async、all 之外,还可以通过函数来过滤所需的 chunks;
- minSize:表示抽取出来的文件在压缩前的最小大小,默认为 30000;
- maxSize:表示抽取出来的文件在压缩前的最大大小,默认为 0,表示不限制最大大小;
- minChunks:表示被引用次数,默认为1;上述配置commons中minChunks为2,表示将被多次引用的代码抽离成commons。
值得注意的是,如果没有修改minSize属性的话,而且被公用的代码(假设是utilities.js)size小于30KB的话,它就不会分割成一个单独的文件。在真实情形下,这是合理的,因为(如分割)并不能带来性能确实的提升,反而使得浏览器多了一次对utilities.js的请求,而这个utilities.js又是如此之小(不划算)。
- maxAsyncRequests:最大的按需(异步)加载次数,默认为 5;
- maxInitialRequests:最大的初始化加载次数,默认为 3;
- automaticNameDelimiter:抽取出来的文件的自动生成名字的分割符,默认为 ~;
- name:抽取出来文件的名字,默认为 true,表示自动生成文件名;
- cacheGroups: 缓存组。(这才是配置的关键)
缓存组会继承splitChunks的配置,但是 test、priorty和reuseExistingChunk只能用于配置缓存组 。cacheGroups是一个对象,按上述介绍的键值对方式来配置即可,值代表对应的选项。除此之外,所有上面列出的选择都是可以用在缓存组里的:chunks, minSize, minChunks, maxAsyncRequests, maxInitialRequests, name。可以通过optimization.splitChunks.cacheGroups.default: false禁用default缓存组。 默认缓存组的优先级(priotity)是负数,因此所有自定义缓存组都可以有比它更高优先级(译注:更高优先级的缓存组可以优先打包所选择的模块)(默认自定义缓存组优先级为0)
现在我们再重新来看一下pageA、pageB、pageC三个js文件,这三个文件中都引入了utility2.js文件,但是此文件size很明显小于30KB,所以这部分公用代码并没有分割出来。如果想要分割出来很简单,只需要:
optimization: { splitChunks: { chunks: "all", minSize: 0 },
执行npm run build打包命令之后,查看dist目录
显然多了一个pageA~pageB~pageC.[hash].bundle.js文件。查看文件可得知此文件中存储了utility2.js中的代码。如下图所示(借助于webpack-bundle-analyzer插件,详情文章末尾附录)。
上图可以看出,React相关代码均放在了vendors~pageA~pageB~pageC.[hash].bundle.js文件中,如果我们想要抽离出React代码,应该怎么做呐?
splitChunks: { chunks: "all", cacheGroups: { commons: { chunks: "initial", minChunks: 2, name: "commons", maxInitialRequests: 5, minSize: 0, // 默认是30kb,minSize设置为0之后 // 多次引用的utility1.js和utility2.js会被压缩到commons中 }, reactBase: { test: (module) => { return /react|redux|prop-types/.test(module.context); }, // 直接使用 test 来做路径匹配,抽离react相关代码 chunks: "initial", name: "reactBase", priority: 10, } } },
run build之后如下图所示。
看似非常完美,但是reactBase文件中竟然包含了node_modules,神奇的问题?室友都睡觉了,这键盘声影响不好,明天接着看。
附录
我们再安装一个 webpack-bundle-analyzer,这个插件会清晰的展示出打包后的各个bundle所依赖的模块:
npm i webpack-bundle-analyzer -D
引入:
const BundleAnalyzerPlugin = require('webpack-bundle-analyzer').BundleAnalyzerPlugin
使用,在plugins数组中添加即可:
new BundleAnalyzerPlugin()
以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持。
免责声明:本站资源来自互联网收集,仅供用于学习和交流,请遵循相关法律法规,本站一切资源不代表本站立场,如有侵权、后门、不妥请联系本站删除!
稳了!魔兽国服回归的3条重磅消息!官宣时间再确认!
昨天有一位朋友在大神群里分享,自己亚服账号被封号之后居然弹出了国服的封号信息对话框。
这里面让他访问的是一个国服的战网网址,com.cn和后面的zh都非常明白地表明这就是国服战网。
而他在复制这个网址并且进行登录之后,确实是网易的网址,也就是我们熟悉的停服之后国服发布的暴雪游戏产品运营到期开放退款的说明。这是一件比较奇怪的事情,因为以前都没有出现这样的情况,现在突然提示跳转到国服战网的网址,是不是说明了简体中文客户端已经开始进行更新了呢?
更新日志
- 凤飞飞《我们的主题曲》飞跃制作[正版原抓WAV+CUE]
- 刘嘉亮《亮情歌2》[WAV+CUE][1G]
- 红馆40·谭咏麟《歌者恋歌浓情30年演唱会》3CD[低速原抓WAV+CUE][1.8G]
- 刘纬武《睡眠宝宝竖琴童谣 吉卜力工作室 白噪音安抚》[320K/MP3][193.25MB]
- 【轻音乐】曼托凡尼乐团《精选辑》2CD.1998[FLAC+CUE整轨]
- 邝美云《心中有爱》1989年香港DMIJP版1MTO东芝首版[WAV+CUE]
- 群星《情叹-发烧女声DSD》天籁女声发烧碟[WAV+CUE]
- 刘纬武《睡眠宝宝竖琴童谣 吉卜力工作室 白噪音安抚》[FLAC/分轨][748.03MB]
- 理想混蛋《Origin Sessions》[320K/MP3][37.47MB]
- 公馆青少年《我其实一点都不酷》[320K/MP3][78.78MB]
- 群星《情叹-发烧男声DSD》最值得珍藏的完美男声[WAV+CUE]
- 群星《国韵飘香·贵妃醉酒HQCD黑胶王》2CD[WAV]
- 卫兰《DAUGHTER》【低速原抓WAV+CUE】
- 公馆青少年《我其实一点都不酷》[FLAC/分轨][398.22MB]
- ZWEI《迟暮的花 (Explicit)》[320K/MP3][57.16MB]