在你的 Rails App 中开启 ETag 加速页面载入同时节省资源
轉自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 下載,達到加速的目的。
比如下面這個場景的例子:
上面的場景用戶一共訪問了 12 次 /topics/11 這個頁面,但只有第一次和最后一次才有實質性的內容需要下載的,可在沒有 ETag 的情況下面,服務器執行和瀏覽器下載都是有 12 次,其中的 10 次是多余的。
如果加上 ETag 以后,將會是這樣:
這個過程中,服務端執行了 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 7 8 9 10 11 12 13 14 15 | 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 |
這樣一來,每個用戶的 ETag 都是不同的,當用戶登出和登錄以后,頁面的內容將會呈現不同的 ETag,同時當你修改 SiteConfig 的某些內容是,ETag 也會隨著改變,這樣一來 ETag 的引入就不會影響到頁面更新了。
實際上你可以大量的使用 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 |
轉載于:https://www.cnblogs.com/wangyuyu/p/3545978.html
總結
以上是生活随笔為你收集整理的在你的 Rails App 中开启 ETag 加速页面载入同时节省资源的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 构造函数中不应调用虚函数
- 下一篇: 杨森翔的书法:正月十六试笔【圆光、斗方】