本文提供一个优化网页性能的大概思路,具体操做网上资料不少。css
性能优化第一步,即是管理好页面的缓存,避免重复下载资源。不然,即增长服务器压力,又折磨用户的钱包。html
访问页面,请求各类资源,浏览器检查本地是否有缓存。css3
若是有,检查资源是否过时。没过时,直接使用缓存。过时了,便向服务器发出请求。浏览器
发出的请求中会带上etag和last-modified首部字段。缓存
服务器会经过Etag和last-modified来判断浏览器缓存的资源是否已经不可用。性能优化
若是资源仍然有效,便返回304告知浏览器使用缓存。不然返回更新后的资源。服务器
按照这一套逻辑,即可规划好网站的缓存。async
一般没法作到这一点,由于浏览器发现资源没过时,根本不会发出请求。 可是能够经过修改资源的网址来实现。因此须要给资源文件名加上版本号或者随机标记。例如 style.1234.css。 也就是说,不要让浏览器缓存html文件,不然,过时以前,浏览器都不会请求服务器。函数
最好的优化,即是根本不下载资源。因此要尽可能减小比不要的资源。工具
评估全部依赖是否必要,权衡利弊。
依赖的下载路径是否可靠,不可用时候是否会阻碍整个页面。
产品设计时候就须要抛弃浪费带宽的设计。
去掉没必要要的图片
多使用css3来代替图片
使用压缩率更高的图片。特别是gif动图,一些视频格式(H.264或WebM)的体积比gif小不少。
用艺术字字体,不要用图片
仔细权衡图片和文字的关系。要表达一个意思,可能一图胜千言。多了一张图片,反而节省了大量文字。
使用progressive jpeg。相比随着数据下载从上到下显示的baseline jpeg,progressive jpeg是由模糊到清晰,用户体验好,也不会致使reflow。
图片分辨率要尽量小,避免图片分辨率大于显示分辨率。
为使用更新浏览器的用户提供更现代的图片格式。
多种分辨率的位图供不一样页面大小使用。
要给标签指明宽高,不然会致使reflow。
使用HTTP/2。好比,精灵图是由不少小图片组成的一张大图片,能够减小http请求。可是却难以缓存,修改一个小图片,致使全部小图片缓存失效。HTTP/2,一个连接内能够发起多个请求,便无需使用精灵图。
@font-face 中unicode-range能够制定字符范围,用来避免下载不须要的语言的字符。
确保字体都被压缩过。
用@font-face的display属性和FontFace对象管理好字体加载时的逻辑。
浏览器渲染一张网页经过如下步骤。
处理 HTML 标记并构建 DOM 树。
处理 CSS 标记并构建 CSSOM 树。
将 DOM 与 CSSOM 合并成一个渲染树。
根据渲染树来布局,以计算每一个节点的几何信息。
将各个节点绘制到屏幕上。
优化关键渲染路径,即是指优化这个渲染过程,让网页尽快呈现出来。
CSS文件会阻塞渲染。浏览器构建好DOM树后,必须等待CSSOM树构建完成。
在文档顶部防止外联CSS的标签,让浏览器尽快请求CSS文件。
避免在css文件中使用@import,由于只有包含import的文件被下载编译后,浏览器才会发现并下载import的css。
能够考虑使用内联CSS,无需额外请求,不会阻塞渲染。
在CSSOM构建完成前,js不会开始执行。
js也会阻止DOM树构建。除非在 <script>
标签上标记async。
用Chrome开发者工具的audits检查网页。
重绘过程
选择器越复杂,浏览器计算得越久。最糟状况下,浏览器须要遍历整个DOM-tree,计算量等于元素总个数乘以选择器个数。
尽可能不要使选择器太复杂,事先给须要被操做的元素加上类名。
Chrome, Opera, Safari, Internet Explorer中叫layout. 火狐称之为Reflow。
reflow, repaint次数越少越好,牵连的元素越少越好。
reflow老是牵涉整个文档流。
修改元素css后马上读取css计算值,将致使浏览器同步reflow,阻塞js线程。
浏览器渲染网页时,会将网页分层(layer),最后将不一样层合并,而后完成渲染。 同一层中,哪怕只有一个小小的元素发生变化,整个层都会被repaint。 这一点能够在开发者工具的Paint Profiler界面中观察到,layer界面中能够观察网页有多少个layer。
paint是耗费性能的。
修改transform和opacity会致使repaint
建立新layer来减小repaint区域。
will-change属性能够为元素建立新layer(works in Chrome, Opera and Firefox).或 transform: translateZ(0);(works in all browsers).
过多layer也消耗内存和性能,用Performance判断新layer是否带来优化,不然不要建立新layer。
高dpi屏幕下,fixed元素自动拥有本身的layer。低dpi须要自行建立。
repaint某个layer时,若是layer与其余元素重叠,将致使layer和重叠的元素都被repaint。
最好的动画是跳过layout和paint直接composite。
用transform, opacity来制做动画,可实现无layout和repaint. (Devtool Performance的main中无动画相关事件。)
debounce:不要高频率调用函数,事件连续触发时,只调用一次函数。
交互事件的监听函数的执行时间不能太长,不然会阻塞页面滚动。
不要再交互事件的监听函数中修改样式,会致使强制同步reflow,阻塞js执行。
debounce,活用requestAnimationFrame方法。
监听函数可能会调用perventDefault, 致使compositor线程必须等待监听函数执行完成。 不过新扩展的addEventListener方法第三个参数能够解决此问题。
动画不能低于60帧。ui反馈不能低于100ms。
ui反馈没必要追求最快,可故意拖延到100ms。并利用这个时间作其余事。
尽可能增长线程空闲时间,以快速反馈。
ui反馈优先级最高,交互期间尽可能停下其余任务。