为何要有性能优化?回忆一下,当你打开一个网页时,你能忍受的打开速度是几秒?超过5秒你可能会当即走人。。。网站的加载速度严重影响了用户体验,也决定了这个网站的生死存亡。css
减小HTTP请求html
为何?性能黄金法则,在HTTP请求的过程当中,只有 10%~20% 的最终用户时间花在了下载 HTML 文档上。其他 80%~90% 的时间花在了下载页面中的全部组件上进行的HTTP请求上;前端
改善响应时间最简单的途径就是减小HTTP请求的数量; web
每下载一个图片、js文件、css文件等等都是一次HTTP请求,因此要尽量的少下载静态资源;数组
使用CSS雪碧图,以前写过一篇文章 浏览器
图片地图缓存
咱们能够经过使用多个分开的图片,而后每一个图片都对应一个超连接,固然这也会产生不少HTTP请求,咱们目标是减小HTTP请求; 性能优化
图片地图容许你在一个图片上关联多个 URL。目标 URL 的选择取决于用户单击了图片上的那个位置;服务器
将多个图片合并成一个图片(即将多个HTTP请求减小为一个HTTP请求),而后以位置信息定位超连接;网络
具体用法,请移步到 https://www.w3school.com.cn/tags/att_area_coords.asp ;
尽可能合并、压缩CSS、JS文件,或者直接写在页面上
使用CDN加速
通俗的说,服务器离用户更近,HTTP 请求的响应时间将缩短;
CDN(内容发布网络)是一组分布在多个不一样地理位置的web服务器,用于更加有效地向用户发布内容;
借张图说明一下:
利用缓存
CDN缓存
DNS缓存
DNS是“域名系统”的缩写,它的工做是将域名和主机名转化为服务器主机的 IP 地址;
DNS查找流程:浏览器缓存 — 本地hosts文件 — 本地DNS解析器缓存 — 本地DNS服务器 — 本地DNS服务器设置(是否设置转发器)— 根DNS服务器(返回一个负责该域名服务器的一个IP。本地DNS服务器会根据这个IP继续查找服务器,若是查找到的服务器不能解析此域名,则它会找另外一个管理此域名的DNS服务器给本地DNS服务器,重复上面的动做,直到找到域名对应的主机)— 不要晕~
浏览器缓存之客户端缓存
无需请求的memory cache,disk cache;
须要发请求验证的Etag、Last-Modified304;
H5新增的 localStorage、sessionStorage;
合理利用以上缓存,能够很大程度上提升前端性能。
HTML部分
标签语义化,即用合理、正确的标签来展现内容,好比 h1-h6 定义标题;
语义化的优势:
易于用户阅读,样式丢失的时候能让页面呈现清晰的结构;
有利于SEO,搜索引擎根据标签来肯定上下文和各个关键字的权重;
方便其它设备解析,如盲人阅读器根据语义渲染网页;
有利于开发和维护,语义化更具可读性,代码更好维护,与CSS关系更和谐;
HTML很容易被网络爬虫识别,所以搜索引擎能够根据网站的内容在必定程度上实时更新。在写HTML的时候,你应该尽可能让它简洁而有效。举个例子:你在写一个网站,这个网站的其中一个模块包括了各个高校的数据信息,而这些数据信息是实时更新的,你能够利用爬虫去获取这些数据信息,若是各个高校的网站的HTML是很是符合语义化标准的,那么你就能够很顺利的爬到这些数据信息;反之,会增长你的爬虫代码的难度
CSS部分
将CSS放在HTML的上面部分,这个策略不能提升网站的加载速度,但它不会让访问者长时间看着空白屏幕或者无格式的文本(FOUT)等待。若是网页大部分可见元素已经加载出来了,访问者才更有可能等待加载整个页面,从而带来对前端的优化效果。这就是知觉性能。
使用 link 而不是@import
加载页面时,link标签引入的CSS被同时加载;@import引入的CSS将在页面加载完毕后被加载,也就是说,@import会组织浏览器的并行下载;
link是HTML的元素,不存在兼容性问题;@import只有IE5+才能识别;
有关link和@import的区别还有不少,推荐一篇文章 http://www.javashuo.com/article/p-bstehaet-h.html
总之,link标签才是最好的选择,它也能提升网站的前端性能。
合并CSS代码,好比用 margin 来代替 margin-top、margin-bottom、margin-left、margin-right;
减小重排,重排会致使浏览器从新计算整个文档,从新构建渲染树,这一过程会下降浏览器的渲染速度。咱们应该避免发生重排,下面是触发重排的例子
改变 font-size 和 font-family;
改变元素的内外边距;
经过JS改变CSS类;
经过JS获取DOM元素的位置相关属性(如width、height、left等);
CSS伪类激活;
滚动滚动条或者改变窗口大小;
减小重绘,当元素的外观(如color、background、visibility等属性)发生改变时,会触发重绘。在网站的使用过程当中,重绘是没法避免的。不过,浏览器对此作了优化,它会将屡次的重排、重绘操做合并为一次执行。不过咱们仍须要避免没必要要的重绘,如页面滚动时触发的hover事件,能够在滚动的时候禁用 hover 事件,这样页面在滚动时会更加流畅;
减小使用昂贵的属性,在浏览器绘制屏幕时,全部须要浏览器进行操做或计算的属性相对而言都须要花费更大的代价。如 box-shadow、border-radius、filter、opacity、:nth-child等;
合并、压缩CSS文件
JS部分
注意做用域,避免全局查找,访问全局变量比访问局部变量慢,是由于须要遍历做用域链,查找做用域链须要额外的时间。因此在一个函数中,将访问屡次的全局对象或者域外变量存储为局部变量来使用。如某个方法需引用全局变量的值,则在该方法所在的对象的做用域中定义一个局部变量等于全局变量的值。避免没必要要的属性查找,将属性设置为全局变量。
优化循环,当 if-else 较多时,建议使用 switch 语句。当分支较多时,用 switch 的效率是很高的,由于 switch 是随机访问的,就是肯定了值以后直接跳转到那个特定的分支,而 if-else 是遍历全部可能值,直到找到合适的分支;
当循环的数量很少时,展开循环;
最小化语句数,声明多个变量时,可使用一个 var 关键字来声明,变量之间用逗号表示;
使用数组或对象字面量来新建数组或对象,如 var arr = [1,2,3] ;var obj = {a:1,b:2};
JS的执行尽可能脱离DOM树,限制DOM操做的次数优化DOM交互,在《JavaScript高级程序设计》一书有这样一段话:在更新少许节点的时候能够直接向 document.body 节点中添加,可是要向 document 中添加大量数据时,若是直接添加这些新节点,这个过程很是缓慢,由于每添加一个节点都会调用父节点的 appendChild() 方法,为了解决这个问题,能够建立一个文档碎片,把全部新节点附加其上,而后把文档碎片一次性添加到 document 中。
假如想建立十个段落,常规方式以下:
for(let i = 0;i < 10;i++){ let p = document.createElement("p"); let txt = document.createTextNode("段落"+i); p.appendChild(txt); document.body.appendChild(p); }
上段代码调用了10次 document.body.appendChild(),每次都要产生一次页面渲染。这时候能够用文档碎片createDocumentFragment(),
let fra = document.createDocumentFragment(); for(let i = 0;i < 10;i++){ let p = document.createElement("p"); let txt = document.createTextNode("段落"+i); p.appendChild(txt); fra.appendChild(p); } document.body.appendChild(fra);
上段代码中,每一个新的 <p> 元素都被添加到文档碎片中,而后这个碎片被做为参数传递给 appendChild()。fra.appendChild() 实际上并非把文档碎片加到body中,仅仅是追加碎片中的子节点。document.body.appendChild() 一次代替了10次,也就是说,只产生了一次页面渲染,能够看到明显的性能提高。
使用事件代理,页面上的事件处理程序的数量和页面响应用户交互的速度之间有个负相关。因此为了减小事件处理程序,尽可能使用事件委托技术。
提升代码的可阅读性,好比正确标记变量,封装某个重复的行为,合理的注释等。
使用cssText、className一次性改变属性;
JS定义行为,html定义内容,CSS定义外观;
持续完善中,如有错误,欢迎指出!
参考连接
http://www.ruanyifeng.com/blog/2015/09/web-page-performance-in-depth.html
https://blog.csdn.net/qq_21891743/article/details/79642605
https://blog.csdn.net/bluedandelion/article/details/80895021