Web前端性能优化(一)

2024-03-19 19:51:29 浏览数 (2)

UnsplashUnsplash

静态资源的压缩与合并

我们在开发的时候会习惯缩进和写注释,方便我们在日常的维护,但将代码上传至服务端后,我们完全可以把那些空格、制表符、换行符进行压缩,以此减少请求资源的大小;同样的,我们在服务端所引用的第三方库进行合并,能减少 HTTP 的请求数量

  • 将 HTML 文件里的空格、制表符、换行符进行压缩,并剔除所有注释
  • 将 CSS 文件里的空格、制表符、换行符进行压缩,无效代码删除,CSS 语义合并
  • 将 JS 文件压缩与混乱,无效字符的删除,剔除注释,代码语义的缩减和优化(变量名过长,使用其他字符进行代替),代码保护

代码压缩可以使用 开源中国_在线工具 进行压缩,不过这种方式面对需要大量压缩的代码会显得效率低下,推荐大家使用 html-minifier 插件进行压缩,CSS 还可以使用 clean-css 进行压缩,JS 可以使用 uglifyjs2 进行压缩

在 CSS 或 JS 文件中引用第三方插件,即表明我们在引用第三方资源时需要请求大量的文件,在 keep-alive 模式下,文件与文件直接会插入上行请求,增加网络延迟,受到丢包影响会更严重,经过代理服务器时也可能会断开

在将文件进行合并前,有两个地方需要大家注意下,① 将公共库和业务库分开合并,这样的好处是,我们迭代版本的时候,只需要更新业务库即可,在 Vue, React 框架中也是作同样处理;② 若是在 Vue 或 React 项目中,还建议大家将不同页面所需要的 JS 进行合并,只有当路由到该页面的时候,才请求该页面所需要的组件

合并之后的文件要占据更多容量,所请求时间更久,若是首屏渲染依赖 JS,则会出现首次加载出现白屏的情况,这种场景一般存在于Vue,React框架使用过程中,在没有使用服务端渲染的情况下,是将整个过程通过框架进行接管的

我们在标记 JS 文件是否被更改时,通常会在该 JS 文件后加一个 MD5 戳,用来唯一标识该 JS 文件是否被更改,若是合并前的任一个文件有改动,那么合并后的整个文件缓存都会失效

文件合并的方式同样可通过在线网站或 NodeJS 进行合并,在此不再复述

图片优化

我们一般所用到的图片格式为 jpg, png, webp, svg,而不同的图片格式所对应的业务场景也不相同,jpg 格式图片为有损压缩,压缩率高,不支持透明,适用大部分不需要透明图片的业务场景;png 格式图片支持透明,浏览器兼容好,其中 png8 为 256 色,支持透明,png24 为 2^24 色,不支持透明,png32 为 2^24 色,支持透明;webp 格式图片压缩程度好,在 iOS webview 中有兼容性问题,推荐在 Android 中使用该格式图片;svg 格式图片,将图片内容内嵌到 HTML 中,通过使用 iconfont 解决 icon 问题,减少 HTTP 请求,适用于图片样式相对简单的场景

webp 为谷歌开发的图片格式,其优势体现在它具有更优的图像数据压缩算法,能带来更小的图片体积,而且拥有肉眼识别无差异的图像质量;同时具备了无损和有损的压缩模式、Alpha 透明以及动画的特性,在 jpeg 和 png 上的转化效果都非常优秀、稳定和统一

雪碧图 CSS sprite 就是讲网站上用到的一些 icon 整合到一张单独图片中,通过 background-position 属性来显示相对应的图片,使用雪碧图的优点为,减少你的网站 HTTP 请求数量,相对而言,加载比较慢

同样推荐几个图片优化的在线网站, 图片压缩 TinyPNG,PNG 转换 Webp ,CSS Sprite 制作

一个网站在浏览器端是如何进行渲染的呢?

我们在浏览器地址栏输入网址之后,浏览器会对我们输入的 url 进行解析,并对相应的 IP 地址发起请求,请求所返回的是一段 HTML 文档,浏览器对该段 HTML 文档从上到下进行词法分析,其具体过程为:遇到 HTML 标签时,会生成一个 Token,不同类型的标签会解析成不同的 Token,根据 Token 产生对应的节点 Node,最终这些节点根据其嵌套关系,添加到 DOM 树上

在词法分析的过程中,HTML 文档中会通过 <link> 标签进行 CSS 资源引入,此时浏览器就会 **并发** 的向互联网或 CDN 请求相关的静态资源,请求回来之后的 CSS 资源同样会被浏览器解析,根据选择器进行匹配并生成相应的 CSSOM 规则树,跟 DOM 树相结合生成渲染树 **Render Tree**,从而进行布局 **Layout** 和绘制 **Paint**,利用渲染树的信息,计算渲染树中所有节点在页面上的位置和大小,填充 Layout 中的具体内容和样式

我们在 HTML 中所引入的外部资源,虽然是并发去请求的,但对于单个域名是存在并发上限的,即并发请求数是有一个上限的,这就导致很多资源没有全部做到并发请求,所以我们在生产环境中,常常会设置 3 到 4 个 CDN 域名

阻塞关系

CSS 和 JS 的加载都会引起阻塞,其中,CSS 通过 <link> 方式在 <head> 中进行引用,会阻塞页面的渲染;CSS 不阻塞 JS 的加载,但会阻塞 JS 的执行,其原因在于 JS 有可能进行 DOM 操作,涉及到 CSS 样式的修改,该操作基于所引入的 CSS 样式基础上进行的

直接引入的 JS 会阻塞页面的渲染,JS 在执行过程中运行 document.write,修改相关的文档结构,阻塞后面节点的创建,影响后续的文档结构渲染和分析,可以通过 defer属性 和 async 方式引入,避免这种情况出现,如果 JS 还操作了 CSSOM,而正好相关的 CSS 资源还没有引入,浏览器甚至会延迟 JS 的执行和 DOM 树的构建,直到完成其 CSSOM 的下载和构建,因此我们在引入 JS 资源时需要遵循两个原则:1. CSS 资源优先引入;2. JS 资源于页面底部引入,并尽量少影响 DOM 树的构建

Webkit 具有预先扫描器和预资源加载器的能力,执行当前 JS 代码的时候,会通过预先扫描器去扫描后面的词是否有引用到其他 JS 资源,就可以使用预先加载器并发的去请求后续资源,所以 JS 的执行不阻塞资源的加载

JS 执行在浏览器中是单线程的,所以 JS 是顺序执行并且会阻塞后续 JS 逻辑的执行,会保持我们引用的依赖关系进行执行

0 人点赞