开源中国

我们不支持 IE 10 及以下版本浏览器

It appears you’re using an unsupported browser

为了获得更好的浏览体验,我们强烈建议您使用较新版本的 Chrome、 Firefox、 Safari 等,或者升级到最新版本的IE浏览器。 如果您使用的是 IE 11 或以上版本,请关闭“兼容性视图”。
给网页设计师和前端开发者看的前端性能优化 - 技术翻译 - 开源中国社区

给网页设计师和前端开发者看的前端性能优化 【已翻译100%】

Lax 推荐于 5年前 (共 24 段, 翻译完成于 04-16) 评论 32
收藏  
495
推荐标签: 待读

如果不是不可能,你也很难拒绝承认性能目前已是任何正规网站项目的最关键方面之一,无论它是一个小型的网站组合,一个移动优先的web应用,一直到一个大规模的商业项目。研究,论文和个人体验都告诉我们快速是最好的。

性能不仅仅是非常重要,它也相当的有趣,而且这也是我越来越投入的事,不仅在工作方面(我一直在烦我们的首席性能工程师),也在项目与CSS魔法网站方面(我一直在烦Andy Davies)。

在这篇长文章中,我将分享收获,关于快速,简单且非常有趣的性能知识的点点滴滴,以便使你的行为可以像一个初级的网页设计师和前端开发者;希望对任何想开始学习性能的人,这篇文章可以成为一个正规的介绍,并使它们的前端变得超快。这些技巧是你能非常容易实现的。它只需要一点小技巧,以及一些浏览器怎样工作的基础知识,你就能开始玩转系统了!

super0555
 翻译得不错哦!

这篇长帖子不会讲到模糊图像的加载和数据处理,取而代之的是有关理论与第一手的性能方面的技术资料,这些技术是我通过阅读,观察,搜集和整理获得的(我花费了许多时间沉浸于CSS魔法的瀑布图)。我也会链接到其它相似话题的文章,以便帮助强化一些关键要点。享受吧!

注意 本文需要预先知晓一些基础的性能知识,如果有任何你不熟悉的就Google搜索一下好了!

  1. 基础
    1. 顶部的Styles,底部的scripts
    2. 更少的请求
    3. 尽可能并行
  2. HTTP 请求与 DNS查询
    1. DNS 预取
  3. 资源预取
  4. CSS与性能
  5. 压缩与简化
  6. 优化图像
    1. 精灵
    2. 视网膜图像
    3. 渐进的 JPGs
    4. 完全不用图片
  7. 进一步阅读



super0555
 翻译得不错哦!

基础知识

关于性能,有一些知识在所有的设计师和前端开发者中广为传播。例如,尽可能少的请求,优化图片,把样式表(stylesheets)放在<head>, 把JS放在</body>之前, 最小化(minifying) JS 和 CSS 等等。这些基础知识已经被用来加快用户响应了,但还有更多更多需要学习。

虽然在我们每天的工作生活中,浏览器给我们制造麻烦,使我们头疼,但请记住,他们也是很聪明的; 它们为我们做了很多性能优化工作, 所以大量的性能调优知识不但要知道浏览器在哪里给我们做了优化,还要知道怎么更好的挖掘它们。大量性能调优诀窍只是理解,利用和操纵浏览器已经替我们做好的优化工作。

ljb_iss
 翻译得不错哦!

顶部的Styles, 底部的scripts

这真的是一条基本规则,每个人都能非常容易的在大多数时间遵守,但为什么它重要?简短的说:

  • CSS 块渲染, 因此你需要立即处理它(即在文档的顶部,在你的<head>之中)。
  • JS 块下载, 因此你需要最后处理它们,以确保它们没有耽误页面中任何其它东西。

CSS块渲染是因为浏览器总是试图渐进式的渲染页面;它们想在元素到达的时候顺序的渲染它。如果style在距离很远的页面下部,浏览器在获得它之前没有办法渲染那个CSS。因为这个原因,如果浏览器在渲染文档过程中,改变了之前渲染的东西,它们可以避免style的重绘。浏览器在它获得所有需要的style信息之前不会渲染页面,如果你将style放在文档底部,你就是在使浏览器等待,阻塞了渲染。

super0555
 翻译得不错哦!

所以,只要你将CSS放在页面的顶部,那么浏览器就可以立刻开始渲染。

JavaScript块下载是由于好几个原因(这又是浏览器聪明之处),但首先我们需要知道浏览器里的资源下载是如何实际发生的;简单的说,浏览器会从一个单一的域名并行的尽可能多的下载资源。它从越多的域名下载,就能在一瞬间并行的获得更多的资源。

JavaScript中断了这个过程,阻塞了从任何一个域名的并行的下载,因为:

  • 被调用的脚本可能改变页面,即浏览器在继续别的事情以前,将不得不处理它。因此为了处理那个不测事件,浏览器停止了任何其它东西的下载,以便集中精力关注于它。
  • 脚本正常工作经常需要依照一定的顺序加载,例如,要在加载一个插件之前加载jQuery。浏览器阻止了JavaScript的并行下载,因此它不会同时下载jQuery和你的插件;很显然如果你同时并行下载二者,你的插件会在jQuery之前到达。
super0555
 翻译得不错哦!

所以,由于浏览器在获取JavaScript的时候停止了所有其他下载,将你的JavaScript脚本放在文档中尽可能晚加载的地方是一个好主意。我相信你们都看到过页面中的空白片段,在那里第三方的JS脚本被花时间加载,并且它还阻止了页面其他资源的获取和渲染;这就是JavaScript的阻塞在作用了。

但是显然,现代浏览器还是变得聪明了。我将给你一个Andy Davies寄给我的电子邮件的摘录,因为他解释的比我清楚:

现代浏览器将并行下载JS,只有在脚本被执行的时候阻塞渲染(显然脚本必须也被下载了)。

脚本下载常常被浏览器的预加载器所完成。

当浏览器页面渲染被阻塞,即等待CSS,或JS被执行,预分析器将扫描页面剩余部分,寻找它能下载的资源。

有些浏览器如 Chrome, 将分先后下载资源,例如,如果脚本与图片同时在等待下载,它将先下载脚本。

漂亮的内容!

所以,要使页面被尽可能快的渲染,将styles放在顶部。为了阻止JS的阻塞影响到渲染,将scripts放在底部。

super0555
 翻译得不错哦!

更少的请求

另一个明显而基本的性能优化方法是少下载。页面需要的每一个资源就是一次额外的HTTP请求;浏览器不得不停下来去获取每一个用于渲染页面所需的资源。每一次HTTP请求都可能引发DNS查询,重定向,404,等等。每一次HTTP请求,无论为了样式表,图片,web字体,JS文件还是其它你能想到的,都可能是一次非常昂贵的操作。尽量减少这些请求是你可以做的最快的优化方法中的一种.

再谈到浏览器和并行;大多数浏览器一次只从每个引用的域下载一些资源,而JS会阻塞这些下载。所以,你做的每一个HTTP请求都应该仔细考虑,而不是随便随便做的。

ljb_iss
 翻译得不错哦!

尽可能并行


为了让浏览器能并行的下载更多资源,你可以由不同的域名提供服务。如果说,浏览器只能一次从一个域名获取两个资源,那么由两个域名提供服务意味着它可以一次性获取四个资源;三个域名意味着六个并行下载。

许多网站有静态/资源 域名;你可以发现, Twitter, 用 si0.twimg.com 来做静态资源:

<link rel="stylesheet" href="https://si0.twimg.com/a/1358386289/t1/css/t1_core.bundle.css" type="text/css" media="screen">

Facebook 用fbstatic-a.akamaihd.net:

<link rel="stylesheet" href="https://fbstatic-a.akamaihd.net/rsrc.php/v2/yi/r/76f893pcD3j.css">

通过这些静态的资源域名, Twitter与Facebook能提供更多的并行资源服务;来自twitter.com和si0.twimg.com的资源可以协作方式下载。这真的是使你的页面上获得更多并发下载的简单方法,如果再加上实际的CDN技术就会更好,CDN技术通过从一个更加合适的物理位置提供资源服务的方法来减少延迟。

这全部都很好,但后面我们将讨论在特定环境下,怎样从子域名提供服务却会实际上对性能有害。

因此,现在有了我们关于性能的基础知识:

  • 将样式表放在文档的顶部
  • 将JavaScript放在底部(可能的地方)
  • 尽可能减少HTTP请求
  • 从多个域名提供资源服务能增加浏览器并行下载的资源数量。
super0555
 翻译得不错哦!

HTTP 请求与 DNS 查询

每当你从任何域名请求一个资源,会发出一个带有相关头部,被访问资源的 HTTP请求,并且会返回一个响应。这是对该过程的一个极端简化,但它基本就是事实上你需要知道的。这是一个HTTP请求,而且所有涉及的资源都从属于这个往返的旅行。当提到前端性能,这些请求正是主要的瓶颈所在,因为如我们谈到的,浏览器受限于有多少请求可以并行发生。这也是为什么我们经常要使用子域名;以便允许这些请求在数个域名上发生,允许同时发生多得多数量的请求。

然而关于这还有个问题,DNS查询。每次(从一个空缓存)一个新的域名被引用,HTTP请求会受制于一个耗时的DNS查询(某个介于20到120毫秒之间的值),在DNS查询中,发出的请求会查询资源实际存在的地点;互联网通过IP地址被绑定在一起,这些地址由DNS管理的主机名引用。

super0555
 翻译得不错哦!

如果每个引用的新域名具有DNS查询的前端代价,你必须确保这个代价确实是值得的。如果是一个小网站(例如像CSS魔法),那么由子域名提供资源可能并不值得;相比执行多个域名的DNS查询并将其并行化来说,从一个域名非并行的获取若干资源,浏览器可能更快。

如果你或许有一打资源,你可能会考虑从一个子域名提供它们的资源服务;为了更好的并行化那许多资源,额外的DNS查询可能是值得的。如果说你有40个资源,可能将那些资源切分到两个子域名是值得的;为了由总数为三个的域名提供你的网站服务,两个额外的DNS查询会是值得的。

DNS查询代价很高,因此你需要决定什么才是对你的网站更合适的;承担查询的消耗或者只是由一个域名提供所有服务。

很重要的需要记得的是,比方说一旦HTML被请求于foo.com,对那个主机的DNS查询就立即发生了,所以后续的任何对foo.com的请求不再受制于DNS查询。

super0555
 翻译得不错哦!
本文中的所有译文仅用于学习和交流目的,转载请务必注明文章译者、出处、和本文链接
我们的翻译工作遵照 CC 协议,如果我们的工作有侵犯到您的权益,请及时联系我们
评论(32)
Ctrl/CMD+Enter

好文章,前排支持!
不错
好文章
好文章.
好文章,顶一个
技巧都知道,这里讲解了原理,挺有意思的文章,老外的文章都很严谨
不错,,值得学习
强文,必须支持一下
参考
好文章,学习了
前排留名
mark
学习了。谢谢Lz!
好文章吖!必须顶!
不错!
多谢楼主,又学到了
学习了,收藏
很好,学习了
好文,收藏了
不错的文章
顶部