0 系列文章目录
Web前端性能优化(一)
Web前端性能优化(二)
Web前端性能优化(三)
1 静态资源的压缩与合并
资源的合并与压缩主要涉及减少HTTP请求数量,减少请求资源的大小,我们在开发的时候会习惯缩进和写注释,方便我们在日常的维护,但将代码上传至服务端后,我们完全可以把那些空格、制表符、换行符进行压缩,以此减少请求资源的大小;同样的,我们在服务端所引用的第三方库进行合并,能减少 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 进行合并,在此不再复述
2 图片优化
我们一般所用到的图片格式为 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 制作
3 一个网站在浏览器端是如何进行渲染的呢?
我们在浏览器地址栏输入网址之后,浏览器会对我们输入的 url 进行解析,并对相应的 IP 地址发起请求,请求所返回的是一段 HTML 文档,浏览器对该段 HTML 文档从上到下进行词法分析,其具体过程为:遇到 HTML 标签时,会生成一个 Token
,不同类型的标签会解析成不同的 Token
,根据 Token
产生对应的节点 Node
,最终这些节点根据其嵌套关系,添加到 DOM 树上
在词法分析的过程中,HTML 文档中会通过 标签进行 CSS 资源引入,此时浏览器就会 并发 的向互联网或 CDN 请求相关的静态资源,请求回来之后的 CSS 资源同样会被浏览器解析,根据选择器进行匹配并生成相应的 CSSOM 规则树,跟 DOM 树相结合生成渲染树 Render Tree,从而进行布局 Layout 和绘制 Paint,利用渲染树的信息,计算渲染树中所有节点在页面上的位置和大小,填充 Layout 中的具体内容和样式
我们在 HTML 中所引入的外部资源,虽然是并发去请求的,但对于单个域名是存在并发上限的,即并发请求数是有一个上限的,这就导致很多资源没有全部做到并发请求,所以我们在生产环境中,常常会设置 3 到 4 个 CDN 域名
4 阻塞关系
CSS 和 JS 的加载都会引起阻塞,其中,CSS 通过 方式在
中进行引用,会阻塞页面的渲染;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 逻辑的执行,会保持我们引用的依赖关系进行执行
End of File
行文过程中出现错误或不妥之处在所难免,希望大家能够给予指正,以免误导更多人,最后,如果你觉得我的文章写的还不错,希望能够点一下喜欢和关注,为了我能早日成为优秀作者献上一发助攻吧,谢谢!^ ^