欢迎你们前往腾讯云技术社区,获取更多腾讯海量技术实践干货哦~css
导语 : 从事前端有6年+的时间了,从最开始的美工到重构再到偏向js逻辑开发的前端开发,一直在前端这个行业里面摸索和学习,我如今将本身这些年的一个心得体会来个系统性的梳理写成一篇关于性能优化的主题文章,但愿对你们有点帮助,也欢迎你们提出各类意见和建议。html
做者:刘勇刚 前端
前端工程师是一个最近这5-6年才开始慢慢被互联网公司重视起来的一个职业,能够说是一个新兴行业,我用一张简单的思惟导图带你们回顾一下前端技术发展的历程以及将来一个展望:html5
1.0时代没什么说的,html、css打天下的时代,那个时候你会用js开发个计算器就牛逼到不行。2.0时代是最好的时代,新技术、新思想蓬勃发展,堪称前端的工业革命,前端人员的地位获得了充分承认,门槛也有必定的提高。前端性能优化的涉及点从服务器到协议再到宿主环境自己都要有比较深入的认识,业界目前主要仍是以雅虎总结出来35条前端性能优化的黄金军规(http://www.cnblogs.com/siqi/p/3655436.html) 为参考。今天我想将这些年对前端的性能优化的经验思考总体来个串烧,带你们鸟瞰一下前端性能优化目前的一些通行作法以及这么作的出发点。文章初衷主要是对一些性能优化基础知识回顾和体系梳理,不对具体技术点作深刻分析,点到为止,我的理解不对的地方欢迎各位大神拍砖,抛砖引玉。node
引入话题前我仍是先从一个老生常谈的话题开始:webpack
“从用户输入URl到页面展现给用户浏览器客户端的过程当中发生了什么?”css3
这里用个图表简单描述一下几个步骤:web
web优化的目标就是如何让用户更快、更简单易用、更流畅的使用咱们的服务,对于前端开发而言就是如何让咱们的资源体量更小、数量更精简、内容更早呈现、交互更加人性化。ajax
web性能优化有个你们比较公认的二八原则,就是资源从服务器处理完下发到客户端的浏览器上(上图第6步)所占的时间比例大概是整个过程的20%,也就是说服务器端能够优化的空间的效率提高并不会很明显,前端性能优化成为web性能优化重点考虑的领域,我下面将会从如下几个维度去作了本身的一个思考(跟35条军规有必定重叠)和总结:算法
浏览器是一个单线程解析模式去解析渲染从服务器端拿到的html文本,css加载的过程当中会对后续的脚本资源加载形成阻塞,脚本的加载也会阻塞后续DOM结构的解析形成页面的留白时间增加,雅虎的35条军规中有一条就是样式文件放在头部,脚本文件放在DOM节点最末尾,减小阻塞。这里还有几个针对脚本文件的优化:
浏览器的事件模型的冒泡的特性(浏览器事件模型不清楚的自行搜索了解)我以为是最牛逼的设计之一,解决了浏览器由于解析DOM模型不一样步致使开发者往DOM对象注册事件回调找不到对象的问题。
浏览器事件注册有3个级别定义,DOM 0级事件注册(利用DOM元素行内事件属性onclick注册事件回调),DOM 1级事件注册(利用DOM元素对象的onclick API 在外部注册事件回调),DOM 2级事件注册(利用利用DOM元素对象的addEventListner/attachEvent API 在外部注册事件回调)。这里性能优化的建议就是利用DOM2级在目标DOM的父标签(大部分框架是在body标签统一注册事件监听)注册回调,收拢事件监听入口同时节约了DOM节点引用开销。
Cookie是前端做为先后台登陆态校验最一般用的缓存方案,但鉴于浏览器在每次都会往同域的任何资源的http请求中自动带上cookie信息的状况,这里有必要进行优化一下,由于像css、js、image这些资源请求是不须要cookie信息的,会无故形成请求带宽的浪费(想象一下咱们的cookie大小假设为10K,100个请求就是近1M的大小,高并发下以咱们现行网络带宽也是蛮大的一笔负担了)。Cookie free性能优化方案的处理方式是CDN异域静态资源服务器部署咱们的前端css、js、image资源。
以本身目前负责的香港跨境汇款为例
页面路径下的资源的请求:
CDN资源加载的请求:
经过对比CDN分开部署的资源请求并无带上cookie信息。
浏览器针对domain,而非页面page作并发链接限制的特性,domain hash的技术优化方案的处理方式是将资源划分域分开部署,但由于过多的域划分会增长多余的DNS开销,这里通行的数量是3个之内。目前咱们的港菲汇款业务只有两个域名分开部署,一个主站,一个CDN,我我的建议能够将CDN中的图片资源再单独再分一个域名部署会更好些,为何单独把图片抽出来,后面会讲到。
针对一些界面渲染过程比较耗时的状况下,能够利用CSS3属性开启GPU来加速渲染咱们的DOM,开启很简单通常我是用-webkit-transform:translateZ(0)假3D属性来唤起系统GPU加速渲染功能,关于为何会这样,我这里作个简单的解释:
对于咱们的浏览器而言,拿到咱们的html文本串开始按顺序解析成DOM树,并与同步解析出来的CSS匹配生成渲染树(跟DOM树的节点不是一一对应,好比display:none的节点就不会插入渲染树)
图片来源 http://www.javashuo.com/article/p-tmdxesbg-hy.html
浏览器将渲染树的节点用一个图层表示,这样层层叠加在一块儿生成layout,有点像ps的图层叠加的概念(能够经过火狐浏览器开发者工具3维展现更直观),通常状况下对节点的任何涉及尺寸的改变都会引发layout的重排重绘(重排和重绘是形成浏览器渲染的最大性能损耗的因素),但有种开小灶的状况Composite Layers(复合图层)直接交给咱们GPU中单独的合成器进程处理,自身变化不会引发其余层的位置变化,不会引发重排重绘。tranform 3d属性是能够悄悄的告诉咱们的浏览器把元素解析做为复合图层交给单独进程去处理的。
注:这里有个原则,不能滥用咱们的加速,由于过多开启硬件加速会消耗更多的用户内存空间,也会比较耗电,通常针对css3动画建议开启
a、通行解决方案
图片base64编码传输:图片base64编码后,可让浏览器减小自身的一次http请求,但由于自身的一些缺陷,不能滥用(即便一个很小的图片编码后都会有一大串字符,增长了咱们CSS体积,性能不降反升),个人建议是针对那些全站通用或者体积很小很差整合到雪碧图里面的图标进行编码,固然还有不少不一样的场景你们本身权衡。
图片延时加载:主要是为了减小首屏一次性图片的加载量。具体作法是给图片或者标签设置一个私有行内属性data-image(固然能够本身随便定义)存放目标图片地址信息,监听浏览器的滚动事件,标签到了浏览器可视区域就将图片地址放入图片的src属性中或者做为标签的样式的背景图片中展现。淘宝首页的作法是用一个div来作延时图片加载,经过背景图片来展现最后的图片。
图片展现前:
图片展现后:
b、缓存机制
一、给须要作离线缓存的页面html标签设定manifest属性,指定缓存的配置文件 cache.appcahe(能够设定任何扩展名,只要在服务器端配置mime-type为text/cache-manifest就行)。
二、建立上一步指定的cache.appcache配置文件,按如下截图说明来配置资源
三、在服务器端配置配置文件的扩展名映射的mime-type为text/cache-manifest
appcache离线方案诟病太多,目前接入的很少,有种慢慢变弃儿的趋势,这里提出来让你们权衡
a、通行解决方案
css、script、图片压缩:这些能够gulp或者webpack自动化脚本里面定义脚本任务来完成。
服务器开启gzip压缩:通常如今服务器都有开启Gzip压缩,压缩率一般都是30%以上,效果仍是不错的。
原图:
Gzip压缩后:
b、页面切片预加载方案
性能优化静态资源维度最后一块内容就是针对页面,如何尽早输出页面模块,减小留白时间是一个思考点。facebook应用的BigPipe方案是个很不错的借鉴思想,还有淘宝也有首页作了相应的切片方案,对页面合理的分块,在服务器和客户端创建某种对应机制,让各个页面块并行的在服务器端拼接完成并吐出来,目前我对这块没有太深的了解,这里只是提出bigPipe的方案供你们参考。
TCP链接中的3次握手、慢启动的一些特性注定了链接通道的利用效率成为制约性能的一个很大的因素。由于http是基于TCP的应用协议,TCP层维度考虑还得从http几个版本的发展历史来看:
谷歌(叒是谷歌,牛逼)率先在09年基于TCP开发出全新SPDY应用协议,解决了多路复用请求优化、服务器推送的痛点问题,也为后面http2.0的推出奠基了基础。
咱们能够作的优化:减小一些没必要要的请求(扫除404死链接、304请求用咱们的长缓存机制)去优化,尽可能减小一些没必要要的链接请求数。
鉴于js语言自己的灵活性,以及每一个人的开发习惯,很难有很好的一个方式去验证开发者的代码实现的效率(目前更多的是用打点测速的方式去监控代码的执行时间),更多的是一种建议,你们有更好的建议能够提出来分享。
单线程限制:利用异步回调&多线程API突破js语言单线程带来的内存开销利用不充分的问题,现有能够利用的一些异步方式的回调均可以尝试利用好比settimeout,setinterval,requestAnimationframe(推荐用它),多线程的API方式有WebWork。这里推荐日本的一个开发者开发的一个多线程前端库Concurrent.Thread.js(它是做者用setTimeout和setInterval来模拟的多线程,能够自行网上搜索了解)。
重点优化代码中的循环结构体:就代码自己而言影响执行效率的大部分是循环体结构和算法设计不合理致使的时间复杂度和空间复杂度的增长。这里放两段实际项目中的代码截图来对比:
实例功能须要:实现输入框每4个字符一个空格隔开的效果
低效实现方式,用for循环:
改进后的方式:
性能优化通常都是从技术角度去入手,但咱们的目标之一“让用户简单易用”也是性能优化的一环。当技术性能缺陷难于避免的时候,做为前端交互实现的执行者,更应该配合产品和交互设计师提出一个咱们认为更好的交互逻辑体验方案去让咱们的数据加载不那么让用户有等待的感知,让咱们的提示更加的人性舒服。(交互设计师更加专业,我这里不敢班门弄斧)
文章最后对Web3.0时代作个本身的猜测,web3.0目前在业内尚未很明肯定义,你们能够大胆猜测前端行业将来形态。我在这先YY一下,人工智能、大数据普遍应用应该会成为推进前端进入3.0的时代的最好契机,以此引起的前端新的革命:
结语:刚来鹅厂不久,做为前端攻城狮进入到国内顶尖互联网公司感到骄傲,性能优化是一个永恒的话题,每一个阶段都有聊不完的性能优化的话题,我将我这些年的一些不成文的理解整理了一下,但愿对你们有点帮助。第一次发文章,有错误的地方请你们指点一二。
从 10 Gb 到 40 Gb,从百万级到千万级转发,打造高性能 TGW
此文已由做者受权腾讯云技术社区发布,转载请注明文章出处
原文连接:https://cloud.tencent.com/community/article/879614