YSlow有23条规则,中文能够参考这里。这几十条规则最主要是在作消除或减小没必要要的网络延迟,将须要传输的数据压缩至最少。css
1)合并压缩CSS、JavaScript、图片,静态资源CDN缓存html
经过构建工具Gulp,能够在开发的时候就将合并压缩的事情一块儿作掉。node
之因此要作合并压缩是由于:HTTP 1.x不容许一个链接上的多个响应数据交错到达(多路复用),于是一个响应必须彻底返回后,下一个响应才会开始传输。web
也就是说即便客户端同时发送了两个请求,并且CSS资源先准备就绪,服务器也会先发送HTML响应,而后再交付CSS。chrome
使用CDN是为了让用户访问的时候能用最近的资源,减小来回传输时间。设计模式
HTTP2.0改进了HTTP1.x不少方面。浏览器
2)CSS放顶部,JavaScript放底部缓存
CSS能够并行下载,而JavaScript加载以后会形成阻塞。服务器
但凡事仍是会有例外,若是把行内脚本放在样式表以后,会明显地延迟资源的下载(结果是样式表下载完成而且行内脚本执行完毕时,后续资源才能开始下载)。微信
这是由于行内脚本可能含有依赖于样式表中样式的代码,好比document.getElementsByClassName()。
<head> <link rel="stylesheet" href="css/all-normal.css" type="text/css" /> </head> <body> <div id="content"></div> <script> var content = ''; for(i=1; i<1000000; i++) content += '写入页面'; document.getElementById('content').innerHTML = content; </script> <img src="images/ui.png" /> </body>
下面经过Chrome的工具查看下:
3)优化DNS解析,减小重定向
在作一个“女神评选活动”的时候,须要在微信中访问可以获取用户的openid,微信获取用户基本信息是须要通过几个步骤的:
先获取code,再经过code获取openid,最后再跳转访问静态页面。
因为公司将业务分红了多个小组,因此短短的三步其实须要三个小组配合,须要重定向多个域名。
下图是未优化前的瀑布图,但不是最坏状况,有时候访问到静态页面须要通过10多秒,彻底不能接受,下图中会跳转4个域名:
后面不跳index那个域名,直接跳转到微信操做域名,减小一个域名的跳转,各小组代码再作优化,但效果仍是不理想,仅仅快了几秒。
最后发现实际上是在与微信的服务器作交互的时候,DNS解析花了太多时间!不得已,在服务器的host中添加一条记录,直接经过IP指向。
下图是最终优化结果,虽然达不到秒开,但至少能够接受了:
1)图片预加载
在作一个“秋名山活动”的时候,使用了图片预加载。这个活动中有120多张图片。
流程很简单,就是答题,最后给评论结果,再分享出去。
若是一会儿加载那么多图片,必定是愚蠢的想法,最后决定,在页面载入的时候先加载一些通用图片。
在答题的时候当前页面,预先加载后面页面中的图片,防止访问页面的时候直接不展现图片,图片也作了适当的合并。
将网站地址放在gtmetrix.com测试,下面是最终的瀑布图,能够发现图片都在其余静态资源的后面,这样能尽早的展示页面给用户:
优化还远远没有结束,在Chrome中分别模拟了good 2G、good 3G以及4G后,有结果的状况并不理想。
good 2G:
good 3G:
4G:
还有很大的优化空间能够作,关于这个预加载的原理,能够参考《图片预加载与懒加载》
2)减小分支
在写业务逻辑的时候,常常会用到if else,switch之类的逻辑判断,若是每次都作这么多判断,很容易影响性能。
因此能够经过多种方式来避免过多的判断。
1. 惰性模式
这是在看《JavaScript设计模式》的时候看到的。
减小每次代码执行时的重复性分支判断,经过对对象重定义来屏蔽原对象中的分支判断。
惰性模式分为两种:第一种文件加载后当即执行对象方法来重定义,第二种是当第一次使用方法对象时来重定义。
公司有个页面要提供给第三方APP,可是最终发现第三方APP不能使用localStorage缓存,最终只得作兼容的方式。
但为了不每次引用方法的时候都作判断,就使用加载后当即重定义:
var getFn = function() { if (sore.enabled) return sore.get; return cookie.get; }(); var setFn = function() { if (sore.enabled) return sore.set; return cookie.set; }();
2. 创建映射关系
页面中常常须要弹出框提示,后面就本身作了一个,但弹出框会有不少款式。
若是用简单工厂模式建立的话,免不了switch分支判断,后面就直接用赋不一样的key,还能缓存起来,只初始化一次。
/** * 弹出框单例模式 */ var factories = {}; var DialogFactory = function(type, options) { if (factories[type]) return factories[type]; return factories[type] = new iDialog(options); }; /** * 提示框 */ var Alert = function(content, options) { var d = DialogFactory('alert', options); //其余逻辑省略 return d; }; /** * 确认框 */ var Confirm = function(content, options) { var d = DialogFactory('confirm', options); //其余逻辑省略 return d; };
3)第三方代码异步加载
第三方代码,例如百度统计、微信SDK等,这些彻底能够在将业务资源加载完后再添加。
/** * 百度统计设置 */ util.baidu = function(key) { global._hmt = global._hmt || []; (function() { var hm = document.createElement("script"); hm.src = "//hm.baidu.com/hm.js?" + key; var s = document.getElementsByTagName("script")[0]; s.parentNode.insertBefore(hm, s); })(); };
4)cookie与localStorage缓存
有了缓存后,就能减小与服务器的通讯,在本地操做。
公司有个查违章的业务,在本地添加好车辆后,再次进入页面的时候就须要能直接选择事先添加好的车辆。
最理想的方式就是添加好后,就在本地缓存起来,下次进入直接调取缓存。
我会优先使用localStorage,下面的表格就是对比:
cookie |
localStorage | |
数据生命周期 |
可设置失效时间 | 除非被清除,不然永久保存 |
数据大 |
大约4KB | 大约5M |
与服务器通讯 |
每次都会携带在HTTP头中,若是使用cookie保存过多数据会带来性能问题 |
不参与和服务器的通讯 |
本地存储,以前的历史大概以下图所示:
localStorage在浏览器兼容方面,IE8竟然也支持了。
5)事件委托
使用事件委托技术能让你避免对特定的每一个节点添加事件监听器。
事件监听器是被添加到它们的父元素上,经过事件冒泡,触发执行。
在开发的时候,常常会出现动态添加元素的状况。
若是每次都从新绑定一次事件,那会有不少多余操做,而绑定在此元素的父级,就只需绑定一次便可。
document.getElementById('ul').onclick = function(e) { var e = e || window.event, tar = e.target || e.srcElement; if (tar.nodeName.toLowerCase() == 'li') { tar.style.background = 'black'; } }
6)节流与去抖动
节流(throttle):预先设定一个执行周期,当调用动做的时刻大于等于执行周期则执行该动做,而后进入下一个新周期。
例如mousemove 事件、window对象的resize和scroll事件。
去抖动(debounce):当调用动做n毫秒后,才会执行该动做,若在这n毫秒内又调用此动做则将从新计算执行时间。
例如文本输入keydown 事件,keyup 事件,作autocomplete等。
节流与去抖动最大的不一样的地方就是在计算最后执行时间的方式上。著名的开源工具库underscore中有内置了两个方法。
在作公司内部的一个系统的时候,须要方但愿在左右滚动表格的时候,能将第一列固定在最左边,方便查看。
为了让操做能更流畅,我再这里用了节流,有些浏览器会出现卡顿,就得须要增长周期时间。
1)在手机中打印变量
在移动页面的时候常常须要调试字段,又不能用console.log,每次alert的话,碰到对象就看不到内容了。
只能本身写个小方法来打印出来,JSON.stringify,经过这个方法可以方便的实现功能。
var print = function(obj, space) { space = space || 4; var html = JSON.stringify(obj, null, space); html = html.replace(/\n/g, '<br>').replace(/\s/g, ' '); var pre = document.createElement('pre'); var div = document.createElement('code'); pre.style.cssText = 'border:1px solid #000;padding:10px;background:#FFF;margin-bottom:20px;'; div.innerHTML = html; pre.appendChild(div); var body = document.querySelector('body'); body.insertBefore(pre, body.children[0]); }; print({a:1, b:'demo', c:{text:'content'}});
2)chrome插件JSON-handle
服务器返回的不少都是JSON格式的数据,一般写好后给你个接口,顺便给你几个demo参数。
在浏览器中打开后,就是一串字符串,但要给人看的话,就得格式化一下了,这个插件就是用来让人看的。