发布网友 发布时间:2024-09-30 19:41
共1个回答
热心网友 时间:18小时前
事情的起因是这样的。笔者在摸鱼期间突然发现首屏加载的几个js库的gzip大小只有10几k!!!10几k,这就离谱,是gz压缩的功劳吗?再细看一下,卧槽,不得了,原文件大小也就20来k!好,爱折腾搞事的我,在此就萌生了一个优化的想法了......
本文方案是笔者去年自己琢磨出来的一个优化思路,并不是业界常用的首屏优化方案,适用性方面可能有所*~主要出发点就是为了提升gzip的压缩率,所以才有了本文的优化实现方案的思路。因为在面试中有面试官也认可这种方式,所以打算写成文章把思路分享出来~反正大?各取所需!
接下来,让我们一起开始折腾,再提升首屏性能亿点点!
一、优化想法萌生1.场景介绍简单介绍下,笔者负责的项目通过找运维进行黑盒操作,开启服务器gzip的资源加载方式,所有资源都进行gzip压缩了。其中,除了项目的业务代码,还包括vue、vue-router、axios、vuex、elementui等等这些在打包阶段被我externals掉的第三方库
来看看是不是你熟悉的webpackexternals的配置!
configureWebpack:?config?=>?{...??config.externals?=?{????"vue":?"Vue",????"vue-router":?"VueRouter",????"vuex":?"Vuex",????"element-ui":?"ELEMENT",????"axios":?"axios"??};...????}好了,那externals的库,你是通过什么方式让页面加载的呢?笔者所在的公司有一个专门放第三库的cdn,所以是直接通过5个script标签对这几个第三库的cdn进行加载~如果你的项目也是这样,那ok,可以接着往下看,如果不是这样的话,那场景可能就不适用了,可以不用再往下看了!
2.gzip的压缩率低不知道大家有没有注意到这么一点,有一些第三库的包体积,本身就很小!笔者去node_moles下找几个库为例:
从这里引发一个思考的点,这个包大小本来就不大,那gzip压缩完的效果能减少多少体积呢?这个时候你是不是也跟我想到一起了?有些包压缩完基本没有太大优化空间,比如vuex这种,全压完也就只能优化10来k~有没有办法更加优化压缩率呢!接着往下看
二、实践出真知1.gzip压缩原理关键的两个:LZ77与哈夫曼编码。网络传输的内容都会通过文本的形式传输嘛,所以可以简单理解成对字符串进行压缩处理。这里只会简单描述一下,如果需要深入的话,大家自行去找一下相应的资料看看就好了~
LZ77。只需要知道:第一个字符串的内容和重复的字符串相对于首串的:距离+长度即可
比如:0111111001111110可以换成01111110(8,8)
哈夫曼编码。字符重新编码,保证出现频率越高的字符占用的字节越少。
根据以上两点,我们不难发现,压缩的两个关键都是针对重复的字符串做手脚!那如果我们的一个文件比较小,那能重复的内容可能就偏少,如果是一个大文件,那么能重复的内容就更多,基于这么一个出发点,我们把小文件都合并起来,看看效果,实践一下!
2.提升gzip的压缩率不知道读到这里的你会不会跟我一样,想到当年有个前端优化方案叫雪碧图的东西。它的做法就是把多个小图片合成一个大图片,以减少资源的加载次数,并且合并后的图片可能还会比所有原片加起来的总和小!笔者就是这么想,且是这么干的,就是通过把文件合并起来,组成一个更大点的文件,以此来提高文件内容的重复度,提升gzip的压缩率!
看下这段node的代码,很简单:
const?fs?=?require("fs");const?path?=?require("path");const?zlib?=?require("zlib");?//?用了?node?提供的?zlib?模块实现?gz?压缩//?获取命令参数,如输入命令:node?执行文件.js?axios.min.jsconst?[fileName]?=?process.argv.slice(2)//?这里的fileName拿到的就是?axios.min.js?//调用压缩函数gzipFn(fileName)function?gzipFn(fileName)?{??const?sourcePath?=?path.resolve(__dirname,?fileName);??//?输出的文件名,gz后缀??const?gzipPath?=?`${sourcePath}.gz`;??const?gzip?=?zlib.createGzip();??//?读原文件?xx.min.js??const?rs?=?fs.createReadStream(sourcePath);??//?写入后缀?gz?结尾的新文件??const?ws?=?fs.createWriteStream(gzipPath);??rs.on("err",?function?(err)?{????console.log("gzip?run?err?>>>",?err);??});??//?使用?gzip?压缩文件??rs.pipe(gzip).pipe(ws);}把案例中externals的文件全部copy放在一个文件夹下,再全部使用上述的node代码进行gzip压缩。执行命令如下,总共6条命令(其中whole.js就是把5个文件整合在一起的大文件~)
接下来,我们分别计算5个gzip文件大小的总和,再和我们5个文件合并的whole.js的gzip文件大小进行比较,结果如下图:
5个文件夹起来的计算结果是:144472+9719+34100+6100+3877=198268字节!
whole文件的gz大小是:196465字节
根据上图可知,先把5个文件合并起来再进行gz压缩,实际大小是比分开进行gz压缩要小的,换算下来差不多1~2k的优化空间吧~
菜?笔者在这里问问大?,你们觉得这个方案可行吗??
好了,本文到这里就结束了~其实读完的你可能会觉得笔者多此一举,因为优化力度不是十分大,但是其实笔者更多的是想分享这样一个优化的思路。毕竟性能能追求更好的,为什么不追求呢,这里提供的一个思路,在一定的场景说不定能优化好几k甚至上10k的资源体积大小~对于一些海外的用户来说,首屏能少10k说不定能极大的提升用户体验了~?还是文章开头说的吧,不是业界的方案,只是个人的思考的一个方向,大佬们觉得没用的也不要喷,觉得有用的话可以实战应用到自己的项目中试试效果,反正我就是这么应用的~
原文:https://juejin.cn/post/7095668844319997988