Web 前端性能优化原理问题
前端性能优化,资源的合并与压缩,图片编码的原理,以及类型的选择,浏览器的渲染机制,懒加载,预加载,浏览器存储,缓存机制,PWA 和 Vue-SSR 等。
技术栈,Vue.js 和 Chrome,调试工具 performance 和 layers。那么什么是前端性能优化原理的点,涉及作用以及原理,如何与真实的项目场景结合,理论结合实战经验,进行量化分析。
前端优化,一般是先基础优化(图片编码原理等问题),高一点 即为 进阶优化(浏览器的渲染机制,浏览器的存储,优化),结合服务端进行优化(首屏渲染等问题)等。
前端性能优化方案,最小化 HTTP 的请求,使用内容交付网络,避免空 src 或是 href,添加过期或者是缓存控制标头,gzip 组件,将 styleSheets 放在顶部,将脚本放在最下面,避免 css 表达式,减少 dns 的查找,将 js 和 css 设置为外部,避免重定向,配置 etag,使用 ajax 缓存,减少 dom 元素的数量,没有 404,减少 cookie 的大小,不缩放 HTML 中的图像,避免使用过滤器,使用 favicon.icon 小型且可缓存。
面试官拷问
面试官:为什么要进行前端优化?图片在前端是如何解码的?浏览器渲染加载的过程是如何进行的?懒加载和预加载的原理是什么样的?懒加载和预加载的应用场景是什么样的?PWA 和 VUE-SSR 等原理的是怎么样的?
面试官深度拷问每个优化性能后的原理是怎么样的?结合你自己做过的项目性能优化的原理是怎么样的?说说你在项目中使用过性能优化后的感悟心得?说说每个性能优化原理最适合的场景过程。
面试人员想要了解你掌握多少性能优化的原理,了解你做过项目上是否使用过性能优化,分析自身做过的项目,找到需要性能优化的点,选择合适的性能优化等。
影响前端性能的有图像,样式表,脚本,flash 等,减少组件的数量,减少所需的HTTP 请求的数量,即可加快页面的速度。
前端性能优化,资源的合并与压缩
合并文件是一种通过将所有脚本合并为一个脚本,类似将所有 css 合并为一个样式表来减少HTTP 请求数量的方法。
实现性能优化,第一,减少我们的HTTP 请求的数量,以及减少请求的资源大小,第二,资源的压缩与合并的原理是什么。压缩与合并前是什么样的效果,压缩与合并后又有什么区别。
拷问:浏览器的一个请求从发送到返回是一个怎样的过程?
url 分解,协议名称,层级 url 的标记符号,固定不变,访问资源需要的凭证信息,从哪个服务器获取数据,需要连接的端口号,指向资源的层级文件路径,查询字符串,片段 id。
客户端,走 HTTP 应用层,tcp 传输层,ip 网络层,数据链路层网络
分层由高到低分别为:应用层、传输层、网络层、数据链路层。发送端从应用层往下走,接收端从数据链路层往上走。
应用层客户端发送HTTP 请求,报文首部,空行,报文主体,报文首部含请求行,请求首部字段,实体首部字段,其他。
SYN (Synchronize Sequence Numbers)同步序列编号
ACK (Acknowledgement)确认字符
过程,用户先在浏览器中输入一个 url,浏览器内部中的核心代码会将这个输入的 url 拆分解析,然后将 domain 传给 dns 服务器,dns 服务会根据 domain 查询相关的 post 对应的 ip 地址,然后将 ip 地址传递给浏览器,浏览器有 ip 地址,就知道浏览器要到哪里去,持有 ip 地址知道这个请求发送到哪里去。就跟随协议,请求的参数都会在协议中携带,发送到网络中去,然后通过局域网,交换机,路由器,主干网络,到达服务端。
服务端是有一个 MVC 的架构的,请求首先会进入 Controller 中,在 Controller 中进行相关的逻辑处理,以及请求的分发,调用 Model 层,负责和数据进行交互,model 层会读取 Redis 和 db 里面的数据。然后通过 view 层给到网络,由服务端到浏览器端,浏览器主要是做 render 的过程,render 的过程就是通过浏览器请求回来的 HTML,css,JavaScript 等渲染的过程,会形成相关的 dom 树,以及对应的 css 树,在页面上进行相应的样式渲染。
拷问,从浏览器到服务器的过程中,那几个点,哪些过程可以进行我们的前端优化呢?
client 浏览器与 server 通过 http 协议通讯,http 协议属于应用层协议,http 属于 tcp 协议,所以 client 与 server 主要通过 socket 进行通讯。
tcp 属于传输层协议,走 https 需要会话层 tls,ssl 等协议。
浏览器,dns 服务器,服务器等,dns 上我们可以进行缓存,来优化前端性能,路由器层面,url 层面进行数据缓存,这样访问的时间就会被缩短了很多。
网络请求的过程,带宽,网络的选择,涉及到缓存,可以使用 cdn,cdn 是请求静态资源用的,请求静态资源,那么 cookie 是没有用的,所以希望在请求静态资源中,把这个 cookie 给去掉,这里注意 cdn 的域名不要和主站的域名一致,防止携带 cookie。
如何减少我们HTTP 请求的大小,每一个HTTP 请求都要走网络环境才能达到我们的服务器,每一次请求都有网络环境的损耗,把多次 HTTP 请求减少到一次,减少网络环境中的损耗。也可以从服务器端出发,先把反映到页面中效果进行渲染,然后直出到网页上。
每一次请求都有网络环境的损耗,我们可以把多次 HTTP 请求合并成一次,从而减少相同的环境损耗。
带宽,一个 HTTP 的请求大小能够较小的话,访问就比较快一些,浏览器端的渲染过程,使用框架,就要从浏览器中进行渲染,框架中的模板是要在浏览器中进行渲染的,这个在框架中进行渲染,不利于首屏,对首屏有很大的损耗,不利于前端的性能。
服务器的渲染,将 HTML 渲染后直出到我们浏览器页面,不是在浏览器中进行渲染了。
前端性能优化点,通过 HTTP 请求的过程,可以了解到,我们可以通过 dns 进行缓存从而减少 dns 查询的时间,网络请求的过程走最近的网络环境,相同的静态资源进行缓存,减少 HTTP 请求的大小,减少 HTTP 请求,服务器端渲染,从业务中进行前端优化点。
重点,深入了解一下 HTTP 的请求过程,就可以知道前端性能优化的核心要点
资源的合并与压缩
减少资源体积,gzip 压缩,js 混淆,css 压缩,图片压缩。
减少 HTTP 请求的数量即为合并,减少 HTTP 请求的大小即为压缩。可以对 HTML 进行压缩,css 进行压缩,js 进行压缩和混乱,文件合并,开启 gzip 等。
进行HTML 压缩
第一使用在线网站压缩,使用 html-minifier 工具进行压缩,后端模板引擎渲染压缩。
进行css 压缩
css sprite 是减少图像请求数量的首选方法,将背景图像合并为单个图像。
CSS Sprites 在国内很多人叫 CSS 精灵,是一种网页图片应用处理方式。它允许你将一个页面涉及到的所有零星图片都包含到一张大图中去,这样一来,当访问该页面时,载入的图片就不会像以前那样一幅一幅地慢慢显示出来了。对于当前网络流行的速度而言,不高于 200KB 的单张图片的所需载入时间基本是差不多的,所以无需顾忌这个问题。
第一进行无效代码的删除,第二是 css 语义合并,使用在线网站压缩,使用 html-minifier 对 HTML 中的 css 进行压缩,使用 clean-css 对 css 进行压缩。
用 CSSbackground-image 和 background-position 属性显示所需的图像段
进行 js 的压缩和混乱
第一删除无效字符,剔除注解,代码语义的缩减和优化,代码的保护,可以使用在线网站进行压缩,html-minifier 对 html 中的 js 进行压缩,使用 uglifyjs2 对 js 进行压缩
(1)将 table 改为 div 布局
(2)缩减精简 div、span、ul、li 等系列标签
(3)删除多余空格
(4)表格类型布局时候适当使用 table 替代 div 布局
(5)网页 GZIP 压缩
文件的合并
文件与文件之间有插入的上行请求,增加了 N-1 个网络延迟,受丢包问题影响更加严重,经过代理服务器时可能会被断开。合并文件存在首屏渲染问题,缓存失败问题,js 文件比较大,请求比较慢,得请求回来后才会首屏 HTML 渲染,js 是由缓存的,文件合并如果其中某个 js 文件有变化,就会导致缓存失败的问题,如果文件不合并,修改其中的某一个 js 文件,只会导致该文件缓存失效,其他的不会受影响。文件合并,存在很严重的缓存失效问题。
那么是否进行文件的合并,建议可以将公共库单独打包成一个文件,业务单独打包成一个文件,不同页面的合并,将不同页面的 js 不同打包,
如何进行文件合并,在线网站进行文件合并,使用 nodejs 实现文件合并
实战资源和与压缩
实战页面开发,网站进行压缩与合并,fis 进行自动化的压缩与合并。
压缩前
压缩后
前端自动化的构造实现压缩与合并
fis3 是一款百度内的构建工具,start->getSource()->所有文件是否编译完成,(单文件的编译,另个走向为打包的过程)。
fis3 的配置文件,fis-conf.js
压缩后,优化前后性能对比,还是要性能优化得好,大的资源效果很明显
加载优化,合并 CSS,JavaScript,合并小图片,缓存一切可以缓存的资源,使用外联样式引用 CSS 和 JavaScript,压缩 HTML,css,JavaScript,启用 GZIP,使用首屏加载,按需加载,滚屏加载,增加加载进度条,减少 cookie,避免重定向,异步加载第三方资源。
css 优化,css 写在头部,JavaScript 写在尾部,避免图片和 Frame 等的空 Src,尽量避免重设置图片大小,图片尽量避免使用 DataURL,尽量避免写在 HTML 标签中写 style 属性,避免 css 的表达式,移除空的 css 规则,正确使用 display 的属性,不滥用 float,不滥用 web 字体,不滥用过多的 Font-size,值为 0 时不需要任何单位,标准化各种浏览器前缀,避免让选择符看起来像正则表达式。
渲染优化,HTML 使用 viewport,减少 dom 节点,尽量使用 css3 动画,合理使用 requestAnimationFrame 动画代替 setTimeout,适当使用 Canvas 动画,Touchmove,Scroll 事件会导致多次渲染,使用 CSS3 transitions,CSS3 3d,transforms,Opacity,Canvas 等来触发 GPU 渲染。
脚本优化,减少重绘和回流,缓存 dom 选择与计算,缓存列表 length,尽量使用事件代理,避免批量绑定事件,尽量使用 id 选择器,使用 touchstart,touchend 代替 click。
图片优化,使用 css3,svg,iconfont 代替图片,使用 srcset,web 优于 jpg,png8 优于 gif,首次加载不大于 1014kb,图片不宽于 640。
注意,在我们修改后端响应时间缩短一半时,整体响应事件只能减少 5-10%,而优化前端性能,缩短一半时,整体响应可以减少 40-45%。
前端优化的意义 HTTP 请求的过程是进行优化的核心 压缩和合并的原理
图片优化的过程
图片加载处理,图片预加载,图片懒加载,首屏加载时进度条的显示。异步请求的优化,使用正常的 json 数据格式进行交互,部分常用数据的缓存。
图像映射将多个图像合并为一个图像,整体大小大致相同,但是减少 HTTP 请求的数量可以加快页面的速度。
png8、png24、png32 区别
png8 为 256 颜色,支持透明,png24 为 2 的 24 次幂,不支持透明,png32 为 2 的 24 次幂,支持透明。
jpg 有损压缩,压缩率高,不支持透明,png 支持透明,浏览器兼容好,webp 压缩程度更好,在 ios webview 有兼容性问题,svg 矢量图,代码内嵌,相对较小。
jpg 使用场景,用在不需要透明图片,png 使用场景,用在需要透明图片的场景,webp 用在安卓,svg 矢量图用在图片样式相对简单的业务。
css 雪碧图,把一些图片整合到一张单独的图片中,用来减少请求数量,问题出在图片大,如果没有加载成功的话,慢,也是有问题的。image inline,把图片的内容内嵌到 HTML 上,与 HTML 存在,作为 base64 的格式,可以减少你的网站的 HTTP 请求数量。使用矢量图 svg,绘制功能,使用 iconfont 解决 icon 问题。
webp 使用在安卓下,它具更好的图像数据压缩算法,和无损和有损的压缩模式,alpha 透明,动画的特性。
HTML 渲染过程:顺序执行(词法分析),并发加载,是否阻塞,依赖关系,引入方式。
css 阻塞,css head 中阻塞页面的渲染,css 阻塞 js 的执行,css 不阻塞外部脚本的加载。
js 阻塞,引入 js 阻塞页面的渲染,js 不阻塞资源的加载,js 顺序执行,阻塞后续 js 逻辑的执行。
图片压缩与拼接
PNG、PNG-8、PNG-24 以及 JPEG 格式图片区别
PNG 格式适合对透明度有要求的情形,PNG-8 处理不了复杂色域下的渐变,PNG-24 可以几乎不失真地保留渐变
图片压缩方法
使用 Photoshop 自带图片压缩,文件—存储为 Web 所用格式,一般情况下,JPEG 选择输出质量为 70~80%可以保证视觉上几乎没有差异。
页面体积
优化前后文件体积压缩率 = 优化后的体积÷优化前的体积
懒加载原理
什么是懒加载的定义是对于图片而言,图片资源,对于商城项目图片是很多的,页面很长的业务场景适用,减少无效资源的加载,并发加载的资源过多会阻塞 js 的加载。
当图片进入到我们可视区域,去请求加载资源
懒加载的效果延迟加载
预加载原理
图片等静态资源使用前提前请求,资源在使用时从缓存中加载,提高用户体验。
什么是重绘与回流的机制?
频繁重绘与回流会导致 ui 频繁渲染,导致 JavaScript 变慢。回流,当 render tree 中的一部分因为元素的规模尺寸,布局等改变需要重新构建,会触发回流,重绘,当 render tree 中的一些元素需要修改属性,这些属性不影响元素的外观,风格,布局,就叫做重绘,如修改颜色等。
所以回流一定会引起重绘,但是重绘不一定会引起回流。
掌握一些 css 属性
将频繁重绘回流的元素单独出来,作为一个独立的图层,那么这个元素的重绘回流就只能影响这个图层中。
把一个元素独立成独立的图层,用 css 属性
避免使用触发重绘,回流的 css 属性,重绘和回流很频繁可以独立出来。
浏览器存储
了解什么是 localstorage,cookie,sessionstorage,indexdb
了解 pwa 和 service worker 的应用
多种浏览器存储方式共存
什么是 cookie
用 cookie 给服务端传递相关信息,让服务端来分别当前请求的是哪个客户端,cookie 是 1993 年有的,它的目的就是为了区分 HTTP 的请求情况,本来 HTTP 请求就是无状态的,就是请求之后的连接就关闭了,cookie 就是去维护客户端的状态。
用于浏览器端和服务端的交互,客户端自身数据的存储。
cookie 有限制,作为浏览器存储大小有 4kb 左右,需要设置过期时间。
cookie 的生成方式,http response header 的 set-cookie,通过 document.cookie 可以读写 cookie,cookie 中的相关域名下面-cdn 的流量损耗,httponly。
LocalStorage
专门用于浏览器存储,大小 5M 左右,接口封装好,本地缓存的方案,可提高首屏的加载速度。
SessionStorage
会话级别的浏览器存储,大小 5M 左右,在客户端使用,不和服务端进行通信,接口封装较好。
pwa 是什么
它是一种 web app 新模型,并不是指某一种前沿的技术,是一种渐进式的 web app,是通过一系列新的 web 特性。pwa 在没有网络的环境中也能提供基本的页面访问,web app 没有网络的话接收不到基本页面的展示,但是 pwa 不会出现未连接到网络就导致显示不了页面。它很快速,对网页渲染以及网络数据访问很快速,融入特性,可以被添加到手机桌面等。
service worker 是什么
它是一个脚本,浏览器独立于当前网页,将其在后台运行,实现一些不依赖的页面。具有拦截和处理网络请求的特性。
缓存,DNS 缓存,CDN 部署与缓存,http 缓存
了解 cache-control,last-modified,etag。httpheader 的属性,Cache-control 属性,max-age,s-maxage,private,public,no-cache,no-store。
浏览器在 DNS 解析中会消耗一定的时间,对一些访问量高的来说,需要做好 DNS 的缓存工作,CDN 缓存,CDN 作为静态资源文件的分发,做好静态资源的缓存工作,就能加快网站的加载速度,
移动到优化,使用 cache,减少重定向,首屏优化,保证首屏加载数据小于 14kb,不滥用 web 字体。
服务端性能优化
服务器是 node.js,所以也能进行优化。
谷歌 PageSpeed 团队的测试表明,30~50KB(压缩后)是每个 JavaScript 文件大小的合适范围:既达到了能够减少小文件带来的网络延迟,还能确保递增及分层式的执行。–web 性能权威指南
减少 HTTP 请求,合并 js 文件,合并 css 文件,使用 css sprite,使用 base64 表示简单的图片。
移动端优化,长列表滚动优化,函数防抖和函数节流,使用 touchstart,touchend 代替 click,html 的 viewport 设置,开启 gpu 渲染加速。