只有10-20%的最终用户响应时间花在了下载HTML文档上。其余的80-90%时间花在了下载页面中的所有组件上。

规则1、减少HTTP请求
  1. 图片地图:将多个图片合并成一个,而后通过css定位显示不同的位置
  2. CSS Sprites:同上
  3. 内联图片
  4. 合并脚本和样式表
规则2、使用内容发布网络(CDN,Content Delivery Network)
规则3、添加Expires头
  1. Expires头:在这一日期/时间之后,响应将被认为是无效的
  2. Max-Age: 设置相对有效时间Cache-Control:max-age=100
  3. 空缓存VS完整缓存:尽可能将页面内容放入大缓存中
  4. 不仅仅是图片:图片应该使用缓存,但这一最佳实践不应该仅限于图片
  5. 修订文件名:为能够获取最新的文件,最有效的解决方案是修改其所有链接,这样,全新的请求将从原始服务器下载最新的内容。
规则4、压缩组件
  1. gzip:Accept-Encoding:gzip,deflate。gzip是目前最流行和最有效的压缩方法,是最理想的压缩方法
  2. 压缩内容:压缩脚本和样式表是非常值得的,同时还有XML和JSON在内的文本。图片和PDF不应该压缩,因为它们本来就已经被压缩了。
  3. 节省率:压缩通常能将响应的数据量减少将近70%
  4. gzip配置:不同的web服务器有不同的gzip配置方式,但大多支持gzip
  5. 代理缓存:Web服务器基于Accept-Encoding来检测是否对响应进行压缩。不管是否压缩过,浏览器都会基于响应中的其他HTTP头如Expires和Cache-Control来缓存响应。由于压缩的决定是基于Accept-Encoding请求头的,因此需要在服务器的Vary响应头中包含Accept-Encoding。
  6. 边缘情形:服务器和客户端的压缩对等性看似简单,但必须正确才行。无论是客户端还是服务器发生错误(发送压缩内容到不支持它的客户端、忘记将压缩内容声明为已经进行了gzip编码等),页面都会被破坏。错误并不会经常发生,但它们是必须考虑的边缘情形(Edge Case)。这种情况虽然可以通过浏览器白名单方式解决,但设置浏览器白名单的指令过于复杂,无法使用HTTP头进行编码。最佳做法是将User-Agent作为代理的另外一种判断标准添加到Vary头中Vary:Accept-Encoding,User-Agent
规则5、将样式表放在顶部

规则5对于加载页面所需的实际时间没有太多影响,它影响更多的是浏览器对这些组件顺序的反应。为避免当样式变化时重绘页面中的元素,浏览器会等待位于底部的样式表加载完成后才会呈现,这时浏览器会延迟任何可视化组件。实际上,用户感觉缓慢的页面反而是可视化组建加载得更快的页面。使用LINK标签将样式表放在文档的HEAD中可以解决该问题。

在使用样式表时,页面逐步呈现会被阻止,直到所有的样式表下载完成。将样式表移到文档head中,这样就能首先下载它们而不会阻止页面呈现。

规则6、将脚本放在底部
  1. 并行下载 对响应时间影响最大的是页面中组件的数量,如果一个Web页面平均地将其组件分别放在两个主机名下,整体响应时间将可以减少大约一半。但并行下载数量并不是越多越快,因为增加并行下载数量是有开销的,其优劣取决于带宽和cpu速度。
  2. 脚本阻塞下载 并行下载组件的优点是很明显的,然而,在下载脚本时并行下载实际上被禁用的。即使使用了不同的主机名,浏览器也不会启动其他的下载。其中一个原因是,脚本可能使用document.write来修改页面内容,因此浏览器会等待,已确保页面能够恰当地布局。另一个原因是为了保证脚本能够按照正确的顺序执行。

在使用脚本时,对于所有位于脚本以下的内容,逐步呈现都被阻塞了。将脚本放在页面越靠下的地方,意味着越多的内容能逐步地呈现。

规则7、避免css表达式
规则8、使用外部JavaScript和Css
  1. 纯碎而言,内联快一些
  2. 页面查看 每个用户产生的页面查看越少,内联JavaScript和Css的论据越强势。另一方面,如果普通用户能够产生很多的页面查看,浏览器很可能将(具有长久的Expires头的)外部文件放在其缓存中。
  3. 组件重用  如果你的网站中的每一个页面都使用了相同的JavaScript和Css,使用外部文件可以提高这些组件的重用率。在这种情况下使用外部文件更加具有优势,因为当用户在页面间浏览时,JavaScript和Css组件已经位于浏览器的缓存中了。
  4. 动态内联  如果主页服务器知道一个组件是否在浏览器的缓存中,它可以在内联和使用外部文件之间做出最佳选择。尽管服务器不能查看浏览器缓存中有些什么,但可以用cookies做指示器。如果cookie不存在,就内联了JavaScript和Css。如果cookie出现了,则有可能外部组件位于浏览器的缓存中,并使用了外部文件。
规则9、减少DNS查找

Internet是通过IP地址来查找服务器的。由于IP地址很难记忆,通常使用包含主机名的URL来取代它,但当浏览器发送其请求时,IP地址仍然是必需的。这就是Domain Name System(DNS) 所处的角色。DNS也有开销,通常浏览器查找一个给定的主机名的IP地址要花费20-120毫秒。响应时间依赖于DNS解析器(通常由你的ISP提供)、它所承担的请求压力、你与它之间的距离和你的带宽速度。

  1. DNS缓存  DNS查找可以被缓存起来提高性能。这种缓存可以发生在由你的ISP或局域网中的一台特殊的缓存服务器上,但这里探讨的是发生在独立用户的计算机上的DNS缓存。在用户请求了一个主机名之后,DNS信息会留在操作系统的DNS缓存中,之后对于该主机名的请求将无需进行过多的DNS查找,至少短时间内不需要。·
  2. 影响DNS缓存的因素 首先,服务器可以表明记录可以被缓存多久。查找返回的DNS记录包含了一个存活时间(Time-to-live,TTL)值。该值告诉客户端可以对该记录缓存多久,尽管操作系统缓存会考虑TTL值,但浏览器通常忽略该值,并设置它自己的时间限制。另外浏览器对缓存的DNS记录的数量也有限制,TTL设置值通常是1天。
  3. 减少DNS查找  当客户端的DNS缓存为空(浏览器和操作系统都是)时,DNS查找的数量与Web页面中唯一主机名的数量相等。这包括页面URL、图片、脚本文件、样式表、Flash对象等的主机名。减少唯一主机名的数量就可以就可以减少DNS查找的数量。
  4. 通过使用Keep-Alive和较少的域名来减少DNS查找
规则10、精简JavaScript

JavaScript作为一门解释型语言,是构建Web页面的首选。当以快速原型为基准开发用户界面时,解释语言要优于其他语言。

  1. 精简 是从代码中移除不必要的字符以减少其大小,进而改善加载时间的实践。在代码被精简后,所有的注释以及不必要的空白字符(空格、换行和制表符)都将被移除。对于JavaScript而言,这可以改善响应时间效率,因为需要下载的文件大小减少了。精简JavaScript最流行的工具是JSMin。
  2. 混淆  是可以应用在源代码上的另外一种优化方式。和精简一样,它也会移除注释和空白,同时它还会改写代码。作为改写的一部分,函数和变量的名字将被转换为更短的字符串,这时的代码更加精炼。但是会带来三个弊端:可能引入错误、增加调试难度、需要对JavaScript关键字标记
  3. 内联脚本  内联的JavaScript块也应该精简
规则11、避免重定向

重定向用于将用户从一个URL重新路由到另一个URL,种类有很多,常用的是301和302。它是损伤性能的,可以采用Alias、mod_rewirte、DirectorySlash和直接连接代码来避免重定向。

规则12、移除重复脚本
  1. 重复脚本--确有其事 开发一个网站需要极大数量的资源,除了核心团队要构建网站外,其他团队也会向页面贡献HTML代码。由于来自不同团队的很多人都要向页面中添加HTML,很容易想到相同的脚本可能会被添加多次
  2. 重复脚本伤害性能 引起不必要的HTTP请求和执行JavaScript所消耗的时间
规则13、配置ETag

实体标签(Entity Tag,ETag)是Web服务器和浏览器用于确认缓存组件的有效性的一种机制。减少呈现页面时所必需的HTTP请求的数量是加速用户体验的最佳方式。可以通过最大化浏览器缓存组件的能力来实现这一目标,但当网站被宿主在多于一台服务器上时,ETag头可能会阻碍缓存。

ETag带来的问题 ETag的问题在于,通常使用组件的某些属性来构造它,这些属性对于特定的、寄宿了网站的服务器来说是唯一的。当浏览器从一台服务器上获取了原始组件,之后又向另外一台不同的服务器发起条件GET请求时,ETag是不会匹配的----而对于使用服务器集群来处理请求的网站来说,这是很常见的一种情况。默认情况下,对于拥有多台服务器的网站,Apache和IIS向ETag中嵌入的数据都会大大地降低有效性验证的成功率。

解决该问题的两种方式:选择ETag的配置方式或者直接移除ETag

规则14、使Ajax可缓存

Ajax表示异步JavaScript和XML(Asynchronous JavaScript and XML),尽管今天除了XML有很多其他选择,最著名的是JSON。Ajax的目的是为了突破Web本质的开始--停止交互方式。向用户显示一个白屏然后重绘整个页面不是一种后的用户体验。而Ajax在UI和Web服务器之间插入了一层。这个Ajax层位于客户端,与Web服务器进行交互以获取请求的信息,并与表现层交互,仅更新哪些必要的组件。它将Web体验从“浏览页面”转变为“与应用程序进行交互”。

Ajax的一个明显优点是向用户提供了及时反馈,因为它异步地从后端Web服务器请求信息。但Ajax并不保证用户就不会一边玩弄自己的手指一边等着“异步JavaScript和XML”返回响应,记住“异步”并没有暗示“即时”,这一点很重要。用户是否需要等待的关键因素在于Ajax请求是被动的还是主动的。被动请求是为了将来使用而预先发起的。主动请求是基于用户当前的操作而发起的。

改善Ajax请求的最重要的方式就是使响应可缓存,前面第4、9、10、11、13原则也适用于此。

确保Ajax请求遵守性能指导,尤其应具有长久的Expires头。

 
 

<读书笔记>《高性能网站建设指南:前端工程师技能精髓》的更多相关文章

  1. 简单物联网:外网访问内网路由器下树莓派Flask服务器

    最近做一个小东西,大概过程就是想在教室,宿舍控制实验室的一些设备. 已经在树莓上搭了一个轻量的flask服务器,在实验室的路由器下,任何设备都是可以访问的:但是有一些限制条件,比如我想在宿舍控制我种花 ...

  2. 利用ssh反向代理以及autossh实现从外网连接内网服务器

    前言 最近遇到这样一个问题,我在实验室架设了一台服务器,给师弟或者小伙伴练习Linux用,然后平时在实验室这边直接连接是没有问题的,都是内网嘛.但是回到宿舍问题出来了,使用校园网的童鞋还是能连接上,使 ...

  3. 外网访问内网Docker容器

    外网访问内网Docker容器 本地安装了Docker容器,只能在局域网内访问,怎样从外网也能访问本地Docker容器? 本文将介绍具体的实现步骤. 1. 准备工作 1.1 安装并启动Docker容器 ...

  4. 外网访问内网SpringBoot

    外网访问内网SpringBoot 本地安装了SpringBoot,只能在局域网内访问,怎样从外网也能访问本地SpringBoot? 本文将介绍具体的实现步骤. 1. 准备工作 1.1 安装Java 1 ...

  5. 外网访问内网Elasticsearch WEB

    外网访问内网Elasticsearch WEB 本地安装了Elasticsearch,只能在局域网内访问其WEB,怎样从外网也能访问本地Elasticsearch? 本文将介绍具体的实现步骤. 1. ...

  6. 怎样从外网访问内网Rails

    外网访问内网Rails 本地安装了Rails,只能在局域网内访问,怎样从外网也能访问本地Rails? 本文将介绍具体的实现步骤. 1. 准备工作 1.1 安装并启动Rails 默认安装的Rails端口 ...

  7. 怎样从外网访问内网Memcached数据库

    外网访问内网Memcached数据库 本地安装了Memcached数据库,只能在局域网内访问,怎样从外网也能访问本地Memcached数据库? 本文将介绍具体的实现步骤. 1. 准备工作 1.1 安装 ...

  8. 怎样从外网访问内网CouchDB数据库

    外网访问内网CouchDB数据库 本地安装了CouchDB数据库,只能在局域网内访问,怎样从外网也能访问本地CouchDB数据库? 本文将介绍具体的实现步骤. 1. 准备工作 1.1 安装并启动Cou ...

  9. 怎样从外网访问内网DB2数据库

    外网访问内网DB2数据库 本地安装了DB2数据库,只能在局域网内访问,怎样从外网也能访问本地DB2数据库? 本文将介绍具体的实现步骤. 1. 准备工作 1.1 安装并启动DB2数据库 默认安装的DB2 ...

  10. 怎样从外网访问内网OpenLDAP数据库

    外网访问内网OpenLDAP数据库 本地安装了OpenLDAP数据库,只能在局域网内访问,怎样从外网也能访问本地OpenLDAP数据库? 本文将介绍具体的实现步骤. 1. 准备工作 1.1 安装并启动 ...

随机推荐

  1. Python笔记(四)_字符串的方法

    字符串的方法 []表示该参数时可选的,start和end参数表示范围 count(sub[, start[, end]]) 返回sub在字符串里边出现的次数 find(sub[, start[, en ...

  2. 爬虫(一)—— 请求库(一)requests请求库

    目录 requests请求库 爬虫:爬取.解析.存储 一.请求 二.响应 三.简单爬虫 四.requests高级用法 五.session方法(建议使用) 六.selenium模块 requests请求 ...

  3. websocket 服务搭建

    链接过程 前端 1.CREATED WEBSOCKE 2.ONOPEN 3.ONMESSAGE 服务端 1.收到request 2.给客户端发送消息,生成id //msg { type: " ...

  4. sublime中使用插件anaconda而在代码中出现方框

    这个标志是说不符合PEP8标准,比如使用了Tab做缩进:一行过长等问题. 可以在可以在 Sublime > Preferences > Package Settings > Anac ...

  5. linux随笔-04

    管道符.重定向与环境变量&vim编辑器  输入输出重定向 标准输入重定向(STDIN,文件描述符为0):默认从键盘输入,也可从其他文件或命令中输入. 标准输出重定向(STDOUT,文件描述符为 ...

  6. 转载:java面试题(一)

    1.面向对象的特征有哪些方面? 答:面向对象的特征主要有以下几个方面: - 抽象:抽象是将一类对象的共同特征总结出来构造类的过程,包括数据抽象和行为抽象两方面.抽象只关注对象有哪些属性和行为,并不关注 ...

  7. Java 代码规范,你应该知道的一些工具和用法(转)

    转自:http://yifeng.studio/2017/06/30/coding-with-code-style/ Java 代码规范,你应该知道的一些工具和用法 2017-06-30 从事编程这个 ...

  8. Django Rest框架 流程详解

    什么是Restful REST与技术无关,代表的是一种软件架构风格,REST是Representational State Transfer的简称,中文翻译为“表征状态转移” REST从资源的角度类审 ...

  9. Java集合框架的基础接口有哪些?

    Collection为集合层级的根接口.一个集合代表一组对象,这些对象即为它的元素.Java平台不提供这个接口任何直接的实现. Set是一个不能包含重复元素的集合.这个接口对数学集合抽象进行建模,被用 ...

  10. spring mvc 整合 druid

    环境: ubuntu eclipse maven 一. pom.xml 加入druid 依赖 <!-- https://mvnrepository.com/artifact/com.alibab ...