目录
3. 首次有效渲染时间要低于1.25秒,速度指数要低于1000
5. 渐进增强(progressive enhancement)
15.1 如何使用webpack将静态素材快速托管到ImageX,并开启http/2
18. 通过tree-shaking和code-splitting减少净负载
微优化是保持性能最好的办法,但是又不能有太过明确的优化目标,因为过于明确的目标会影响在项目中做的每一个决定。以下是一些不同的模型,请按照自己舒服的顺序阅读
根据一个心理学研究,你的网站最少在速度上比别人快20%,才能让用户感觉到你的网站比别人的更快。这个速度说的不是整个页面的加载时间,而是开始加载渲染的时间,首次有效渲染时间(例如页面需要加载主要内容的时间),或者交互时间(指的是页面或者应用中主要的页面加载完成,并主备好与用户进行交互的时间)。
在Moto G(一个中端三星设备)和Nexus 4(比较主流的设备)上衡量开始渲染时间(用WebPagetest)以及首页有效渲染时间(用Lighthouse),最好是在一个开放的实验室中,使用规范的3G,4G和Wi-Fi链接。
你可以通过你的分析报告看看你的用户处在哪个阶段,选取其中前90%的用户体验来做测试。接着收集数据,建一个表格,筛去20%的数据并预设一个目标(如:性能预算)。现在你可以将上述两个值进行对比检测。如果你始终维持着你的目标并且通过一点一点改变脚本去加快交互时间,那么上述方法就是合理可行的。
如果前端工程师们都在积极的参与项目概念,UX以及视觉设计的决定,这将会给整个项目带来巨大收益。地图设计的决定违背了性能理念,所以他在这份清单内的顺序有待考虑。
RAIL性能模型会为你提供一个优秀的目标,既尽最大的努力在用户初始操作后的100毫秒内提供反馈。为了达到这个目标,页面需要放弃权限,并将权限在50毫秒内交回给主线程。对于像动画一样的高压点,最好的方法就是什么都不做,因为你永远无法达到最小绝对值。
同理,动画的每一帧都需要在16毫秒内完成,这样才能保证每秒60帧(一秒/60=16.6毫秒),如果可以的话最好能在10毫秒内完成。因为浏览器需要一定的时间去在屏幕上渲染新的帧,而且你的代码需要在16.6毫秒内完成执行。要注意,上述目标应用于衡量项目的运行性能,而非加载性能。
纵使这个目标实现起来非常困难,你的最终目标也应该是让开始渲染时间低于1秒且速度指数低于1000(在网速快的地方)。对于首次有效渲染时间,上限最好是1250毫秒。对于移动端,3G下移动设备首次渲染时间低于3秒都是可以接受的。稍微高一点也没关系,但千万别高太多。
不要过多的关注当下最流行的工具,坚持选择适合自己开发环境的工具,例如Grunt、Gulp、Webpack、PostCSS,或者组合起来的工具。只要这个工具运行的速度够快,而且没有给你的维护带来太大问题,这就够了。
在构建前端结构的时候,应始终将渐进增强作为你的指导原则。首先设计并且构建核心体验,随后再完善那些为高性能浏览器设计的高级特性的相关体验,创建弹性体验。如果你的网页可以在使用低速网络、老旧显示器的很慢的电脑上运行飞快,那么在光纤高配电脑上它只会运行的更快。
根据你整体组织结构的优先顺序和策略,你可以考虑使用Google的AMP或Facebook的Instant Articles。要知道没有这些你也可以达到不错的性能,但是AMP可以提供一个性能不错的免费的内容分发网络框架(CDN),Instant Articles可以在Facebook上促进你的性能。你也可以建立progressive web AMP。
根据你的动态数据量,可以将一部分内容外包给静态网站生成工具,将它置于CDN上,从中生成一个静态版本,从而避免那些数据库的请求。也可以选择基于CDN的静态主机平台,通过交互组件丰富你的页面(JAMStack)。注意CDN是否可以很好的处理(或分流)动态内容。没必要单纯的将你的CDN限制为静态。反复检查CDN是否执行了内容的压缩和转化,检查智能HTTP/2传输和缓存服务器(ESI),注意哪些静态或动态的部分处在CDN的边缘(最接近用户的服务器)。
首先应该弄清楚你想解决的问题是什么。检查一遍你所有的文件(JavaScript,图片,字体,第三方script文件以及页面中重要的模块,例如轮播,复杂信息图标和多媒体内容),并将他们分类。
列一个表格。明确浏览器上应该有的基础核心内容,哪些部分属于为高性能浏览器设计的升级体验,哪些是附加内容(那些不必要或者可以被延时加载的部分,例如字体,不必要的样式,轮播组件,播放器,社交网站入口,很大的图片)。
使用符合标准的技术向过时的浏览器提供核心体验,向老式浏览器提供增强体验, 同时对所加载的内容要有严格的把控。即首要加载核心体验部分,将增强部分放在
DomContentLoaded
,把额外内容发在load
事件中。以前我们可以通过浏览器的版本推断出设备的性能,但现在我们已经无法推测了。因为现在市场上很多廉价的安卓手机都不考虑内存限制和CPU性能,直接使用高版本的Chrome浏览器。一定要注意,在我们没有其他选择的时候,我们选择的技术同时可能成为我们的限制。
在一些应用中,可以在渲染页面前先初始化应用。最好先显示框架,而不是一个进度条或指示器。使用可以加速初始渲染时间的模块或技术(例如tree-shaking和code-splitting),因为大部分性能问题来自于应用引导程序的初始分析时间。还可以在服务器上提前编译,从而减轻部分客户端的渲染过程,从而快速输出结果。最后,考虑使用Optimize.js来加快初始加载速度,它的原理是包装优先级高的调用函数(虽然现在已经没什么必要了)。
到底采用客户端渲染还是服务器端渲染?不论哪种做法,我们的目标都是建立渐进启动:使用服务器端渲染可以得到很短的首次有效渲染时间,这个渲染过程也包括小部分的JavaScript文件,目的是使交互时间尽可能的接近首次有效渲染时间。接下来,尽可能的增加一些应用的非必要功能。不幸的是,正如Paul Lewis所说,框架基本上对开发者是没有优先级的概念的,因此渐进启动在很多库和框架上是很难实施的。如果你有时间的话,还是考虑使用策略去优化你的性能吧。
仔细检查一下例如expires,cache-control,max-age以及其他HTTP缓存头是否被正确的使用。一般来说,资源不论在短时间(如果它会被频繁改动)还是不确定的时间内(如果它是静态的)都是可缓存的——你大可在需要的时候在URL中成改版本。如果可能,使用为指纹静态资源设计的Cache-control:immutable,从而避免二次验证(2016年12月,只有FireFox在https://处理中支持)。你可以使用,Heroku的primer on HTTP caching headers,Jake Archibald的 ”Caching Best Practices”,还有IIya Grigorik的HTTP caching primer作为指导。
当用户请求页面时,浏览器会抓取HTML同时生成DOM,然后抓取CSS并建立CSS对象模型,最后通过匹配DOM和CSS对象生成渲染树。在需要处理的JavaScript文件被解决之前,浏览器不会开始对页面进行渲染。作为开发者,我们要明确的告诉浏览器不要等待,直接开始渲染。具体方法是使用HTML中的
defer
和async
两个属性。事实上,defer
更好一些(因为对于IE9及以下用户对于IE9及以下用户,很有可能会中断脚本)。同时,减少第三方库和脚本的使用,尤其是社交网站的分享按键和<iframe>
嵌入(比如地图)。你可以使用静态的社交网站分享按键(例如SSBG的)和指向交互地图的静态链接去代替他们。
尽可能的使用带有
srcset
,sizes
还有<picture>
元素的响应式图片。你也可以利用<picture>
元素的AVIF、WEBP格式,用JPEG格式作为替补(参见Andreas Bovens的code snippet)或是使用内容协商(使用接受头)。本身可以使用自己的PS或者skecth尝试导出,若不能导出,可以尝试 火山引擎的ImageX图像处理服务(不知道怎么使用可以自行百度搜索 "火山引擎 ImageX")可以支持多种格式输出,比如AVIF、webp格式;
我曾经写过这篇文档可以对照一下:高效率图像压缩处理服务, 参考截图:
你也可以使用客户端提示,现在浏览器也可以做到。在用来生成响应图片的源文件过少时,使用响应图片断点生成器。
当你在编写登录界面的时候,发现页面上的图片加载的特别快,这时你需要确认一下图片进一步优化的思路只要有三点:
- 降低图片的分辨率,如果浏览器中展示区域100*100,此时展示 400*400 就属于资源浪费,这也是显著提高图片响应速度最直接的方法;
- 降低图片压缩的质量,图片压缩质量,使用有损压缩,比如图片压缩质量90 和75对人眼可见的范围内都可以接受,常见支持有损压缩的图片格式比如,jpeg、wepb、heic、avif等图片格式支持图片有损压缩;
- 改变图像压缩的压缩方式,改变图片的压缩算法也能更高效的提高图片优化图片提高速度,比如 常见图像压缩率(图像画质等同前提下): HEIF (heic) > AVIF (avif、avis) >webP(awebp) > jpeg > png 等;
正常情况下PNG是原图格式,体积特别大,巧的是业界对PNG 有
pngquant
使用Median Cut量化算法的修改版本和其他技术来缓解Median Cut的不足,可以最大效率保留信息的前提下降低png 的体积大小;如果我们把如上的一些优化处理起来,我使用的过程中发现,火山引擎的imagex 已经完美的支持了上面三者的使用方法:下面我举个例子做一下说明:http://imagex.75live.com/tos-cn-i-n9b2vwdhz3/public/attachments/2021/03/11/GyVrojIWFkQOKSAzYnUmlQxvaESnPaZYxgpu9v1Z.png~tplv-n9b2vwdhz3-12:300:200.webp 这个是 png的原图处理好的结果,在这个url中imagex 给出了一种url语义,"~tplv--模板名称:[模板参数].图像格式" 通过改变300:300 能改改变压缩率,通过参数能够调整压缩质量,通过改变webp-->avif 可以转换成不同的压缩方法;
更巧妙的是在这,就算指定输出png后仍然还可以设置质量参数
如果你还觉得不够,那你可以通过多重背景图片技术来提高图片的感知性能。
这里发现一个第三方写的但被官方推荐的开源插件https://github.com/Cmaxd/veimagex-webpack-loader ,通过配置webpack-loader 插件的方式可以将图片上传到ImageX,然后将图片使用不同的图片模板访问就可以满足需求,同一个图片可以使用多个地址,例如avif、webp、jpeg 使用 <picture> 标签进行降级 或者判断浏览器支持降级;
你用来修饰网页字体的服务很有可能毫无用处,包括字形和额外的特性。如果你在使用开源的字体,尝试用字体库中某一个小的子集或是自己归类一个小的子集从而压缩文件大小(例如通过一些特殊的注音符号引用Latin)。WOFF2 support是个非常不错的选择,如果浏览器不支持,那你可以将WOFF和OTF作为备用。你也可以从Zach Leatherman的“Comprehensive Guide to Font-Loading Strategies”一文中选择一个合适的策略,然后使用服务器来缓存字体。如果想要快速入门,Pixel Ambacht的教程与案例会让你的字体变得尽然有序。如果你用的是第三方服务器主机,没办法自己在服务器上对字体进行操作,一定看看Web Font Loader。
为了确保浏览器尽可能快的渲染你的页面,先收集页面首次可见部分的CSS文件(也叫决定性CSS或上半版CSS)进行渲染,然后将它加入页面的<head>部分,从而避免重复操作。因为慢启动阶段对交换包大小的限制,你关键CSS文件的大小也被限制在14KB左右。如果高于这个值,浏览器需要重复一些步骤来获取更多的样式。关键CSS是允许你这样做的。可能对每个模板都需要这个操作。如果可能,考虑一下用Fiament Group用的条件内敛方法。
通过HTTP/2,关键CSS可以单独存为CSS文件,通过服务器传输,而且可以避免HTML膨胀。服务器传输缺乏连续支持,并且存在一些超高速缓存的问题(Hooman Beheshti演示的前144页)。事实上,这样会导致网络缓冲区膨胀。因为TCP的慢启动,服务器传输在稳定的连接下会更有效率。所以你可能需要建立带有缓存的HTTP/2服务器传输机制。但请记住,新的
cache-digest
规则会否定手动建立的需要缓存的服务器的请求。
Tree-shaking是通过保留那些在项目过程中真正需要的代码从而清理你的构建过程的一种方式。你可以用Webpack 2来提出那些没用的住配置文件,用UnCSS或Helium从CSS中取出不需要的样式。同理,也可以考虑学习一下如何编写高效的CSS选择器,以及如何避免膨胀和高费的样式。
Code-splitting是另一个Webpack特性,它可以根据按需加载的块将你的代码分开。只要你在代码中定义了分离点,Webpack便会处理好相关的输出文件。它基本上能保证你初始下载的内容很小,而且在需求被添加时按需请求代码。
Rollup所展示的结果要比Browserify配置文件所显示的好得多。所以当我们想使用类似工具的时候,或许应该看看Rollupify,它将ECMAScript2015模块变成了一个更大的CommonJS模块——因为小模块没准有出乎意料的高性能成本,这源自于你对打包工具模块系统的选择。
使用类似CSS containment的方法对高消耗组建进行隔离,从而限制浏览器样式的范围,可以作用在为无canvas的浏览工作的布局和装饰工作中,或是用在第三方工具上。要确保页面滚动和出现动画效果时没有延迟,别忘了之前提到过的每秒60帧的原则。如果没办法做到,那就尽可能保证每秒帧数的大致范围在15到60帧。使用CSS中的will-change通知浏览器哪些元素和属性发生了变化。也记得要衡量渲染执行中的性能(可以用DevTools)。可以参照Udacity上Paul Lewis的免费课程——浏览器渲染优化,作为入门。还有一篇Sergey Chikuyonok的文章讲了如何正确的用GPU动画。
使用页面框架,对高消耗组建延迟加载(字体,JS文件,循环播放,视频和内嵌框架)。使用资源提示来节省在
dns-prefetch
(指的是在后台执行DNS检索),preconnect
(指要求浏览器在后台进行握手链接(DNS,TCP,TLS)),prerender
(指要求浏览器在后台对特定页面进行渲染),preload
(指的是提前取出暂不执行的源文件)。根据你浏览器的支持情况,尽量使用preconnect
来代替dns-prefetch
,而且在使用prefetch
和prerender
要特别小心——后者(prerender
)只有在你非常确信用户下一步操作的情况下再去使用(比如购买流程中)。
Google开始向着更安全网页的方向努力,并且将所有Chrome上的HTTP网页定义为“不安全”时,你或许应该考虑是继续使用HTTP/1.1,还是将目光转向HTTP/2环境。虽然初期投入比较大,但是使用HTTP/是大趋势,而且在熟练掌握之后,你可以使用service worker和服务器推送技术让行性能再提升一大截。
现在,Google计划把所有HTTP页面标记为不安全,并且将HTTP安全指示器设置为与Chrome用来拦截HTTPS的红色三角相同的图标。使用HTTP/2的环境的缺点在于你要转移到HTTPS上,并且根据你HTTP/1.1用户的数量(主要指使用过时操作系统和过时浏览器的用户),你需要适应不同的建构过程,才能发送不同的建构。注意:不论是迁移还是新的构建过程都可能非常棘手而且耗时很多。
重申,使用HTTP/2协议之前,你需要彻底排查目前为止你所使用协议的情况。你需要在打包组建和同时加载很多小组间之间找到平衡。
一方面,你可能想要避免将很多资源链式链接,与其将你全部的界面分割成许多小模块,不如将他们压缩使之成为建构过程的一部分,之后给它们赋予可检索的信息并加载它们。这样的话,对一文件将不再需要重新下载整个样式清单或JavaScript文件。
另一方面,封装是很有必要的,因为一次向浏览器发送太多JavaScript文件会出问题。首先,压缩会造成损坏。得益于dictionary reuse,压缩大文件不会对文件造成损害,压缩小文件则不然。确实有方法可以解决这个问题,但这不是本文讨论的范畴。其次,浏览器还没有优化到可以对类似工作流进行优化。例如,Chrome会引发进程间通信(IPCs),这些通信的数量与资源的数量成正比,而这成百上千个资源将会消耗大量的浏览器的执行时间。
Chrome的Jake Archibald建议,为了用HTTP/2达到最好的效果,考虑一下逐步加载CSS文件
当然你可以考虑逐步加载CSS文件。很显然,你这样做对HTTP/1.1的用户非常不利,所以你可能需要根据不同的浏览器建立多个版本来应对你的调度过程,这样就会使过程略微复杂。你也可以避免HTTP/2连接的合并,同时受益于HTTP/2来使用域名碎片,但是实现起来有些困难。
我们到底应该做什么呢?如果你粗略的用过HTTP/2,似乎成功的发送过10个左右的包(在老是浏览器上运行的也不错)。那你就能着手开始试验并且为你的网站找到平衡点。
所有的浏览器都支持HTTP/2并且使用TLS,这是有你可能想要避免安全警告,并删除页面上没用的元素。好好检查你的安全头部是否设置正确,排除已知的缺陷并检查证书。
如果还没有迁移到HTTP, 你那可以先看看HTTPS准则(The HTTPS-Only Standard)。确保所有外部插件和监视脚本都能被HTTPS正确加载,确保没有跨站脚本出现,HTTP脚本传输的安全头和内容安全头也都设置正确。
这份清单综合性很强,几乎介绍了所有的可用的优化方式。那么,如果你只有一个小时进行优化,你应该干什么呢?让我们从中总结10个最有用的来。别忘了在你开始优化前和结束优化后,记录你的结果,包括开始渲染时间以及在3G,有限连接下的速度。
但没关系,本文只是一个普通大纲(希望能做到综合性强),你应该根据自己的工作环境列一份适合自己的清单。最重要的,在开始优化之前,先对项目中存在的问题有一个明确的了解。
转自:csdn论坛 ,
蓝蓝设计( www.lanlanwork.com )是一家专注而深入的界面设计公司,为期望卓越的国内外企业提供卓越的UI界面设计、BS界面设计 、 cs界面设计 、 ipad界面设计 、 包装设计 、 图标定制 、 用户体验 、交互设计、 网站建设 、平面设计服务
如果您想订阅本博客内容,每天自动发到您的邮箱中, 请点这里
减少页面加载时间的方法:
1.压缩html css js等文件
2.减少DNS解析
3.减少DOM元素,对于相关操作可以缓存节点
4.改变页面元素样式时尽量操作className,而不是频繁使用xxx.style.(其实还有很多这种DOM修改操作的细节比如opacity替代visibility ,多个DOM统一操作(虽然V8会有缓存优化) ,先将DOM离线,即display:none;修改后显示 ,不要把DOM放在已给循环中作为循环变量 ,不要使用table )
5.避免不必要的重定向
6.合并js css及图片,减少请求数量
7.使用CDN
8.合理利用缓存
9…
关于CDN?
https://zhuanlan.zhihu.com/p/39028766
CDN中文名“内容分发网路”,作用是减少传播时延,找最近的节点。CDN本质就一个是缓存,只是这个缓存离你特别近,不管是作为用户还是开发人员都能从中享受一点福利。
CDN的优点
1.访问加速
2.减轻服务器负载
3.抗住攻击
CDN的缺点
1.只能对静态资源加速
2.内容更新时需要分发到其他节点
3.代价高昂
与传统网站访问方式的不同
传统的网站会直接解析域名获得IP地址然后发送请求
使用了CDN的网站则增加了缓存层,解析域名→获取对应CNAME域名→对获取的域名进行解析得到缓存服务器的IP地址,将用户的访问请求引导到最优的缓存节点而不是源站。
总结:通过权威DNS服务器来实现最优节点的选择,通过缓存来减少源站的压力。主要应用于静态网页、大文件的下载等等。
应用与踩坑
缓存设置
max-age在Cache-Control中经常用于缓存的控制,可是max-age设置的缓存会应用于一个请求经过的每一级,如果我们希望CDN不缓存那么久,要怎么办呢?那就是s-maxage,它用于设置代理服务器的缓存时间,会覆盖max-age的设置,这样我们可以把max-age用于本地缓存,把s-maxage用于CDN缓存时间,避免脏数据的产生。
缓存命中率
对于一个缓存而言,还有一点非常重要,就是你的缓存到底有没有用,衡量这个东西的就是缓存命中率。如果只是静态资源,在刷新缓存之后,可能导致命中率下降,因此CDN的资源不适合经常刷新,换句话说,如果一个请求结果会经常进行变更,那么CDN基本就没有什么存在的意义了。
判断是否命中缓存
还要考虑的一件事是:这个资源是否命中了CDN,是否是因为CDN导致的问题。
在各大厂商的CDN返回的数据中都会有一个X-Cache,上面内容是Hit或者Miss,还会加上诸如Memory或者Disk的缩写表示内存还是磁盘,如果出现Upstream或者Miss则表示没有命中。
资源预热
缓存设计中,预热是很重要的环节,在最初刚开始启动CDN的时候,CDN上并没有缓存数据,此刻大量的请求全部打向源站,肯定会把源站打挂,预热就是实现缓存热门数据,这样在业务上线时,CDN上已经有所需的数据了
蓝蓝设计( www.lanlanwork.com )是一家专注而深入的界面设计公司,为期望卓越的国内外企业提供卓越的UI界面设计、BS界面设计 、 cs界面设计 、 ipad界面设计 、 包装设计 、 图标定制 、 用户体验 、交互设计、网站建设 、平面设计服务。
摘要: 前端性能优化是一个很宽泛的概念,本书前面的部分也多多少少提到一些前端优化方法,这也是我们一直在关注的一件重要事情。配合各种方式、手段、辅助系统,前端优化的最终目的都是提升用户体验,改善页面性能,我们常常竭尽全力进行前端页面优化,但却忽略了这样做的效果和意义。先不急于探究前端优化具体可以怎样去做,先看看什么是前端性能,应该怎样去了解和评价前端页面的性能。
相对于桌面端浏览器,移动端Web浏览器上有一些较为明显的特点:设备屏幕较小、新特性兼容性较好、支持一些较新的HTML5和CSS3特性、需要与Native应用交互等。但移动端浏览器可用的CPU计算资源和网络资源极为有限,因此要做好移动端Web上的优化往往需要做更多的事情。
首先,在移动端Web的前端页面渲染中,桌面浏览器端上的优化规则同样适用,此外针对移动端也要做一些的优化来达到更好的效果。需要注意的是,并不是移动端的优化原则在桌面浏览器端就不适用,而是由于兼容性和差异性的原因,一些优化原则在移动端更具代表性。
1.首屏数据请求提前,避免JavaScript文件加载后才请求数据
为了进一步提升页面加载速度,可以考虑将页面的数据请求尽可能提前,避免在JavaScript加载完成后才去请求数据。通常数据请求是页面内容渲染中关键路径最长的部分,而且不能并行,所以如果能将数据请求提前,可以极大程度上缩短页面内容的渲染完成时间。
2.首屏加载和按需加载,非首屏内容滚屏加载,保证首屏内容最小化
由于移动端网络速度相对较慢,网络资源有限,因此为了尽快完成页面内容的加载,需要保证首屏加载资源最小化,非首屏内容使用滚动的方式异步加载。一般推荐移动端页面首屏数据展示延时最长不超过3秒。目前中国联通3G的网络速度为338KB/s(2.71Mb/s),所以推荐首屏所有资源大小不超过1014KB,即大约不超过1MB。
3.模块化资源并行下载
在移动端资源加载中,尽量保证JavaScript资源并行加载,主要指的是模块化JavaScript资源的异步加载,例如AMD的异步模块,使用并行的加载方式能够缩短多个文件资源的加载时间。
4.inline首屏必备的CSS和JavaScript
通常为了在HTML加载完成时能使浏览器中有基本的样式,需要将页面渲染时必备的CSS和JavaScript通过<script>或<style>内联到页面中,避免页面HTML载入完成到页面内容展示这段过程中页面出现空白。
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>样例</title>
<meta name="viewport" content="width=device-width,minimum-scale=1.0, maximum-scale=1.0,user-scalable=no">
<style>
/* 必备的首屏CSS */
html, body{
margin: 0;
padding: 0;
background-color: #ccc;
}
</style>
</head>
<body>
</body>
5.meta dns prefetch设置DNS预解析
设置文件资源的DNS预解析,让浏览器提前解析获取静态资源的主机IP,避免等到请求时才发起DNS解析请求。通常在移动端HTML中可以采用如下方式完成。
<!-- cdn域名预解析 -->
<meta http-equiv="x-dns-prefetch-control" content="on">
<link rel="dns-prefetch" href="//cdn.domain.com">
6.资源预加载
对于移动端首屏加载后可能会被使用的资源,需要在首屏完成加载后尽快进行加载,保证在用户需要浏览时已经加载完成,这时候如果再去异步请求就显得很慢。
7.合理利用MTU策略
通常情况下,我们认为TCP网络传输的最大传输单元(Maximum Transmission Unit,MTU)为1500B,即网络一个RTT(Round-Trip Time,网络请求往返时间)时间内可以传输的数据量最大为1500字节。因此,在前后端分离的开发模式中,尽量保证页面的HTML内容在1KB以内,这样整个HTML的内容请求就可以在一个RTT时间内请求完成,最大限度地提高HTML载入速度。
1.合理利用浏览器缓存
除了上面说到的使用Cache-Control、Expires、Etag和Last-Modified来设置HTTP缓存外,在移动端还可以使用localStorage等来保存AJAX返回的数据,或者使用localStorage保存CSS或JavaScript静态资源内容,实现移动端的离线应用,尽可能减少网络请求,保证静态资源内容的快速加载。
2.静态资源离线方案
对于移动端或Hybrid应用,可以设置离线文件或离线包机制让静态资源请求从本地读取,加快资源载入速度,并实现离线更新。关于这块内容,我们会在后面的章节中重点讲解。
3.尝试使用AMP HTML
AMP HTML可以作为优化前端页面性能的一个解决方案,使用AMP Component中的元素来代替原始的页面元素进行直接渲染。
<!-- 不推荐 -->
<video width="400" height="300" src="http://www.domain.com/videos/myvideo.mp4" poster="path/poster.jpg">
<div fallback>
<p>Your browser doesn’t support HTML5 video</p>
</div>
<source type="video/mp4" src="foo.mp4">
<source type="video/webm" src="foo.webm">
</video>
<!-- 推荐 -->
<amp-video width="400" height="300" src="http://www.domain.com/videos/myvideo.mp4" poster= "path/poster.jpg">
<div fallback>
<p>Your browser doesn’t support HTML5 video</p>
</div>
<source type="video/mp4" src="foo.mp4">
<source type="video/webm" src="foo.webm">
</amp-video>
1.图片压缩处理
在移动端,通常要保证页面中一切用到的图片都是经过压缩优化处理的,而不是以原图的形式直接使用的,因为那样很消耗流量,而且加载时间更长。
2.使用较小的图片,合理使用base64内嵌图片
在页面使用的背景图片不多且较小的情况下,可以将图片转化成base64编码嵌入到HTML页面或CSS文件中,这样可以减少页面的HTTP请求数。需要注意的是,要保证图片较小,一般图片大小超过2KB就不推荐使用base64嵌入显示了。
.class-name {
background-image: url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAoAAAALCAMAAABxsOwqAAAAYFBMVEWnxwusyQukxQudwQyZvgyhxAyfwgyxzAsUHQGOuA0aJAERGAFIXwSTugyEqgtqhghQZgUwQQIpOQKbuguVtQuKrAuCowp2kQlheghTbQZHWQU7SwVAVgQ6TgQlLwMeKwFOemyQAAAAVElEQVQI1y3JVRaAIAAF0UconXbvf5ei8HfPDIQQhBAAFE10iKig3SLRNN4SP/p+N08VC0YnfIlNWtqIkhg/TPYbCvhqdHAWRXPZSp3g3CWZvVLXC6OJA3ukv0AaAAAAAElFTkSuQmCC');
}
3.使用更高压缩比格式的图片
使用具有较高压缩比格式的图片,如webp等。在同等图片画质的情况下,高压缩比格式的图片体积更小,能够更快完成文件传输,节省网络流量。
<img src="//cdn.domain.com/path/photo.webp" alt="webp格式图片">
4.图片懒加载
为了保证页面内容的最小化,加速页面的渲染,尽可能节省移动端网络流量,页面中的图片资源推荐使用懒加载实现,在页面滚动时动态载入图片。
<img data-src="//cdn.domain.com/path/photo.jpg" alt="懒加载图片">
5.使用Media Query或srcset根据不同屏幕加载不同大小图片
在介绍响应式的章节中我们了解到,针对不同的移动端屏幕尺寸和分辨率,输出不同大小的图片或背景图能保证在用户体验不降低的前提下节省网络流量,加快部分机型的图片加载速度,这在移动端非常值得推荐。
6.使用iconfont代替图片图标
在页面中尽可能使用iconfont来代替图片图标,这样做的好处有以下几个:使用iconfont体积较小,而且是矢量图,因此缩放时不会失真;可以方便地修改图片大小尺寸和呈现颜色。但是需要注意的是,iconfont引用不同webfont格式时的兼容性写法,根据经验推荐尽量按照以下顺序书写,否则不容易兼容到所有的浏览器上。
@font-face {
font-family: iconfont;
src: url("./iconfont.eot");
src: url("./iconfont.eot?#iefix") format("eot"),
url("./iconfont.woff") format("woff"),
url("./iconfont.ttf") format("truetype");
}
7.定义图片大小限制
加载的单张图片一般建议不超过30KB,避免大图片加载时间长而阻塞页面其他资源的下载,因此推荐在10KB以内。如果用户上传的图片过大,建议设置告警系统,帮助我们观察了解整个网站的图片流量情况,做出进一步的改善。
1.尽量使用id选择器
选择页面DOM元素时尽量使用id选择器,因为id选择器速度最快。
2.合理缓存DOM对象
对于需要重复使用的DOM对象,要优先设置缓存变量,避免每次使用时都要从整个DOM树中重新查找。
// 不推荐
$('#mod .active').remove('active');
$('#mod .not-active').addClass('active');
// 推荐
let $mod = $('#mod');
$mod.find('.active').remove('active');
$mod.find('.not-active').addClass('active');
3.页面元素尽量使用事件代理,避免直接事件绑定
使用事件代理可以避免对每个元素都进行绑定,并且可以避免出现内存泄露及需要动态添加元素的事件绑定问题,所以尽量不要直接使用事件绑定。
// 不推荐
$('.btn').on('click', function(e){
console.log(this);
});
// 推荐
$('body').on('click', '.btn', function(e){
console.log(this);
});
4.使用touchstart代替click
由于移动端屏幕的设计,touchstart事件和click事件触发时间之间存在300毫秒的延时,所以在页面中没有实现touchmove滚动处理的情况下,可以使用touchstart事件来代替元素的click事件,加快页面点击的响应速度,提高用户体验。但同时我们也要注意页面重叠元素touch动作的点击穿透问题。
// 不推荐
$('body').on('click', '.btn', function(e){
console.log(this);
});
// 推荐
$('body').on('touchstart', '.btn', function(e){
console.log(this);
});
5.避免touchmove、scroll连续事件处理
需要对touchmove、scroll这类可能连续触发回调的事件设置事件节流,例如设置每隔16ms(60帧的帧间隔为16.7ms,因此可以合理地设置为16ms)才进行一次事件处理,避免频繁的事件调用导致移动端页面卡顿。
// 不推荐
$('.scroller').on('touchmove', '.btn', function(e){
console.log(this);
});
// 推荐
$('.scroller').on('touchmove', '.btn', function(e){
let self = this;
setTimeout(function(){
console.log(self);
}, 16);
});
6.避免使用eval、with,使用join代替连接符+,推荐使用ECMAScript 6的字符串模板
这些都是一些基础的安全脚本编写问题,尽可能使用较率的特性来完成这些操作,避免不规范或不安全的写法。
7.尽量使用ECMAScript 6+的特性来编程
ECMAScript 6+一定程度上更加安全,而且部分特性执行速度更快,也是未来规范的需要,所以推荐使用ECMAScript 6+的新特性来完成后面的开发。
1.使用Viewport固定屏幕渲染,可以加速页面渲染内容
一般认为,在移动端设置Viewport可以加速页面的渲染,同时可以避免缩放导致页面重排重绘。在移动端固定Viewport设置的方法如下。
<!-- 设置viewport不缩放 -->
<meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=no">
2.避免各种形式重排重绘
页面的重排重绘很耗性能,所以一定要尽可能减少页面的重排重绘,例如页面图片大小变化、元素位置变化等这些情况都会导致重排重绘。
3.使用CSS3动画,开启GPU加速
使用CSS3动画时可以设置transform: translateZ(0)来开启移动设备浏览器的GPU图形处理加速,让动画过程更加流畅。
-webkit-transform: translateZ(0);
-ms-transform: translateZ(0);
-o-transform: translateZ(0);
transform: translateZ(0);
4.合理使用Canvas和requestAnimationFrame
选择Canvas或requestAnimationFrame等更的动画实现方式,尽量避免使用setTimeout、setInterval等方式来直接处理连续动画。
5.SVG代替图片
部分情况下可以考虑使用SVG代替图片实现动画,因为使用SVG格式内容更小,而且SVG DOM结构方便调整。
6.不滥用float
在DOM渲染树生成后的布局渲染阶段,使用float的元素布局计算比较耗性能,所以尽量减少float的使用,推荐使用固定布局或flex-box弹性布局的方式来实现页面元素布局。
7.不滥用web字体或过多font-size声明
过多的font-size声明会增加字体的大小计算,而且也没有必要的。
1.尝试使用SPDY和HTTP 2
在条件允许的情况下可以考虑使用SPDY协议来进行文件资源传输,利用连接复用加快传输过程,缩短资源加载时间。HTTP 2在未来也是可以考虑尝试的。
2.使用后端数据渲染
使用后端数据渲染的方式可以加快页面内容的渲染展示,避免空白页面的出现,同时可以解决移动端页面SEO的问题。如果条件允许,后端数据渲染是一个很不错的实践思路。后面的章节会详细介绍后端数据渲染的相关内容。
3.使用Native View代替DOM的性能劣势
可以尝试使用Native View的MNV开发模式来避免HTML DOM性能慢的问题,目前使用MNV的开发模式已经可以将页面内容渲染体验做到接近客户端Native应用的体验了。
关于页面优化的常用技术手段和思路主要包括以上这些,尽管列举出很多,但仍可能有少数遗漏,可见前端性能优化不是一件简简单单的事情,其涉及的内容很多。大家可以根据实际情况将这些方法应用到自己的项目当中,要想全部做到几乎是不可能的,但做到用户可接受的原则还是很容易实现的。
于此同时我们要清楚的是,在我们做到了优化的同时也付出了很大的代价,这也是前端优化的一个问题。理论上这些优化都是可以实现的,但是作为工程师我们也要明白懂得权衡。优化提升了用户体验,使数据加载更快,但是项目代码却可能打乱,异步内容要拆分出来,首屏的一个雪碧图可能要分成两个,页面项目代码维护成本成倍增加,项目结构也可能变得混乱。
所以前期在设计构建、组件的解决方案时要解决好异步的自动处理问题。任何一部分优化都可以做得很深入,但不一定都值得,在优化的同时也要尽量考虑性价比,这才是我们作为一名前端工程师处理前端优化时应该具有的正确思维。
蓝蓝设计( www.lanlanwork.com )是一家专注而深入的界面设计公司,为期望卓越的国内外企业提供卓越的UI界面设计、BS界面设计 、 cs界面设计 、 ipad界面设计 、 包装设计 、 图标定制 、 用户体验 、交互设计、 网站建设 、平面设计服务
随着移动互联网的发展,我们越发要关注移动页面的性能优化,今天跟大家谈谈这方面的事情。
首先,为什么要最移动页面进行优化?
纵观目前移动网络的现状:
蓝蓝 http://www.lanlanwork.com