文章原本是给公司内部分享用的,如今发表出来,欢迎你们提出宝贵建议。css
按粒度分为两类:html
页面级别的优化目标基本就是如何减小HTTP请求数,减小请求资源的体积。每一个请求都是有成本的,既包含时间成本也包含资源成本(一个完整的请求都须要通过DNS寻址、与服务器创建链接、发送数据、等待服务器响应、接收数据这样一个 “漫长” 而又复杂的过程)前端
根据静态文件的类型,能够借助gulp工具将js文件和css文件进行合并和压缩。 例如官网项目里css文件有七个,js文件有十几二十多个,合并压缩静态资源后能够减小http的开销。 jquery
lazyload
插件实现图片懒加载。等滚动条滚动到对应的地方再加载所须要的图片资源。devicePixelRatio
检查设备的像素比,辅助区分视网膜设备仍是非视网膜设备来决定加载两倍图仍是原始大小的图片。gulp-imagemin
工具压缩下大小。icon-font
来实现。或者直接在页面写svg代码和转成base64写到页面也行,总之是要减小http的请求数。
将首屏第一时间呈现给用户。 具体的作法是除了首屏dom元素以外,将全部的dom元素用一个template
元素进行包裹,等window监听到load事件后,将剩余的dom部分所有插到页面中。(tips:为避免用户可能还没等到window的load事件就开始滚动页面,能够将首屏的范围扩大。)web
DNS预读取是一项使浏览器主动去执行域名解析的功能。DNS请求须要的带宽很是小,可是延迟却有点高。 下面是引用MDN的一句话:chrome
在某些浏览器中这个预读取的行为将会与页面实际内容并行发生(而不是串行)。正因如此,某些高延迟的域名的解析过程才不会卡住资源的加载。 这样能够极大的加速(尤为是移动网络环境下)页面的加载。在某些图片较多的页面中,在发起图片加载请求以前预先把域名解析好将会有至少 5% 的图片加载速度提高。gulp
具体作法: head
标签里加上浏览器
<link rel="dns-prefetch" href="https://data.dadaabc.com/">
复制代码
data.dadaabc.com
为静态资源的域名,如还有其余连接的域名,都一块儿加进去。缓存
同域下浏览器能并发的请求有限,为了增长并发,尤为是一些静态资源上,可使用多个域名。但因为域名DNS解析自己也是耗时的,因此也不是越多越好,chrome最大支持6路并发,因此通常设置2-4个域名较为合适。 具体的作法是:再增长cdn域名来下载静态资源。好比图片所有用img.dadaabc.com/
域名,css资源所有用css.dadaabc.com/
域名,这些域名最终所有指向一样的cdn服务器。静态资源域名加前缀能够用gulp-rev-replace
来实现。bash
统计代码所有放到window的load事件以后执行。为了便于管理统计代码,例如页面加上一些埋点,增长删除统计产品,咱们能够借助Google Tag Manager
工具来统一管理。 具体作法是:页面只拉取Google Tag Manager
提供的gtm
代码,该js代码含有所有的统计产品,例如百度、Inspelect等, 这些统计产品也都是经过建立script标签来动态插入到页面中的。另外须要注意的是,google提供的gtm
代码是在google服务器上的,为了让获取该代码的速度更快,咱们能够在本身的服务器上执行crontab
定时任务,每分钟获取一次,而后gtm
代码直接从本身服务器上获取。
css文件所有放到head
里,script文件所有放到body
的最底部。 缘由: 把样式表移到head
里容许页面逐步渲染。 浏览器负责渲染的GUI渲染线程与JS引擎线程是互斥的,当JS引擎执行时GUI线程会被挂起(至关于被冻结了),GUI更新会被保存在一个队列中等到JS引擎空闲时当即被执行。
#####多个属性改变一次性写: 举个例子:
var ele = document.getElementById('myDiv');
ele.style.borderLeft = '1px';
ele.style.borderRight = '2px';
ele.style.padding = '5px';
复制代码
三个样式属性被改变,每个都会影响元素的几何结构,虽然大部分现代浏览器都作了优化,只会引发一次重排,可是像上文同样,若是一个及时的属性被请求,那么就会强制刷新队列,并且这段代码四次访问DOM,一个很显然的优化策略就是把它们的操做合成一次,这样只会修改DOM一次:
var ele = document.getElementById('myDiv');
ele.style.cssText = 'border-left: 1px; border-right: 2px; padding: 5px;';
复制代码
总结:同一个DOM的多个属性改变能够写在一块儿(减小DOM访问,同时把强制渲染队列刷新的风险降为0)
fragment是个轻量级的document对象,它的设计初衷就是为了完成更新和移动节点这样的任务。fragment的一个便利的语法特性是当你附加一个片段到节点时,实际上被添加的是该片段的子节点,而不是片段自己。只触发了一次重排,并且只访问了一次实时的DOM。 例如:
var fragment = document.createDocumentFragment();
var li = document.createElement('li');
li.innerHTML = 'apple';
fragment.appendChild(li);
var li = document.createElement('li');
li.innerHTML = 'watermelon';
fragment.appendChild(li);
document.getElementById('fruit').appendChild(fragment);
复制代码
触发大量回调函数的事件,例如拖拽时的mousemove
事件,window对象的resize
、scroll
事件,文字输入、自动完成的keyup
事件等,须要合理使用函数防抖和函数节流机制。具体能够参考个人另一篇文章函数防抖和函数节流
CSS选择器的解析式实际上是从右到左的,例如:
#div1 a {
color: red
}
复制代码
如上面的选择器,浏览器必须遍历查找全部的a元素,再去找ID为div1的元素,这样查找的方式显然很低效。
参考资料: Web前端应该从哪些方面来优化网站? 重排和重绘