在你的 Rails App 中开启 ETag 加速页面载入同时节省资源
2014-02-12 15:06
169 查看
转自http://huacnlee.com/blog/use-etag-in-your-rails-app-to-speed-up-loading/
什么是 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 加速页面载入同时节省资源
- [翻译]ASP.NET MVC 3 开发的20个秘诀(二十)[20 Recipes for Programming MVC 3]:缓存结果数据加速页面载入
- 开启硬件加速 解决页面闪白 保证动画流畅
- ASP.NET MVC 3 开发的20个秘诀(二十)[20 Recipes for Programming MVC 3]:缓存结果数据加速页面载入
- App Thinning功能中其实有三个独立的机制,分别是App Slicing、on-demand resources以及Bitcode,它们在节省iOS应用资源方面发挥着各自的作用。 iOS 9的
- html5新功能5—使用HTML5的页面资源预加载(Link prefetch)功能加速你的页面加载速度
- AndroidAPP载入页面图片全屏显示
- [翻译]ASP.NET MVC 3 开发的20个秘诀(二十)[20 Recipes for Programming MVC 3]:缓存结果数据加速页面载入
- 安卓APP载入HTML5页面解决方式总结
- 解决app按home键运行到后台,再次运行程序避免再次开启app的MAIN页面
- APP 缓存数据线程安全问题,多个线程同时对同一资源进行读写问题
- linux扩大内存可加速 FireFox 及 Chrome 的页面载入速度
- HTML5页面资源预加载(Link prefetch)功能加速页面加载速度
- 网站子目录里的页面无法调用App_LocalResources里的本地资源文件
- android app 返回桌面后再次点击app图标启动 不要重新载入启动页面
- 资源载入和页面事件 load, ready, DOMContentLoaded等
- android:检查系统是否开启消息通知权限,app应用点击开启通知时跳转到app详情页面开启权限
- HTML5 --- 页面资源预加载技术(Link prefetch)加速页面加载
- HTML5的页面资源预加载技术(Link prefetch)加速页面加载
- app放大缩小,同时左右切换页面。插件pinchzoom.js在iscroll和swipper中使用