在你的 Rails App 中开启 ETag 加速页面载入同时节省资源
2013-07-01 17:43
169 查看
什么是 ETag
网上关于 ETag 的解释有很多,我这里简单的说明一下我的理解:ETag 是 HTTP 协议的标准参数,一般是这样的:”686897696a7c876b7e” 一段字符,它能通过一段字符来判断浏览器 cache 的内容是否和服务端返回的内容是否相同,从而来决定是否要重新从服务器下载东西 (HTTP 状态 200 - 重新下载 / 304 - 没有更新)。
ETag 使用场景举例
这个东西非常适合用于动态内容上面,以减少不必要的 HTML 下载,达到加速的目的。比如下面这个场景的例子:
用户访问 /topics/11 页面,
TopicsController#show加载
@topic,并通过
View 生成内容返回
用户来回访问 10 次 /topics/11,可此页面内容无任何变化
过了1天以后,
@topic有了新的回复,用户再次访问的时候,内容变了
上面的场景用户一共访问了 12 次 /topics/11 这个页面,但只有第一次和最后一次才有实质性的内容需要下载的,可在没有 ETag 的情况下面,服务器执行和浏览器下载都是有 12 次,其中的 10 次是多余的。
如果加上 ETag 以后,将会是这样:
用户访问 /topics/11 页面,
TopicsController#show加载
@topic,并通过
View 生成内容返回,并给出目前内容的
ETag: 89vbsn28716
用户带着
ETag: 89vbsn28716再次访问 /topics/11 ,服务器检查 ETag 与执行结果,发现无变化,返回 304,浏览器直接使用 Cache 的内容渲染页面
过了一天以后,
@topic有了新回复,用户再次带着
ETag: 89vbsn28716/topics/11,服务器检查 ETag 发现不对了,生成新内容,并返回 200
这个过程中,服务端执行了 12 次页面,而下载 HTML 内容到本地却只有两次。
Rails 里面开启 ETag
Rails 的 ActionController 里面已经为我们提供了 fresh_when 和 stale? 这两个方法用于处理ETag,可以点击连接稍微看一下说明。
我下面以 Ruby China 的 查看 Wiki 页面 为例子演示如何在 Rails 里面合理的使用 ETag
pages_controller.rb:
1 2 3 4 5 6 7 | class PagesController < ApplicationController def show @page = Page.find_by_slug(params[:id]) @comments = @page.comments.paginate(:page => params[:page], :per_page => 50) fresh_when(:etag => [@page, @comments]) end end |
fresh_when方法以后,Rails 将会用
@page和
@comments内容的组合的
MD5 hash 值作为 ETag 并与 HTTP Headers 里面的 ETag 进行比较来决定是否需要执行后面的 Views 渲染,并返回
200或
304。
在浏览器上面显示将会是这样:
没有 ETag 的情况 (72 ms):
有 ETag 的情况 (40 ms):
OMG! 页面加载速度直接提升了 46%,并且 ETag 命中的情况下,Views 上面的一系列代码都不用执行了,节省了不少资源。
但是实际的场景,往往没有上面这个例子这么简单……
比如,页面上有 current_user的状态,页脚的 HTML 代码是通过
Setting.footer_html出来的,Head
里面还有
Setting.custom_heads出来的代码。
以上这些东西都是需要影响页面更新的。
实际上我们只需要将
fresh_when方法在
ApplicationController里面覆盖一下,把页面上需要调用而影响结果的东西加入到
fresh_when的
:etag参数里面就好了:
application_controller.rb:
1 2 3 4 5 6 78 | def fresh_when(opts = {}) opts[:etag] ||= [] # 保证 etag 参数是 Array 类型 opts[:etag] = [opts[:etag]] if !opts[:etag].is_a?(Array) # 加入页面上直接调用的信息用于组合 etag opts[:etag] << current_user # Config 的某些信息 opts[:etag] << SiteConfig.app_name opts[:etag] << SiteConfig.custom_head_html opts[:etag] << SiteConfig.footer_html opts[:etag] << SiteConfig.google_analytics_key # 所有 etag 保持一天 opts[:etag] << Date.current super(opts) end |
实际上你可以大量的使用
fresh_when方法在你的动态页面上面,来减少 Rails View 的执行与 HTML 下载,只要好好分析,将页面上需要的内容加入到
:etag参数里面就好了。
比如:
1 2 3 4 5 6 7 | def index @hot_topics = Topic.hot.limit(10) @hot_users = User.hot.limit(10) @hot_nodes = Node.hot.limit(10) @recent_topics = Topic.recent.limit(10) fresh_when(:etag => [@hot_topics,@hot_users,@hot_nodes,@recent_topics]) end |
相关文章推荐
- 在你的 Rails App 中开启 ETag 加速页面载入同时节省资源
- app放大缩小,同时左右切换页面。插件pinchzoom.js在iscroll和swipper中使用
- 使用HTML5的页面资源预加载(Link prefetch)功能加速你的页面加载速度
- nginx开启gzip加速你的静态资源加载
- Android APP 进入后台开启手势密码页面
- 开启硬件加速 解决页面闪白 保证动画流畅
- HTML5的页面资源预加载技术(Link prefetch)加速页面加载
- App Thinning功能中其实有三个独立的机制,分别是App Slicing、on-demand resources以及Bitcode,它们在节省iOS应用资源方面发挥着各自的作用。 iOS 9的
- CI-缓存页面 开启缓存加速网站运行
- HTML5的页面资源预加载技术(Link prefetch)加速页面加载
- 创意(一个app访问照片库里面的资源,生成每天的特效幻灯片,同时删除编辑更方便)
- 安卓APP载入HTML5页面解决方式总结
- 解决app按home键运行到后台,再次运行程序避免再次开启app的MAIN页面
- APP 缓存数据线程安全问题,多个线程同时对同一资源进行读写问题
- ASP.NET MVC 3 开发的20个秘诀(二十)[20 Recipes for Programming MVC 3]:缓存结果数据加速页面载入
- [翻译]ASP.NET MVC 3 开发的20个秘诀(二十)[20 Recipes for Programming MVC 3]:缓存结果数据加速页面载入
- html5新功能5—使用HTML5的页面资源预加载(Link prefetch)功能加速你的页面加载速度
- AndroidAPP载入页面图片全屏显示
- [翻译]ASP.NET MVC 3 开发的20个秘诀(二十)[20 Recipes for Programming MVC 3]:缓存结果数据加速页面载入
- HTML5页面资源预加载(Link prefetch)功能加速页面加载速度