前端性能优化最佳实践本文主要考量客户端性能、服务器端和网络性能,内容框架来自 Yahoo Developer Netwo -天下标王
稀土掘金 稀土掘金
MrDream24
7,773 阅读13分钟
原文链接: Yahoo Developer Network,包含 7 个类别共 35 条前端性能优化最佳实践,在此基础上补充了一些相关或者更符合主流技术的内容。

同时,建议关注及时更新的 Google 性能优化指南。

目录:

  • 页面内容
    • 减少 HTTP 请求数
    • 减少 DNS 查询
    • 避免重定向
    • 缓存 Ajax 请求
    • 延迟加载
    • 预先加载
    • 减少 DOM 元素数量
    • 划分内容到不同域名
    • 尽量减少 iframe 使用
    • 避免 404 错误
  • 服务器
    • 使用 CDN
    • 添加 Expires 或 Cache-Control 响应头
    • 启用 Gzip
    • 配置 Etag
    • 尽早输出缓冲
    • Ajax 请求使用 GET 方法
    • 避免图片 src 为空
  • Cookie
    • 减少 Cookie 大小
    • 静态资源使用无 Cookie 域名
  • CSS
    • 把样式表放在 <head>
    • 不要使用 CSS 表达式
    • 使用 <link> 替代 @import
    • 不要使用 filter
  • JavaScript
    • 把脚本放在页面底部
    • 使用外部 JavaScript 和 CSS
    • 压缩 JavaScript 和 CSS
    • 移除重复脚本
    • 减少 DOM 操作
    • 使用高效的事件处理
  • 图片
    • 优化图片
    • 优化 CSS Sprite
    • 不要在 HTML 中缩放图片
    • 使用体积小、可缓存的 favicon.ico
  • 移动端
    • 保持单个文件小于 25 KB
    • 打包内容为分段(multipart)文档

页面内容

减少 HTTP 请求数

Web 前端 80% 的响应时间花在图片、样式、脚本等资源下载上。浏览器对每个域名的连接数是有限制的,减少请求次数是缩短响应时间的关键。

通过简洁的设计减少页面所需资源,进而减少 HTTP 请求,这是最直接的方式,前提是你的 Boss、设计师同事不打死你。所以,还是另辟蹊径吧:

  • 合并 JavaScript、CSS 等文件;
    • 服务器端(CDN)自动合并
    • 基于 Node.js 的文件合并工具一抓一大把
  • 使用CSS Sprite:将背景图片合并成一个文件,通过background-imagebackground-position 控制显示;

    • Sprite Cow
    • Spritebox

      逐步被 Icon Font 和 SVG Sprite 取代。

  • Image Map:合并图片,然后使用坐标映射不同的区域(演示)。

    缺点:仅适用于相连的图片;设置坐标过程乏味且易出错;可访性问题。不推荐使用这种过时的技术。

  • Inline Image:使用 Data URI scheme 将图片嵌入 HTML 或者 CSS 中。

    会增加文件大小,也可能产生浏览器兼容及其他性能问题(有待整理补充)。

    未来的趋势是使用内嵌 SVG。

减少 DNS 查询

用户输入 URL 以后,浏览器首先要查询域名(hostname)对应服务器的 IP 地址,一般需要耗费 20-120 毫秒 时间。DNS 查询完成之前,浏览器无法从服务器下载任何数据。

基于性能考虑,ISP、局域网、操作系统、浏览器都会有相应的 DNS 缓存机制。

  • IE 缓存 30 分钟,可以通过注册表中 DnsCacheTimeout 项设置;
  • Firefox 混存 1 分钟,通过 network.dnsCacheExpiration 配置;
  • (TODO:补充其他浏览器缓存信息)

首次访问、没有相应的 DNS 缓存时,域名越多,查询时间越长。所以应尽量减少域名数量。但基于并行下载考虑,把资源分布到 2 个域名上(最多不超过 4 个)。这是减少 DNS 查询同时保证并行下载的折衷方案。

避免重定向

HTTP 重定向通过 301/302 状态码实现。

HTTP/1.1 301 Moved Permanently  
Location: http://example.com/newuri  
Content-Type: text/html  

客户端收到服务器的重定向响应后,会根据响应头中 Location 的地址再次发送请求。重定向会影响用户体验,尤其是多次重定向时,用户在一段时间内看不到任何内容,只看到浏览器进度条一直在刷新。

有时重定向无法避免,在糟糕也比抛出 404 好。虽然通过 HTML meta refresh 和 JavaScript 也能实现,但首选 HTTP 3xx 跳转,以保证浏览器「后退」功能正常工作(也利于 SEO)。

  • 最浪费的重定向经常发生、而且很容易被忽略:URL 末尾应该添加 / 但未添加。比如,访问 http://astrology.yahoo.com/astrology 将被 301 重定向到 http://astrology.yahoo.com/astrology/(注意末尾的 /)。如果使用 Apache,可以通过 Aliasmod_rewriteDirectorySlash 解决这个问题。
  • 网站域名变更:CNAME 结合 Aliasmod_rewrite 或者其他服务器类似功能实现跳转。

缓存 Ajax 请求

Ajax 可以提高用户体验。但「异步」不意味着「及时」,优化 Ajax 响应速度提高性能仍是需要关注的主题。

最重要的的优化方式是缓存响应结果,详见 添加 Expires 或 Cache-Control 响应头。

以下规则也关乎 Ajax 响应速度:

  • 启用 Gzip
  • 减少 DNS 查询
  • 压缩 JavaScript 和 CSS
  • 避免重定向
  • 配置 Etag

延迟加载

页面初始加载时哪些内容是绝对必需的?不在答案之列的资源都可以延迟加载。比如:

  • 非首屏使用的数据、样式、脚本、图片等;
  • 用户交互时才会显示的内容。

遵循「渐进增强」理念开发的网站:JavaScript 用于增强用用户体验,但没有(不支持) JavaScript 也能正常工作,完全可以延迟加载 JavaScript。

预先加载

预先加载利用浏览器空闲时间请求将来要使用的资源,以便用户访问下一页面时更快地响应。

  • 无条件预先加载:页面加载完成(load)后,马上获取其他资源。以 google.com 为例,首页加载完成后会立即下载一个 Sprite 图片,此图首页不需要,但是搜索结果页要用到。
  • 有条件预先加载:根据用户行为预判用户去向,预载相关资源。比如 search.yahoo.com 开始输入时会有额外的资源加载。

    Chrome 等浏览器的地址栏也有类似的机制。

  • 有「阴谋」的预先加载:页面即将上线新版前预先加载新版内容。网站改版后由于缓存、使用习惯等原因,会有旧版的网站更快更流畅的反馈。 为缓解这一问题,在新版上线之前,旧版可以利用空闲提前加载一些新版的资源缓存到客户端,以便新版正式上线后更快的载入(好一个「心机猿」:scream:)。

TODO: Prefetch 相关细节

  • Resource Hints Spec

减少 DOM 元素数量

复杂的页面不仅下载的字节更多,JavaScript DOM 操作也更慢。例如,同是添加一个事件处理器,500 个元素和 5000 个元素的页面速度上会有很大区别。

从以下几个角度考虑移除不必要的标记:

  • 是否还在使用表格布局?
  • 塞进去更多的
    仅为了处理布局问题?也许有更好、更语义化的标记。
  • 能通过伪元素实现的功能,就没必要添加额外元素,如清除浮动。

浏览器控制台中输入以下代码可以计算出页面中有多少 DOM 元素:

document.getElementsByTagName('*').length;  

对比标记良好的的网站,看看差距是多少。

为什么不使用表格布局?

  • 更多的标签,增加文件大小;
  • 不易维护,无法适应响应式设计;
  • 性能考量,默认的表格布局算法会产生大量重绘(参见表格布局算法)。

划分内容到不同域名

浏览器一般会限制每个域的并行线程(一般为 6 个,甚至更少),使用不同的域名可以最大化下载线程,但注意保持在 2-4 个域名内,以避免 DNS 查询损耗。

例如,动态内容放在 csspod.com 上,静态资源放在 static.csspod.com 上。这样还可以禁用静态资源域下的 Cookie,减少数据传输,详见 Cookie 优化。

更多信息参考 Maximizing Parallel Downloads in the Carpool Lane

尽量减少 iframe 使用

使用 iframe 可以在页面中嵌入 HTML 文档,但有利有弊。

优点

  • 可以用来加载速度较慢的第三方资源,如广告、徽章;
  • 可用作安全沙箱;
  • 可以并行下载脚本。

缺点

  • 加载代价昂贵,即使是空的页面;
  • 阻塞页面 load 事件触发;

    Iframe 完全加载以后,父页面才会触发 load 事件。 Safari、Chrome 中通过 JavaScript 动态设置 iframe src 可以避免这个问题。

  • 缺乏语义。

避免 404 错误

HTTP 请求很昂贵,返回无效的响应(如 404 未找到)完全没必要,降低用户体验而且毫无益处。

一些网站设计很酷炫、有提示信息的 404 页面,有助于提高用户体验,但还是浪费服务器资源。尤其糟糕的是外部脚本返回 404,不仅阻塞其他资源下载,浏览器还会尝试把 404 页面内容当作 JavaScript 解析,消耗更多资源。

补充规则:

  • 定义字符集,并放在 顶部。大多数浏览器会暂停页面渲染,直到找到字符集定义。

服务器

服务器相关优化设置可参考 H5BP 相关项目:

  • Nginx HTTP server boilerplate configs
  • Apache HTTP server boilerplate configs
  • IIS Web.Config Boilerplates

使用 CDN

网站 80-90% 响应时间消耗在资源下载上,减少资源下载时间是性能优化的黄金发则

相比分布式架构的复杂和巨大投入,静态内容分发网络(CDN)可以以较低的投入,获得加载速度有效提升。

添加 Expires 或 Cache-Control 响应头

  • 静态内容:将 Expires 响应头设置为将来很远的时间,实现「永不过期」策略;
  • 动态内容:设置合适的 Cache-Control 响应头,让浏览器有条件地发起请求。

启用 Gzip

Gzip 压缩通常可以减少 70% 的响应大小,对某些文件更可能高达 90%,比 Deflate 更高效。主流 Web 服务器都有相应模块,而且绝大多数浏览器支持 gzip 解码。所以,应该对 HTML、CSS、JS、XML、JSON 等文本类型的内容启用压缩。

注意,图片和 PDF 文件不要使用 gzip。它们本身已经压缩过,再使用 gzip 压缩不仅浪费 CPU 资源,而且还可能增加文件体积。

对于不支持的 Gzip 的用户代理,通过设置 Vary 响应头,返回为压缩的数据:

Vary: *  

配置 Etag

Etag 通过文件版本标识,方便服务器判断请求的内容是否有更新,如果没有就响应 304,避免重新下载。

当然,启用 Etag 可能会导致其他问题,还需要根据具体情况做判断。(TODO:补充相关内容)

尽早输出(flush)缓冲

用户请求页面时,服务器通常需要花费 200 ~ 500 毫秒来组合 HTML 页面。在此期间,浏览器处于空闲、等待数据状态。使用PHP 中的 flush() 函数,可以发送部分已经准备好的 HTML 到浏览器,以便服务器还在忙于处理剩余页面时,浏览器可以提前开始获取资源。

可以考虑在 之后输出一次缓冲,HTML head 一般比较容易生成,先发送以便浏览器开始获取 里引用的 CSS 等资源。

Example:

  
  
  
  
  

Ajax 请求使用 GET 方法

浏览器执行 XMLHttpRequest POST 请求时分成两步,先发送 Header,再发送数据。而 GET 只使用一个 TCP 数据包发送数据,所以首选 GET 方法。

根据 HTTP 规范,GET 用于获取数据,POST 则用于向服务器发送数据,所以 Ajax 请求数据时使用 GET 更符合规范(GET 和 POST 对比)。

IE 中最大 URL 长度为 2K,如果超出 2K,则需要考虑使用 POST 方法。

避免图片 src 为空

图片 src 属性值为空字符串可能以下面两种形式出现:

HTML:

  

JavaScript:

var img = new Image();  
img.src = "";  

虽然 src 属性为空字符串,但浏览器仍然会向服务器发起一个 HTTP 请求:

  • IE 向页面所在的目录发送请求;
  • Safari、Chrome、Firefox 向页面本身发送请求;
  • Opera 不执行任何操作。

以上数据较老,当下主流版本可能会有改变。

src 产生请求的后果不容小憩:

  • 给服务器造成意外的流量负担,尤其时日 PV 较大时;
  • 浪费服务器计算资源;
  • 可能产生报错。

当然,浏览器如此实现也是根据 RFC 3986 - Uniform Resource Identifiers,当空字符串作为 URI 出现时,被当成相对 URI,具体算法参见规范 5.2 节。

参考链接

  • Empty image src can destroy your site

空的 href 属性也存在类似问题。用户点击空链接时,浏览器也会向服务器发送 HTTP 请求,可以通过 JavaScript 阻止空链接的默认的行为。

Cookie

减少 Cookie 大小

Cookie 被用于身份认证、个性化设置等诸多用途。Cookie 通过 HTTP 头在服务器和浏览器间来回传送,减少 Cookie 大小可以降低其对响应速度的影响。

  • 去除不必要的 Cookie;
  • 尽量压缩 Cookie 大小;
  • 注意设置 Cookie 的 domain 级别,如无必要,不要影响到 sub-domain;
  • 设置合适的过期时间。

更多细节参考 When the Cookie Crumbles。

静态资源使用无 Cookie 域名

静态资源一般无需使用 Cookie,可以把它们放在使用二级域名或者专门域名的无 Cookie 服务器上,降低 Cookie 传送的造成的流量浪费,提高响应速度。

CSS

把样式表放在 中可以让页面渐进渲染,尽早呈现视觉反馈,给用户加载速度很快的感觉。

这对内容比较多的页面尤为重要,用户可以先查看已经下载渲染的内容,而不是盯着白屏等待。

如果把样式表放在页面底部,一些浏览器为减少重绘,会在 CSS 加载完成以后才渲染页面,用户只能对着白屏干瞪眼,用户体验极差。

不要使用 CSS 表达式

CSS 表达式可以在 CSS 里执行 JavaScript,仅 IE5-IE7 支持,IE8 标准模式已经废弃。

CSS 表达式超出预期的频繁执行,页面滚动、鼠标移动时都会不断执行,带来很大的性能损耗。

IE7 及更低版本的浏览器已经逐渐成为历史,忘记它吧。

对于 IE 某些版本,@import 的行为和 放在页面底部一样。所以,不要用它。

不要使用 filter

AlphaImageLoader 为 IE5.5-IE8 专有的技术,和 CSS 表达式一样,放进博物馆吧。

注意:

这里所说的不是 CSS3 Filter,参考文章 Understanding CSS Filter Effects

JavaScript

把脚本放在页面底部

浏览器下载脚本时,会阻塞其他资源并行下载,即使是来自不同域名的资源。因此,最好将脚本放在底部,以提高页面加载速度。

一些特殊场景无法将脚本放到页面底部的,可以考虑

相关内容推荐

口碑好的百度seo网站优化优化网站小程序网站建设优化广告流量罗湖收费网站优化的公司榆林网站优化平台收费网站优化营销企业网站搜索引擎优化方法毕节市百度网站优化镇海区网站优化方式网站seo优化的关键网站内部优化工作大邑网站优化网站优化需要懂得打代码吗石家庄网站排名优化服务金华网站优化平台静海网站优化联系方式宁夏银川网站优化哪家好网站内部链接优化有哪些宿州手机网站优化清镇网站优化价格网站搜索引擎优化电池绍兴网站优化平台莘县网站关键词优化网站做优化认可y火18星来优化方案网站自媒体时代需要网站优化万安网站优化衡阳品质网站建设优化怎么优化网站收录量淄博济南网站优化排名公司潍坊企业网站优化公司新乡网站怎么优化黄山网站优化如何选择肇庆网站关键词优化软件网站资料优化长春市网站关键词优化外包二七区网站整站优化北京网站首页优化南阳搜狗seo网站优化推荐郑州网站关键词优化工具拉萨网站优化公司公司高端网站优化有哪些关键词优化的网站莘县网站关键词优化长虹网站搜索引擎优化分析上海涂光优化网站排名网站优化排名步骤蓟州区网站优化推广网站建设优化颂扬云速捷选择建筑网站优化软件专注软件优化分享的网站移动端网站优化点击器阳江网站优化查询早教产品推广优化网站桓台网站优化湖北品质网站优化产品介绍网站优化快速排名软件大全吉林服务好的网站优化网站做优化只选d火17星做网站优化思路亦庄专业的网站优化广西网站优化注意事项哪个网站可以优化百度收录网站访问速度优化图片潍坊汽修网站建设优化价格实惠惠州网站优化收费玉环网站优化公司梁平网站关键词优化潍坊安防网站建设优化优质服务沙井seo优化网站招远外贸网站优化推广图片尺寸不同对于网站优化滨州网站优化开户专业优化网站公司侯镇网站优化价格金山桥网站优化公司响水盐城网站优化沙田服装网站优化是怎么做的朝阳网站关键词优化价格南充网站优化工具商业在线分享网站导航优化壹起航网站优化后注意事项网站优化技巧视频教程seo网站怎么优化到百度贷款行业网站优化方案网站优化方案基本流程高埗电子网站优化是怎么做的建湖网站关键词优化工作室安龙网站优化推广西安网站代码优化公司徐州网站搜索优化工作室肇庆市seo网站优化代理商常州专业网站优化公司怎么样优化新网站揭阳外贸网站关键词优化公司宝鸡网站优化外包滨州网站优化方案汕尾网站排名优化优化网站主要做哪些工作网站搜索引擎优化知识优化网站的方法心细火23星五金网站优化技术深圳网络营销网站优化怎么做来宾网站运营优化公司贵阳网站管理优化广州网站关键词优化服务南通网站排名优化费用温州网站优化开发太原网站搜索引擎优化技巧沧州盐山网站推广优化如何提高网站体验优化淄博网站seo优化多少钱河源网站优化售价优化需要更新网站吗东莞网站seo优化哪里好漳州网站优化服务手机网站搜索引擎优化广告网站优化效果好优化网站做什么上海涂光优化网站排名简述网站导航优化的五点要求本溪外贸网站优化南京医院网站优化手机优化网站建设手机端应该怎么做网站优化深圳百科网站优化互联网推广陆丰优化网站惠州谷歌网站优化潍坊安防网站建设优化优质服务网站搜索排名优化工具已注册好的餐饮行业网站优化方法北京网站推广优化公开封企业网站优化平台学网络优化需要会建设网站吗点卡网站怎么优化关键字怎么选择免费网站优化富阳区seo网站优化外包化妆品行业网站优化襄阳如何优化网站上海优化公司网站宝安企业网站优化安康网站推广优化阳江网站关键词优化哪家好网站诊断与优化实例艾奥兹网站优化是什么意思粤海外贸独立网站优化常平网站seo优化收费嘉兴网站专题优化网站百度推广和优化长春电商网站优化有什么技巧如何做网站搜索优化深圳网站优化追高粱seo珠海教育网站seo优化浙江网站怎么优化泉州seo网站排名优化网站排名优化吉金手指下拉六优化网站 网络服务山东济阳网站优化荆门市网站排名优化要多少钱自贡网站综合优化网站的优化思路桐乡网站网址优化正规网站优化一般多少钱网站后台管理关键词优化台山网站搜索优化陆丰优化网站南京网站优化哪家专业海口seo网站排名优化软件可信赖的网站seo优化优化网站学校网站优化是属于什么专业镇江营销网站优化是什么吉林求推荐好的网站优化推广浦江seo网站优化排名免费的网站优化最好的方法黄埔seo网站排名优化建瓯网站推广优化有什么好方法可以优化网站濮阳县网站优化网站优化建设南昌菏泽章丘网站优化费用多少钱长尾关键词 网站优化韶关企业网站seo优化邯郸seo网站关键词优化高港区网站优化专业团队天长网站优化公司哪家专业网站建设与优化联系方式seo网站优化案例分析正规的电商网站优化方法优化公司网站炕云速捷非凡长安网站推广及优化外包北京网络网站设计优化价格安顺市网站优化平台怎么用宝塔优化网站访问速度宁波网站关键词优化方案网站排名优化的逻辑网站优化的基本方式苏宁易购网站优化设计方案朔州网站seo优化培训黄山提供网站排名优化价格

合作伙伴

天下标王

龙岗网络公司
深圳网站优化
龙岗网站建设
坪山网站建设
百度标王推广
天下网标王
SEO优化按天计费
SEO按天计费系统