Web 前端性能优化之五:构建优化

4、构建优化

资源的合并与压缩所涉及的优化点包括两方面:一方面是减少HTTP的请求数量,另一方面是减少HTTP请求资源的大小。

1、HTML 压缩
1、什么是 HTML 压缩

在这里插入图片描述

百度首页部分 HTML 源代码

在这里插入图片描述

谷歌首页部分 HTML 源代码

虽然这些格式化的字符能带来很好的代码可读性,但对浏览器解析过程来说其实并不需要,反而还增加了资源的开销。

HTML压缩就是要删除在文本文件中有意义的,但在HTML中并不参与解析的字符。这些字符包括空格、制表符、换行符及一些其他意义的字符,如HTML注释等。

如果单纯只看一个文件的压缩,可能效果并不明显,比如就以前面百度首页为例,原始字符长度为158519,经过压缩之后的长度为157334,长度减少了约0.75%。

难道这就能说明HTML压缩的效果不明显吗?其实我们不能这么考虑,对大型的互联网公司来说,每一个请求的减少都是一个非常大的优化。以谷歌为例,它的网络流量占到了全网流量的40%左右,假如网络流量能达到5ZB(1ZB=109TB),以谷歌的流量占比,它当年的实际网络流量就是5ZB×40%=2ZB,那么当谷歌经过优化让每1MB的请求减少一个字节,则整年便可节省2000TB的流量。如果以每GB流量一毛钱计算,那么一年省下来的开支也不是个小数目,这就是要进行HTML压缩的原因。

2、如何压缩
1、使用 html-minifier

使用nodejs所提供的html-minifier工具进行压缩,它涉及很多参数的配置,包括是否去掉注释removeComments,是否去掉空格collapseWhitespace,是否压缩HTML中的JavaScript的minifyJS及是否压缩HTML中的CSS的minifyCSS,具体方式如下:

在这里插入图片描述

2、CSS 压缩

CSS代码也能进行压缩,而且很有必要去压缩,如下是谷歌首页经过压缩的部分CSS源代码:

在这里插入图片描述

谷歌首页部分 CSS 源代码

从中非常直观的感受是它去掉了回车和换行,此外这里的CSS压缩还做了两件事:首先是无效代码的删除,因为对有些CSS来说,无效的代码可能是注释和无效字符,需要将这些无效的代码删除,这一步很重要;其次是CSS语义合并,通常我们写的CSS可能由于文件层级的嵌套,很难避免一定的语义重复,所以就需要进行语义合并。

可以使用html-minifier针对HTML中的CSS进行压缩。除此之外,还可以使用clean-css进行CSS的压缩,其基本使用方法如下:

在这里插入图片描述

clean-css也有许多配置项,比如是否基于语义进行合并的merging,是否优化颜色取值的colors,以及诸多对不同类型浏览器兼容性的规则导出。

3、JavaScript 压缩与混淆

JavaScript部分的处理主要包括三个方面:无效字符和注释的删除、代码语义缩减和优化及代码混淆保护。无效字符和注释的删除原理与HTML和CSS的压缩类似。

1、代码语义缩减和优化

通过对JavaScript的压缩可以将一些变量的长度进行缩短,比如说原本一个很长的变量名经过压缩后,可以用很短的像a、b来代替,这样能进一步有效地缩减JavaScript的代码量。同样还可以针对一些重复代码进行优化,比如去除重复的变量赋值,将一些无效的代码进行缩减与合并的优化。

在这里插入图片描述

2、代码混淆保护

由于任何能够访问到网站页面的用户,都可以通过浏览器的开发者工具查看到前端的JavaScript代码,如果前端代码的语义非常明显,没进行压缩也没进行混淆,其格式还完整保留,那么理论上任何访问网站的人都可以轻易地窥探到我们代码中的逻辑,从而去做一些威胁系统安全的事情。所以进行JavaScript代码压缩和混淆的处理,也是对我们前端代码的一种保护。

如何来防止别有用心之人窥探到我们业务的核心代码呢?实际上就是进行JavaScript压缩,将前端源代码的可读性变得尽可能低,混淆变量与方法的命名。

对大部分公司来说,HTML压缩可有可无,但是CSS与JavaScript压缩却是必须要进行的。

JavaScript压缩处理也有类似的第三方库可供使用:uglifyJS2。可以通过npm引入uglify-js库来使用,也可以结合构建工具一起使用,其单独使用时的方法如下:

在这里插入图片描述

其中压缩混淆的配置对象结构如下:

在这里插入图片描述

4、webpack 构建与优化
1、尽量与时俱进:尽可能使用最新稳定版本的webpack、nodejs、npm或yarn能有效地提升打包构建的效率。
2、较少 Loader 的执行

根据具体情况使用include或exclude,在尽可能少的模块上执行Loader。webpack的配置文件如下:

在这里插入图片描述

这里关注module字段中对JavaScript文件的处理规则,如果不加exclude字段,则webpack会对该配置文件所在路径下的所有JavaScript文件使用babel-loader,虽然babel-loader的功能强大,但它执行起来很慢。

这样所处理的JavaScript不仅会包含我们的项目源代码,还会涉及node_modules路径下项目引用的所有第三方文件。由于第三方库的文件在发布前本身已经执行过一次babel-loader,没必要再重复执行一次,增加不必要的打包构建耗时,所以exclude字段不可省略。

同时与之对应的还有一个include字段,其使用含义与exclude相反,即仅对其指定范围内的JavaScript文件进行处理,以降低loader被执行的频率。

对于图片文件则没有必要通过include或exclude来降低loader的执行频率,因为无论哪里引入的图片,最后打包都需要通过url-loader对其进行处理,所以include或exclude的语法并不适用于所有loader类型,要根据具体的情况而定。

使用exclude或include可以帮助我们规避对庞大的第三方库文件的处理,但仅通过限定文件处理范围所带来的性能提升其实是有限的,除此之外,如果开启缓存将构建结果缓存到文件系统中,则可让babel-loader的工作效率得到成倍增加,处理方式也很简单,只需为loader增加相应的参数即可:

在这里插入图片描述

3、确保插件的精简和可靠

建议使用webpack官方网站上推荐的插件

4、合理配置 resolve 参数

配置resolve参数可以为我们在编写代码引入模块时提供不少便利,比如使用extensions省略引入JavaScript文件的后缀,使用alias减少书写所引入模块的多目录层级,使用mainFiles声明目录下的默认使用文件等,但当我们使用这些参数带来便利的同时,如果滥加使用也会降低打包速度。

1、可对 js、ts 省略路径,但不要对 css、图片等设置

在这里插入图片描述

可以使用resolve中的extensions属性来申明这些后缀,让项目在构建打包时,由webpack帮我们查找并补全文件后缀。同时对组件路径的引用也可通过resolve的alias配置来进行简化,配置如下:

在这里插入图片描述

如此配置的含义是,当所引入的模块默认了文件后缀时,webpack会在其指定路径下依次查找是否有.js、.jsx、.ts这三种后缀的文件,如果有便使用,并且在模块引入的同时用cpn代替src/component。当有了上述配置后,之前提到的Hello模块的引入便可写成如下形式:

在这里插入图片描述

2、不建议使用 mainFiles 属性

另外,resolve还有一个mainFiles属性,通过对它的配置可以指定让webpack查找引入模块路径下的默认文件名,虽然它能在很大程度上简化模块引用的编码量,但付出的代价是增加了打包构建过程中对目标文件的查找时间,所以不建议使用

5、使用 DllPlugin

前端项目中经常会用到庞大的第三方库,来协助我们完成特定功能的开发,而每当发生修改需要重新进行打包时,webpack会默认去分析所有引用的第三方组件库,最后将其打包进我们的项目代码中。在通常情况下,第三方组件包的代码是稳定的,不更换所引用的版本其代码是不会发生修改的,所以这就给出了一条优化的思路:我们仅需要在第一次打包时去分析这些第三方库,而在之后的打包过程中只需使用之前的结果即可。

这便会用到DllPlugin,它是基于Windows动态链接库(DLL)的思想创建出来的,该插件会把第三方库单独打包到一个文件中,作为一个单纯的依赖库,它不会和我们的项目代码一起参与重新打包,只有当依赖自身发生版本变化时才会重新进行打包。

使用DllPlugin处理文件的过程可分为两步:首先基于动态链接库专属的配置文件打包dll库文件,然后再基于webpack的构建文件打包项目代码。下面以一个简单的React组件为例:

在这里插入图片描述

这里引入了三个在React项目中经常会遇到的第三方包react、react-dom和lodash,如果我们不进行任何处理,每当修改该文件后进行重新打包,则都会引起webpack去分析它们,若打包次数频繁,显然会浪费许多时间。

接下来我们进行优化,具体分为两步,首先将所依赖的第三方库打包成dll文件,然后检查第三方库的版本是否在其后的迭代中发生了变化,若无变化就都使用之前的打包结果。这里可以为第三方库创建单独的配置文件,内容如下:

在这里插入图片描述

该配置文件中将react、react-dom和lodash三个包的包名存储在数组中,并赋值给vendors,其含义是经过打包后,这三个包归于一个名为vendors的包。output中声明了该包的文件名及输出路径,library字段表示该第三方包对外暴露的引用名,即在其他地方可以使用该字段值引用包中的内容。最后使用webpack中的DllPlugin插件对该包中的映射关系进行分析,并将结果输出到指定路径下的json文件。

然后我们需要在webpack主配置文件中,声明对上述打包好的第三方包的使用规则:

在这里插入图片描述

这样配置的意思是首先引入第三方包的打包结果路径,其次引入第三方包的映射关系,当发生重新打包构建时,webpack会首先查看引用的第三方包是否包含在已建立的映射关系文件vendor.manifest.json中,若存在便通过所声明的全局变量vendors去使用,若不存在便去node_modules中获取所需的模块,动态地进行打包操作。

上述方式虽然能够降低重复打包构建的时间,但将项目中所有第三方包都打包进一个文件,势必会使其体积过大从而导致请求过慢,所以在实际项目中,我们也应根据各个第三方包的大小进行拆分,就上述代码而言,可将react和react-dom从vendors中组成为一个新包,代码如下:

在这里插入图片描述

如此在执行webpack构建后会生成四个文件,分别是:vendors包的代码文件vendors.dll.js和其映射关系文件vendors.manifest.json,react包的代码文件react.dll.js和其映射关系文件react.manifest.json,同时对应的主配置文件也需要进行相应的修改,以引入打包的代码文件和映射关系文件。

在这里插入图片描述

这样处理后,既降低了重复构建时的打包时间,又规避了打包成单一文件时,可能由于代码文件体积过大而存在加载过慢的风险。

6、将单进程转化为多进程

webpack是单进程的,就算有多个任务同时存在,它们也只能一个一个排队依次执行,这是nodejs的限制。

但好在大多数CPU已经都是多核的了,我们可以使用happypack充分释放CPU在多核并发方面的优势,帮助我们把打包构建任务分解成多个子任务去并发执行,这将大大提高打包的效率。其使用方法也很简单,就是将原有的loader配置转移到happypack中去处理:

在这里插入图片描述

7、压缩打包结果的体积
1、删除冗余代码

webpack从2.0版本开始,便基于ES6推出了Tree-shaking,它能根据import、export的模块导入导出语法,在构建编译过程中分析每个模块是否被真实使用,对于没用到的代码,会在最后的打包结果中删除。

容易看出Tree-shaking对处理模块级的代码冗余比较擅长,但对更细粒度的代码冗余,比如console语句、注释等,可能就需要在CSS和JavaScript压缩过程中进行处理了,常用的方式是通过uglifyjs-webpack-plugin来实现的,具体配置方式如下:

在这里插入图片描述

2、代码拆分按需加载

项目源代码也需要拆分,可以根据路由来划分打包文件,当访问到不同路由时再触发相应回调请求打包文件,对于webpack的打包输出的配置如下:

在这里插入图片描述

以React项目为例,在配置路由时还需添加如下内容:

在这里插入图片描述

此处的关键方法就是require.ensure这个异步方法,webpack会将我们这里定义的组件单独打包成一个文件,仅当路由跳转到mine时,才会触发回调去获取MyComponent组件的内容。

3、可视化分析

分析打包结果的可视化工具:webpack-bundle-analyzer。它的分析结果会生成一个文件大小图:

该插件的工作原理也比较简单,就是分析在compiler.plugin(‘done’,function(stats));时传入的参数stats,它是webpack的一个统计类Stats的实例,然后通过对实例调用toJson()方法转成json文件,再从中提取出chunks各个包的大小信息,最后在Canvas中进行画图。通过该图能让开发者快速意识到哪些模块异常的大,然后找出过大的原因去优化它。

在这里插入图片描述

webpack-bundle-analyzer分析结果

该工具使用起来也很方便,就如使用普通插件一样:

在这里插入图片描述

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/525346.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

LiDAR点云转3D Tiles

到 2026年,一个国家项目旨在绘制整个法国领土的三维地图。 美国国家地理和林业信息研究所 (IGN) 是这个名为“Lidar HD”的“项目”的幕后黑手,其目标是获得该地区非常精确的 3D 描述。 NSDT工具推荐: Three.js AI纹理开发包 - YOLO合成数据生…

内外网数据交换发展进程:安全与便捷并行

随着信息化的不断推进,医院、党政以及企业的内外网数据交换正成为日益关注的焦点。在保障数据安全的前提下,需要寻求一种既安全可靠又操作便捷的数据传输方式。本文将探讨内外网数据交换发展进程,分析各种传输方式的优缺点,以及它…

爬虫入狱笔记——xx政府网站公开政策数据

最近在学习爬虫,做个笔记吧 今天爬xx政府网站-政策法规栏目的数据 咱们首先需要找到数据从哪里来,鼠标右键->检查(或者快捷键一般为F12)检查元素,搜索关键词 eg.【违法案例】 回车, 如果没有的话&am…

【随笔】Git 高级篇 -- 整理提交记录(下)rebase(十六)

💌 所属专栏:【Git】 😀 作  者:我是夜阑的狗🐶 🚀 个人简介:一个正在努力学技术的CV工程师,专注基础和实战分享 ,欢迎咨询! 💖 欢迎大…

【Vue】我的第一个组件

文章目录 项目简介 项目简介 项目根目录中的index.html是项目的入口文件 加载index.html,vite解析。指向的src下的ts文件或者js文件 最后通过vue3的createApp函数创建一个应用,并挂载到指定div下 App.vue结构说明 特别注意:script脚本内&#xff0…

51单片机入门_江协科技_17~18_OB记录的笔记

17. 定时器 17.1. 定时器介绍:51单片机的定时器属于单片机的内部资源,其电路的连接和运转均在单片机内部完成,无需占用CPU外围IO接口; 定时器作用: (1)用于计时系统,可实现软件计时&…

Golang 开发实战day08 - Multiple Return values

Golang 教程08 - Multiple Return values 1. Multiple return values 1.1 如何理解多个返回值? Go语言中的多返回值,就像你听了一首歌曲yellow,可以从歌曲里反馈出忧郁和害羞!Goland的多个返回值就类似于如此,设定一…

C++版本GDAL3.5无法找到proj.db文件

问题:C版本的GDAL无法找到proj.db文件 自己编译过的gdal3.5版本在自己电脑上使用坐标转换没有问题,而将库文件和头文件迁移到别的笔记本上转换坐标出实现问题: ERROR 1: PROJ: proj_create_from_database: Cannot find proj.db ERROR 1: PRO…

C语言第四十一弹---猜数字游戏

✨个人主页: 熬夜学编程的小林 💗系列专栏: 【C语言详解】 【数据结构详解】 猜数字游戏 1、随机数生成 1.1、rand 1.2、srand 1.3、time 1.4、设置随机数的范围 2、猜数字游戏的分析和设计 2.1、猜数字游戏功能说明 2.2、猜数字游戏…

新人硬件工程师往哪个方向更有前途?

如果是比较沉默寡言,不擅长交际的,那么可以走技术路线。我这里有一套自动化入门教程,不仅包含了详细的视频讲解,项目实战。如果你渴望学习自动化,不妨点个关注,给个评论222,私信22,我…

让chatGPT控制物理设备

作为自动控制行业的工程师,我们也许最关心的是如何使chatGPT 控制物理设备。我发现许多人仍然停留在传统程序设计的思维阶段,比如让大模型编写一段PLC 代码,或者是生成一些信息模型。 其实大模型具备判断与思考的能力,AI …

数字乡村:科技引领新时代农村发展

随着信息技术的迅猛发展和数字化浪潮的推进,数字乡村作为新时代农村发展的重要战略,正日益成为引领农村现代化的强大引擎。数字乡村不仅代表着农村信息化建设的新高度,更是农村经济社会发展的重要支撑。通过数字技术的深入应用,农…

【C#】读取指定XML节点

&#x1f4f0;XML文件 <?xml version"1.0" encoding"utf-8"?> <configuration><userSettings><Internal.Settings type"Desktop"><setting name"StatsDisplayCount" serializeAs"String">…

【每周精选资讯 | 第 4 期】2024-04-01 ~ 2024-04-08

文章目录 前言阿里巴巴&#xff1a;推出Qwen1.5-32B 模型文心一言&#xff1a;定制自己的 AI 声音动画线条图自动填色SWE-agent&#xff1a;AI程序员OpenAI&#xff1a;收集高质量训练数据Stability AI 发布 Stable Audio 2.0OpenAI&#xff1a;开放GPT3.5&#xff0c;无需注册…

百度富文本编辑器配置(vue3)

今天分享一下我做的项目里面的一个百度富文本的配置问题&#xff0c;安装配置流程以及如何解决的 1.首先是安装组件 # vue-ueditor-wrap v3 仅支持 Vue 3 npm i vue-ueditor-wrap3.x -S # or yarn add vue-ueditor-wrap3.x 2. 下载 UEditor UEditor 并不支持通过 npm 的方式…

Matlab进阶绘图第49期—气泡堆叠图

气泡堆叠图是堆叠图与气泡图的组合—在堆叠图每根柱子上方添加大小不同的气泡&#xff0c;用于表示另外一个数据变量&#xff08;如每根柱子各组分的平均值&#xff09;的大小。 本文利用自己制作的BarBubble工具&#xff0c;进行气泡堆叠图的绘制&#xff0c;先来看一下成品效…

c语言:操作符

操作符 一.算术操作符: + - * % / 1.除了%操作符之外,其他的几个操作符可以作用与整数和浮点数,如:5%2.0//error. 2.对于操作符,如果两个操作数都为整数,执行整数除法而只要有浮点数执行的就是浮点数除法。 3.%操作符的两个操作数必须为整数。 二.移位操作符:<&…

如何在 Windows上安装 Python

系列文章目录 作者&#xff1a;i阿极 作者简介&#xff1a;数据分析领域优质创作者、多项比赛获奖者&#xff1a;博主个人首页 &#x1f60a;&#x1f60a;&#x1f60a;如果觉得文章不错或能帮助到你学习&#xff0c;可以点赞&#x1f44d;收藏&#x1f4c1;评论&#x1f4d2;…

SQL Server语法基础:入门到精通

博客前言 在数据库管理的世界中&#xff0c;SQL Server无疑是一个重要的角色。无论是初学者还是经验丰富的数据库管理员&#xff0c;都需要对SQL Server的查询语法有深入的理解。本文将带领大家深入解析SQL Server的查询语法&#xff0c;并分享一些实用的技巧&#xff0c;帮助…

C语言数组:数据的集合艺术(续)

前言 在上一篇文章中&#xff0c;我们深入探讨了C语言数组的基本概念、操作以及多维数组的应用。今天&#xff0c;我们将继续探索数组的更多高级特性&#xff0c;包括动态内存分配、指针与数组的关系以及数组在实际编程中的应用案例。 一、动态内存分配与数组 在C语言中&…