12bet,的读书笔记

第一章 概述

12bet,高性能并不仅仅指页面加载时间,它还包括一下几个方面:

  • 页面加载时间
  • 浏览器性能
  • 网络性能
  • 开发效率

12bet,页面加载时间过长会使用户离开网站,还会影响Google的排名

12bet,现代浏览器都非常重视对JavaScript引擎、CSS动画处理等方面的性能优化和加速

网络带宽比较昂贵,每个商业公司都希望能够控制网络带宽的使用成本,减少不必要的浪费

工程师不喜欢做重复的事情,代码重用节省开发时间、12博体育,减少代码量,能够有效避免工程师迫于时间压力写出有隐患的代码。别想着以后回来优化这些代码,事实上没有回头的机会

第二章 开发原则

我们应当遵守的开发原则:

  • 12博体育,编写符合当代浏览器性能的代码
  • 用CSS布局
  • 使用渐进增强
  • 各司其职

编写符合当代浏览器性能的代码

首先需要知道浏览器的工作原理:

HTML源码 → HTML解释器 →   DOM
                           ↓
                         渲染树 → 渲染 → 展现
                           ↑
CSS源码  → CSS解释器  → 样式规则

HTML被解析成一棵DOM树。之后DOM树与CSS样式结合起来构成渲染树(FF中叫框架树),CSS样式表不仅包括自定义的样式,也包括浏览器默认样式。

可以从以下两个方面进行优化;

  • 减少HTML元素数量
  • 减少重绘

减少HTML元素数量

不要滥用HTML,而是要用最少量但是必需的HTML去语义化布局

减少重绘

在元素完成绘制后,动态更改DOM机构或CSS样式都会引发浏览器重绘。性能的损耗取决于动态改动的范围,现代的高级浏览器只会重回必要的部分。但是如果改动一个元素的位置或是新增一个元素,就会引发大量重绘,因为它影响了所有的兄弟元素

修改DOM和CSS样式有两个要点需要考虑:

  1. 改动的元素在DOM树中的深度,越深则改动阅读理解,对其他节点影响越少
  2. 如果对DOM和样式有多次操作,尽量合并到一次做完

吧CSS(包括外链CSS)放在head标签中,吧script放在body标签的尾部。浏览器不会等全部HTML解析完成之后才渲染元素,而是同时进行。把CSS放到前面就会保证先渲染的那一部分的样式显示是正确的。浏览器要预处理JavaScript文件,所以把JavaScript文件放在头部会延迟页面元素的渲染

使用CSS来布局

浏览器渲染页面实际上就是渲染一系列的盒子。这些盒子里还包含了许多其他的盒子。完美实现盒子套盒子的方法就是把一个或一大组元素都包在一个盒子里,相反,不好的方式就是把一些元素丢到盒子外面

通过这种方式布局,我们应该尽量做到:

  • 清晰的表达意图(也就是使用有意义的标签),同时也能让别人比较容易知道我们的意图
  • 尽一切可能兼容更多浏览器
  • 轻松地创建和维护,有助于将减少重复劳动
  • 模块化可复用

渐进增强

渐进增强指首先有一个基本的设计是可以兼容所有浏览器的,然后再为较新的或更新的浏览器做加强的显示或功能(渐进式)

老式的浏览器记得特征检测和打polyfill

各司其职

有一种性能叫开发性能,也就是开发效率。为了代码复用,需要将内容、表现、行为进行分离

  • HTML:内容之源
  • CSS:展现大师
  • JavaScript:动态数据之王

第三章 性能准则

页面加载时长很重要

  • google把页面加载的快慢列入了搜索排名的考虑因素
  • 100ms对应1%的销量下滑

准则

  • 减少HTTP请求
  • 使用CDN加速
  • 避免空的src和href属性值
  • 增加过期头
  • 使用GZIP
  • CSS放head标签中
  • JavaScript放body标签尾部
  • 避免使用CSS表达式
  • 删除不使用的CSS语句
  • 对JavaScript和CSS进行代码压缩
  • 减少重绘

减少HTTP请求

可以分为三部分:

  1. 理解并行连接
  2. 合并资源文件
  3. 使用图片精灵

HTTP 1.1 协议很明确的限制了单个用户不能在同一时间保持2个以上的连接。但最近几年,大部分浏览器突破了这个限制,很多浏览器现在支持4个并行的连接,有一少部分只吃到了6个。IE8会根据用户的带宽来决定连接的数量,拨号连接时为2个,宽带连接为4个。可以把资源分散到不同域名下,来充分利用浏览器并发提高效率,但是由于DNS查询也有耗时,如果域名过多,也会降低性能

把内容合并成尽可能少呃文件,可能的话,所有CSS合并成单独一个,所有JavaScript合并成单独一个。如果有多个页面相互引用,那么可以通过编译脚本解决,为每个页面生成单独的合并脚本。有如下方式进行合并:

  1. 可以在JS文件和CSS文件改变时进行合并
  2. 可以在上线发布的时候进行合并
  3. 抽出所有网页共同的CSS文件,进行合并。然后为每一页提供只针对该页面的CSS文件

图片精灵(sprite)其实就是把几张图拼成一张图。它把很多小图片拼成一张大图从而在地并发的浏览器上达到快速传输并呈现内容的目的,这样可以有效减少HTTP请求数量。可以进行如下考虑:

  1. 可以将图片精灵根据颜色进行分组,每一个精灵都只有一种颜色范围(色相和亮度),这样图片压缩时效率更好,压缩后的图片更小
  2. 当然出于可维护性考虑,有时候也会不按颜色而根据某种法则去合成多张图片精灵
  3. 图片精灵能够被缓存,这样就节省更多的HTTP请求

使用CDN加速

CDN(内容分发网络)是一个拥有很多服务器、经过策略性部署、可以覆盖全球的网格系统。当从中取数据时,总是从最近的一个节点取数据给他。这些节点所缓存的文件是不易改动的,所以最好在CDN上存放静态的文件,如图片、字体、JavaScript库等

使用CDN最好在文件引用时加一个时间戳,这样就有一个唯一的文件引用,而不用担心缓存在CDN服务器上的过期文件会对用户产生影响。每次改动文件时更新一下时间戳

避免空的src和href属性

src和href为空时,浏览器依然会发起一个HTTP请求。另外,空的src和href也会产生报错。如果在发送空属性值的时候,追踪请求头的状态,是无法追踪到状态的

增加过期头

应该在所有的静态文件(图片、样式、脚本、Flash、PDF等)上加过期头。过期的日期要定得非常遥远,基本上可以认定为永不过期。这样,用户第二次访问网站时,就不会再次请求这些已经被缓存的静态文件了。但为了防止用户只能看到老版本,最好有一套版本控制机制,其中一种方式就是在文件名上加入时间戳

启用GZIP压缩

HTTP 1.1 引入Accept-Encoding这个功能,它可以表明HTTP请求的内容被压缩过。GZIP是目前最普遍的一种压缩方式,现存的压缩比率最高的方法。使用GZIP压缩能减少文件传输时间,增强用户体验,节省了带宽。

但有些浏览器和代理服务器不支持,需要在头部加上Vary字段,这样哪些浏览器和代理服务器就能获得未压缩的数据了

图片和PDF不应当被压缩,它们本身提供了压缩方式,且效果很好。如果压缩PDF和图片,可能会越压越大

把CSS放在头部

如果有CSS的引用,把它放在头部(head标签内)。有一些浏览器为了减少重绘,它们会在CSS文件加载完成后渲染页面。如果样式文件在页面底部,那么这些浏览器会的呢过所有文件都加载完才去渲染页面。

很多浏览器会等所有样式文件加载完成后才渲染页面,所以应当对多个CSS文件进行合并

把JavaScript放到尾部

脚本hi阻止并行加载。当浏览器加载一个脚本时,它不会加载其他文件。如果脚本在头部,那它会阻止页面的渲染。

可以使用script标签上的defer属性告诉浏览器并行加载这个脚本,但有两个问题:

  1. 兼容性
  2. 用了defer属性的脚本,不能修改dom

避免使用CSS表达式

只有IE5~7支持CSS表达式。它的执行频率远超想象。只要页面一滚动,他就会重复执行,甚至鼠标移动的时候,他也会执行

移除不使用的CSS语句

目前绝大多数浏览器的渲染引擎都是通过遍历所有的CSS规则来寻找匹配的元素。所以如果有很多没用的CSS语句,那就会白白浪费样式引擎的事件。移除不使用的CSS语句还会减少CSS文件体积,让浏览器更快的加载它们,以节省带宽

可以通过之前说的合并方式编译生成CSS文件

对JavaScript和CSS进行代码压缩

这里不是指通过GZIP压缩,而是去掉不必要的非功能性字符,比如空白行、换行符、注释、分隔符。这样可以减少加载量,节省带宽。另外JS还可以吧变量名称换成极短的名字,进一步减少文件体积

减少重绘

减少重绘有很多方面:

  • 规定图片的宽和高
  • 不要使用表格布局
  • 定义字符集
  • 不要重组DOM

规定图片的宽和高

为每一个img元素规定宽和高,这样在浏览器进行布局时,会给元素留下空白。如果一开始不规定好img的宽高,浏览器只好猜了,猜错的概率很大。如果预留大小不对,只能通过重绘来纠正。所以通过定义宽高来避免这次重绘

不要使用表格布局

表格通常会导致页面重绘,浏览器是一行一行显示表格的,如果有一行的列宽和行高和之前的不一样,那么之前绘制好的也必须重绘了。如果用它来布局,就会有很大问题了。在加载的时候,有时会发现内容出现跳跃

定义字符集

大多数浏览器(除了IE6~8)会暂停页面渲染,直到他们找到字符集定义。不同的字符集意味着完全不同的渲染,显示效果也不同。所以在head中定义字符集来加快页面显示。就算不定义字符集也比把字符集定义放在页面后面要好。浏览器开始渲染后才发现字符集不同,又会重新进行渲染

不要重组DOM

重新排列DOM通常会引发浏览器重绘。增加或移除一个DOM元素都会造成浏览器重绘。而移动DOM元素更可怕,其相当于在一个地方删除,然后在其他地方添加。

如果有很多节点要添加,不要一次加一个,最好一次性添加所有。这个原则同样适用于样式的修改,不要在style上多次修改样式。最好将其转成class,一次性添加到元素上