《高性能HTML5》优化笔记

目录

  • 什么是高性能
  • 开发原则
  • 性能准则

    什么是高性能
       当谈到“高性能”时,很多人想到的是页面加载时间,这是对Web开发性能的传统定义。其实性能并不仅仅是指页面加载,它还包括以下几个方面。
       页面加载时间
       浏览器性能
       网络性能
       开发效率

 

     页面加载时间
           页面加载时间过慢会使用户离开网站。
     浏览器性能
          现代浏览器都非常重视对JavaScript引擎、CSS动画处理等方面的性能优化和加速,如果不了解这些新特性,就很可能错过浏览器提供的便利功能。

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

     开发效率
          大多数工程师都不喜欢做重复的事情,因此我们将讨论一种能在各种不同环境中复用的技术。它的关键是建立简洁灵活的HTML5结构,然后针对环境使用相应的CSS,使同样的结构在不同的环境中都能获得最佳的表现。还有就是如何解决命名冲突的问题,它在团队合作开发中发挥着重要的作用。代码重用节省开发时间,减少代码量,能有效地避免工程师迫于时间压力而写出有隐患的代码---别想着以后有时间再回来优化代码这样的事情了,事实证明,根本没有回头的机会。
 
   开发原则

       编写符合当代浏览器性能的代码
       用CSS来布局
       使用渐进式增强的方法
       各司其职

       编写符合当代浏览器性能的代码
       如果你想当一个性能高手,那么必须理解浏览器的工作原理,哪怕是个大概。
首先HTML被解析为一棵DOM树,也叫作文档对象模型,这就是为什么浏览器要在第一时间下载页面的HTML内容的原因之一,另一个原因是HTML包含了展示页面所需的其他所有资源文件(样式、脚本、图片)。然后第二棵树是DOM树和CSS样式表结合起来构成的渲染树,其中CSS样式表不仅包括你自己定义的也包括浏览器默认的。根据这棵渲染树,浏览器就开始显示了,把你写的元素“画”到屏幕上,从左上开始到右下结束。
      你可以从以下两方面改进性能:
      减少HTML中元素数量;让HTML做内容的事情,让CSS做展现的事情,这样做不仅可以提高客户端的性能,同样可使得页面更易于维护从而提高开发效率。
       减少重绘
       对于提高性能来说,减少HTML元素的数量确实很管用,但减少浏览器重绘次数的效果会更加明显。在元素完成绘制之后动态更改DOM结构和CSS样式都会引发浏览器重绘。性能的损耗直接取决于动态改动的范围。现代的高级浏览器只会重绘必要的部分,如果只是改动一个元素的背景颜色,那就只引发这一个元素的重绘,但如果是改动一个元素的位置或是增加一个新的元素,那就会引发大量的重绘,因为它影响了所有的兄弟元素。
      在动态改动DOM和CSS样式时有两点是需要考虑的。第一点是要改动的元素在DOM树中的深度,越深则改动就越独立,对其他节点的影响越少,所以能改多深就改多深。第二点也是更重要的一点,如果要对DOM有多次操作,尽量合并到一次做完而不是分成一次一次地去做。正因为这个原因,CSS就成了我们改动DOM时最好的伙伴。
  
   用CSS来布局,处理边界
      浏览器渲染页面其实是在渲染一系列的“盒子”,而且这些盒子里还包含了许多其他“盒子”。所以我们说浏览器的天然渲染模型是“很多盒子套很多盒子”,知道这一点,会让我们更明智地布局页面。

完美实现“盒子套盒子”的方法就是把一个或一大组元素都包在一个盒子里。相反,不好的方式就是把一些元素丢到盒子的外面。


   渐进式增强
      首先有一个基本的设计是可以兼容所有浏览器的,然后再为较新的或更新的浏览器做加强的显示或功能(渐进式)。我们先有一个基本的CSS/HTML页面,它是兼容所有浏览器的,然后我们家就有机会为支持HTML5的浏览器添加HTML5的特性。

   各司其职
      CSS、HTML、JavaScript分离。尽可能一切让CSS来完成交互,因为浏览器天生就可以处理它们。

    性能准则

      以下是我们所列的性能准则,根据对页面加载时间的影响强弱排序
      减少HTTP请求
      使用CDN加速
      避免空的SRC或HREF属性值
      增加过期头
      启用GZIP压缩
      把CSS放到头部
      把JavaScript放到尾部
      避免使用CSS表达式
      删除不使用的CSS语句
      对JavaScript、CSS进行代码压缩
      减少重绘

   减少HTTP请求
      理解并行连接
      我们发现减少HTTP请求是经常被开发人员所忽略的一件事情,虽然它是对前端性能影响最明显的一个方面。大概因为开发人员无法控制用户的浏览器,但是他们可以控制自己的服务器,自己的数据库,自己的代码,大家都倾向于关注自己可以掌握的事情。这无可厚非,但是不考虑浏览器的工作原理,就会有大问题。
开发人员往往没有考虑到浏览器端的限制,比如有多少资源可以在同一时间加载。HTTP1.1协议很明确地限制了单个用户不能在同一时间保持2个以上的连接。最近几年,大部分浏览器都突破了这个限制。很多浏览器现在支持4个并行的连接,有一少部分已经支持到了6个。IE8会根据用户的带宽来决定连接的数量。2个对应拨号连接,4个对应宽带连接。

      合并资源文件
      并行连接的讨论可以得出一个结论,大一些的文件比小文件好。对于很多开发人员来说,这个结论太诡异了。可是事实就是这样,在很长的一段时间里,我们忙于把资源文件搞到尽可能小。还记得用56KB的Modern拨号上网的时候,看着页面上图片的加载进度就像是上网加载的某种进度条一样。这样的时代一去不复返了,绝大部分人现在已经有了非常快的网速。基于现在的网络环境,基本上没有任何文件可以困扰浏览器了。所以输了少体积大的文件要比数量多体积小的文件加载更快。回到火车调度的例子,如果你能把更多的车皮挂到一个火车头上,那就可以运送更多的货物。在文件传输和并行连接上也是一样的道理。
      此外,每个HTTP请求在时间和带宽上至少会产生一些开销。因此,如果你可以合并你的资源,减少HTTP请求,在展示页面的时候,就为你的用户赢得了更多页面渲染的时间。

我们要把内容合并成尽可能少的文件。可能的话,把所有的CSS文件合并成一个单独的文件,把所有的JavaScript文件合并成一个单独的文件。如果有多个页面的相互作用,这样合并可能会有问题,不过这个问题我们可以通过编译脚本解决。需要在JS文件和CSS文件改动的时候运行这个脚本。它会自动检测合并相关的文件,为每一个页面产生一个独立的文件。动态内容的网站也可以用这个脚本,如果它们有共用的CSS和JS文件。

      还有一个办法是在上线发布的时候才去合并这些文件,这种方式不会比上一种更快,但是如果你的网站很复杂,最好还是在开发环境保持分割文件模块的方式。

      最后,另一个策略是,抽出所有网页共同的CSS文件,然后在每一页上引用它,之后再为每一页提供只针对该页面的CSS文件。

   使用图片精灵(雪碧图)
      大多数网站会做跨页面的图片精灵。就是把整个网站所有共用的小图片都合成一张图,这是一种有效减少HTTP请求的方法。

   使用CDN加速(内容分发系统)
      CDN是一个拥有很多很多服务器、经过策略性部署的、可以覆盖全球的网络系统。它会从最近的一个节点取数据给你。但是这些节点所缓存的文件是不易改动的,所以你最好在CDN上存放静态文件,如图片、字体、JavaScript库等。把这些静态的资源文件放置在离用户最近的地方,的确可以在很大程度上加速性能。不过动态数据的处理还是应该集中在一个地方。即便是大公司,跨地域同步数据库也是一件很棘手很不知道的事。时序问题是让网络工程师最头痛的。所以,大多数互联网公司都把购买、登录等数据相关的事务放到一个地方处理。
     使用CDN的窍门之一是在文件引用时加一个时间戳,这样就有一个唯一的文件引用,而不用担心缓存在CDN服务器上的过期文件会对用户产生影响。每次改动文件时就更新一下时间戳。如果只是开发一个很小的网站,这种做法很烦人。所以必须要自行决定CDN是否适合自己项目。如果网站只是面向当地人或属于地域独立的,那么使用CDN或许得不偿失。

   避免空的SRC和Href属性值

      在页面加载的过程中,一个有着空src属性的img元素被Js动态的赋值。在脚本执行之前元素就被浏览器渲染了。尤其是当把脚本放到文档最后的时候。所以浏览器依然会发起一个HTTP请求,虽然它是一个空值。
同样的问题发生在href上。所以<a href="javascript:;">Trigger</a>可以解决这个问题;
     <a href="#nogo" id="triggerName">Trigger</a>
     <script>
          $('#triggerName').click(function(e){
               e.preventDefault();
          });
     </script>


    增加过期头
        你应该在所有静态文件上加上过期头,过期日期定的非常遥远,这样浏览器就会缓存静态文件。把过期日期设定成很遥远也会造成麻烦,当你想让老用户得到最新的更新而不是缓存数据时,就必须改文件名以达到这种目的,其中一个办法就是在文件名上加入时间戳。比如把一个通用的CSS取名为base20150101.css。把时间戳加在文件名上的一个好处是你能够很容易地从你的代码管理工具的日志中看到你的修改记录。


    启用GZIP压缩
        根据雅虎关于性能加速的说法,GZIP减小了70%的响应大小。应该压缩一切文字类的内容。这意味着需要压缩HTML、css、脚本、XML、JSON和其他一切文本类的内容。图片和PDF文件是不应该压缩的,因为它们本身就是可压缩的格式。如果发现了根本没有压缩过的图片和PDF,那应该去修改这个文件本身,而不是去选择在服务器上压缩这一类文件。
        另一个不能压缩图片和PDF文件的原因是,它们会越压越大。压缩引擎不仅不会让文件变小,还会加入一些自己的控制代码从而让它变大。


    把CSS 放在头部

    把JavaScript文件放在底部
        脚本会阻止并行加载。

    避免使用CSS表达式
         也就在IE5-7有,其他浏览器未支持。

    移除不使用的CSS语句
        据我所知,目前绝大多数浏览器的样式引擎都是通过遍历所有的CSS规则来寻找匹配的元素,所以没用的CSS就可以去掉了。


    对Js和css文件进行代码压缩


    减少重绘
        规定图片的宽高。当浏览器在生成布局树的时候,它会给每一个元素留一个区域。如果不在一开始规定好img宽高,那浏览器只好猜了,而且猜错的概率很大。当它把图片下载完后发现猜错了,它预留的区域大小不对,那只能重绘来纠正这个错误。可以通过定义宽高避免这次重绘。

    不要用表格布局
        只需要显示表格数据时使用表格。如果有一行的列宽或行高和之前的不一样那之前绘好的行业必须重新绘制。


    定义字符集
        大多数浏览器(除了IE6-8)都会暂停页面渲染直到它们找到字符集的定义。它们这么做是因为字符集是渲染页面的一个重要因素。不同的字符集可能意味着完全不同的渲染,显示的效果也是不同的。所以,你可以通过在head标签里定义字符集来进一步加快你的页面显示。
        比不定义字符集还要可怕的是把字符集的定义放到页面后面,以至于浏览器已经开始渲染页面了才发现你定义的字符集,除非你定义的和浏览器默认的是一致的,否则它会抛弃当前的渲染,并以你定义的字符集重新开始渲染页面。

    不要重组DOM
重新排列DOM通常都会引发浏览器重绘。同样原则也适用于动态的样式更改。不要一次一次去更改元素的内联样式,最好用CSS做一个CLASS,然后一次性都改了,可避免多次重绘。对于DOM节点,能不操作最好,如果一定要操作DOM,那就使用组装好后一次性插入。

相关推荐