33

我在Rails中開始一個新項目,它看起來像application.js清單文件正在做一些有趣的事情,我引用了javascripts - 是否緩存這些文件作爲資產管道?清除Rails資產管道中的緩存

這是發生了什麼事。我添加了一個名爲jquery.autoresize.js給供應商/資產/ JavaScript的文件夾中的JavaScript文件,然後引用清單中像這樣的application.js文件:

//= require jquery.autoresize.js 

然後,我開始了在軌服務器。但是在瀏覽我的應用程序後,我意識到我不小心添加了錯誤版本的jquery.autoresize.js文件。所以,我刪除了該文件,然後將正確的版本添加到vendor/assets/javascripts文件夾。但是,令我驚恐的是,當我重新加載頁面時,它仍在加載舊的JavaScript文件。

我試圖清空我的瀏覽器緩存,然後退出並重新啓動Rails服務器,但無濟於事。我通過簡單地重命名我的JavaScript文件並引用新名稱,這很好地解決了一個解決方案。但是這必須有更好的解決方案。

新資產管道緩存了您引用的文件嗎?如果是這樣,我該如何清除緩存?謝謝你的幫助!

回答

48

我假設我們正在談論生產環境。

當您更改生產環境中的任何JavaScript或樣式表時,您需要運行rake assets:precompile;此任務編譯和壓縮各種.js和.css文件,並創建由視圖加載的application.js和application.css文件。

這是可能的,如果你用一箇舊的時間戳版本替換jquery.autoresize.js,預編譯步驟可以跳過它,想着編譯的版本是最新的更新。您可以通過先運行rake assets:clean來避免這種情況,迫使它從零開始重建public/assets目錄中的所有內容。

+0

啊,非常有趣,謝謝你的想法。我實際上是在我的本地開發環境中執行此操作,並且我從不運行rake資源:預編譯。那麼,也許這使得它的行爲有所不同?你認爲開發環境會使它的行爲與我原先描述的一樣嗎? – 2012-09-06 04:03:47

+2

在開發環境中,不使用哈希文件名,因此所有內容都基於文件修改日期。 (在瀏覽器中查看源代碼以查看HTML標頭中的腳本鏈接。)我的猜測是,在開發環境中,替換文件具有較早的修改日期,因此瀏覽器僅使用其緩存版本。你的編輯更新了文件的mod時間,這就是瀏覽器最終獲取新版本的原因。 – benzado 2012-09-06 18:10:10

+0

太棒了。感謝您幫助我弄清楚這一點。我會修改問題的內容,以更好地解釋問題併爲您提供幫助。 – 2012-09-06 19:02:35

23

每次編輯內容時,Rails都會自動清除單個文件的緩存。 要清除單個文件的緩存,只需打開文件,編輯一行代碼並重新保存即可。 Rails將清除該文件的緩存,並且瀏覽器將在下次加載頁面時加載新文件。

jquery.autoresize.js使用舊緩存版本的文件的原因是,舊版本被刪除,然後新版本被複制並粘貼到相同的文件夾中。由於文件本身從未編輯,Rails繼續使用緩存的舊文件。

這是因爲資產管道使用指紋識別緩存。

指紋識別是一種使文件內容依賴於文件名稱 的技術。當文件內容改變時, 文件名也被改變。對於靜態或不頻繁的內容 進行更改,這提供了一種簡單的方法來判斷文件的兩個版本是否相同,即使是在不同的服務器或部署日期也是如此。

當一個文件名是獨一無二的,根據其內容,HTTP頭可以 被設置爲鼓勵緩存無處不在(無論是在CDN中,在互聯網服務供應商,在 網絡設備,或在網絡瀏覽器),以保持自己的 副本內容。當內容更新時,指紋會改變。 這將導致遠程客戶端請求 內容的新副本。這通常稱爲緩存清除。

Rails用於指紋識別的技術是將內容的散列 插入到名稱中,通常在末尾。例如一個CSS 文件全局。CSS可以用其內容的MD5摘要改名:

global-908e25f4bf641868d8683022a5b62f54.css 

所以,如果你刪除你的清單引用文件,然後在一個新的文件複製具有相同的名稱,高速緩存破壞從未發生。當您編輯文件時,指紋會啓動,併爲文件名稱生成一個新的散列。這爲該文件破壞了緩存

有關完整的故事,請參閱What is Fingerprinting and Why Should I Care?

+1

我不認爲這是正確的。指紋基於文件的內容。如果刪除一個文件並將其替換爲具有相同名稱的* * *,則會得到不同的指紋和不同的文件名。 – benzado 2012-09-05 01:18:28

+1

感謝您的支持。您最近在自己的項目中嘗試了這個嗎?因爲我可以肯定地確認,當我創建這個問題時,我可以通過瀏覽器加載新文件的唯一方法是編輯一行代碼並重新保存它。如果它只是通過刪除文件並將其替換爲具有相同名稱的新文件而爲您工作,我很樂意聽到它。 – 2012-09-05 22:26:11

+0

我有一個不同的資產管道問題,這是我遇到這個問題。你說:「如果你刪除了一個你在清單中引用的文件,然後複製一個新文件具有相同的名稱,緩存破壞永遠不會發生。如果新/舊文件具有*相同的內容*,那麼*只會*爲真,在這種情況下,誰在乎你擁有哪個版本?如果您正在討論生產模式,您需要運行'rake assets:precompile'將這些文件放入'public/assets'目錄;這應該是解決方案,除非你已經改變了默認配置。 – benzado 2012-09-05 23:15:56

6

我在我的application.rb中使用config.assets.version = '1.01019'來破壞整個緩存。當我想要推出一個完整的新版本時,我增加了版本,這個技巧。這考慮到了Rails因任何原因不會重新編譯爲資產的邊緣情況。

25

也試試rake assets:clobber。這將完全重置所有內容並刪除所有已編譯的資產。此外,我經常需要在推進生產前設置環境:RAILS_ENV=production rake assets:precompile

+0

+1!這個解決方案爲我工作。我正在開發一個自定義資產管道處理器,這使得Sprockets再次進入處理器。 Thx – MegaTux 2017-01-09 15:19:41

6

rake tmp:clear爲我做了詭計,我使用less-rails。

+1

我必須這樣做才能讓browserify-rails進行更新,否則它將查找並使用已被刪除的舊文件。 '軌道資產:乾淨'不適合這個。 – Ryan 2016-12-03 20:05:38

+0

該命令也會刪除tmp目錄中的pid文件。 – caiguanhao 2017-04-11 01:35:44