Chặn bộ nhớ cache qua tham số


123

Chúng tôi muốn xóa bỏ sự phá sản khi triển khai sản xuất, nhưng không lãng phí nhiều thời gian để tìm ra một hệ thống để làm như vậy. Suy nghĩ của tôi là áp dụng một tham số cho cuối tệp css và js với số phiên bản hiện tại:

<link rel="stylesheet" href="base_url.com/file.css?v=1.123"/>

Hai câu hỏi: Điều này sẽ phá vỡ bộ nhớ cache một cách hiệu quả? Liệu tham số có khiến trình duyệt sau đó không bao giờ lưu vào bộ nhớ cache phản hồi từ url đó vì tham số chỉ ra rằng đây là nội dung động không?

Câu trả lời:


115

Tham số ?v=1.123chỉ ra một chuỗi truy vấn và do đó trình duyệt sẽ nghĩ rằng đó là một đường dẫn mới từ, chẳng hạn như ?v=1.0,. Do đó làm cho nó tải từ tệp chứ không phải từ bộ nhớ cache. Như bạn muốn.

Và, trình duyệt sẽ giả định rằng nguồn sẽ giữ nguyên vào lần tiếp theo bạn gọi ?v=1.123nên lưu vào bộ nhớ cache với chuỗi đó. Vì vậy, nó sẽ vẫn được lưu trong bộ nhớ cache, tuy nhiên máy chủ của bạn đã được thiết lập, cho đến khi bạn chuyển đến ?v=1.124hoặc hơn thế nữa.


4
Trích dẫn Steve Souders: "Để đạt được lợi ích của việc lưu vào bộ đệm bởi các proxy phổ biến, hãy tránh quay vòng bằng một chuỗi truy vấn và thay vào đó hãy sửa lại chính tên tệp." Giải thích đầy đủ có thể được tìm thấy ở đây: stevesouders.com/blog/2008/08/23/…
lao

25
Bài đăng trên blog đó đã gần tròn một thập kỷ. Bạn có nghĩ rằng các nhà cung cấp bộ nhớ cache và CDN vẫn chưa đáp ứng được nó không? Squid dường như có thể lưu vào bộ đệm các tài liệu bằng các chuỗi truy vấn ngay bây giờ .
jeteon

1
Có thể điều này giúp ích cho ai đó: Cá nhân tôi sử dụng dấu thời gian sửa đổi tệp làm tham số phiên bản 'tự động', ví dụ: <link rel="stylesheet" href="style.css?v=1487935578" />
oelna

Cá nhân tôi không hiểu tại sao nhưng Lara Hogan (Swanson) (quản lý kỹ thuật tại Etsy) không khuyến khích sử dụng các tham số truy vấn để chặn bộ nhớ cache. Tôi nghĩ nó liên quan đến proxy bộ nhớ cache giữa người dùng và máy chủ.
Sam Rueby

36

Hai câu hỏi: Điều này sẽ phá vỡ bộ nhớ cache một cách hiệu quả?

Đúng. Ngay cả Stack Overflow cũng sử dụng phương pháp này, mặc dù tôi nhớ rằng họ (với hàng triệu khách truy cập mỗi ngày và vô số các phiên bản và cấu hình máy khách và proxy khác nhau) đã gặp một số trường hợp kỳ lạ mà ngay cả điều này cũng không đủ để phá vỡ bộ nhớ cache. Nhưng giả định chung là điều này sẽ hoạt động và là một phương pháp phù hợp để phá vỡ bộ nhớ đệm trên máy khách.

Liệu tham số có khiến trình duyệt sau đó không bao giờ lưu vào bộ nhớ cache phản hồi từ url đó vì tham số chỉ ra rằng đây là nội dung động không?

Không. Tham số sẽ không thay đổi chính sách bộ nhớ đệm; các tiêu đề bộ nhớ đệm do máy chủ gửi vẫn áp dụng và nếu nó không gửi bất kỳ tiêu đề nào, thì trình duyệt sẽ mặc định.


1
@spender Tôi không thể tìm thấy tài liệu tham khảo ngay bây giờ, tôi sợ, có một bài báo dài trên blog hoặc câu trả lời SO mà Jeff Atwood nói về nó (IIRC)
Pekka

2
@spender Tôi đã đọc rằng một số máy chủ proxy (cũ hoặc có thể được định cấu hình) bỏ qua chuỗi truy vấn khi lưu vào bộ nhớ đệm.
MrWhite

2
@spender - tôi cũng nghe nói như vậy và tôi nghĩ rằng thay đổi tên tệp hoặc đường dẫn là lựa chọn tốt nhất. Nó có thể là đơn giản nhất để chỉ cho phép di chuyển tất cả các file tĩnh của bạn dưới một cái tên thư mục phiên bản, ví dụ, /static/v22/file.csskhi bạn có thể làm nhiều file với một thay đổi tên đơn thư mục, ví dụ /static/v23/file.css/static/v23/mystuff.js
Brad Parks

22

Sẽ an toàn hơn nếu đặt số phiên bản vào tên tệp thực. Điều này cho phép nhiều phiên bản tồn tại cùng một lúc để bạn có thể triển khai phiên bản mới và nếu vẫn tồn tại bất kỳ trang HTML được lưu trong bộ nhớ cache nào yêu cầu phiên bản cũ hơn, họ sẽ nhận được phiên bản hoạt động với HTML của họ.

Lưu ý, trong một trong những triển khai có phiên bản lớn nhất ở bất kỳ đâu trên internet, jQuery sử dụng số phiên bản trong tên tệp thực tế và nó cho phép nhiều phiên bản cùng tồn tại một cách an toàn mà không cần bất kỳ logic phía máy chủ đặc biệt nào (mỗi phiên bản chỉ là một tệp khác nhau).

Điều này sẽ phá vỡ bộ nhớ cache khi bạn triển khai các trang mới và các tệp được liên kết mới (đó là những gì bạn muốn) và từ đó các phiên bản đó có thể được lưu vào bộ nhớ cache một cách hiệu quả (mà bạn cũng muốn).


Tôi đồng ý với điều đó, nhưng sẽ dễ dàng hơn nhiều nếu chỉ cần thêm Sinatra? V = <% = VERSION%> vào tất cả các yêu cầu css và js thay vì phải kiểm soát từng tệp riêng lẻ. Cuối cùng, chúng tôi sẽ chuyển sang sinatra-assetpack, sẽ xử lý trước và nén tất cả các tệp và thực sự thêm phiên bản # vào tên tệp, sau đó sẽ cho phép chúng tôi kiểm soát chúng riêng lẻ dễ dàng hơn nhiều.
Brad Herman

1
Tôi đồng ý đặt số phiên bản trong tên tệp là giải pháp an toàn cuối cùng nếu bạn muốn chắc chắn 10000%, nhưng tôi không tuân theo đối số "nhiều phiên bản tồn tại cùng một lúc". URL có tham số truy vấn khác với URL có tham số truy vấn khác. Chúng phải được khách hàng coi là hai tài nguyên khác nhau; nếu không, khách hàng bị hỏng.
Pekka

2
@Pekka - điều số phiên bản có thể cho phép nhiều phiên bản tồn tại cùng một lúc, nhưng điều đó yêu cầu sự hợp tác của máy chủ để ánh xạ tham số truy vấn đến đúng tệp thực tế. Tôi không nghĩ đó là những gì OP đang làm ở đây và có rất ít lý do để yêu cầu sự phức tạp đó khi sửa đổi tên tệp đơn giản hơn nhiều và không cần sự hợp tác của máy chủ. Rõ ràng là cả hai đều có thể hoạt động.
jfriend00 13/03/12

11

Như những người khác đã nói, chặn bộ nhớ cache với một tham số truy vấn thường được coi là một Ý tưởng Xấu (tm) và đã xảy ra trong một thời gian dài. Tốt hơn là phản ánh phiên bản trong tên tệp. Html5 Boilerplate khuyến nghị không nên sử dụng chuỗi truy vấn, trong số những chuỗi khác.

Điều đó nói rằng, trong số các khuyến nghị mà tôi đã thấy trích dẫn một nguồn, tất cả dường như đều lấy sự khôn ngoan của họ từ một bài báo năm 2008 của Steve Souders. Kết luận của ông dựa trên hành vi của các proxy vào thời điểm đó, và chúng có thể có hoặc không liên quan vào những ngày này. Tuy nhiên, trong trường hợp không có thêm thông tin mới, thay đổi tên tệp là tùy chọn an toàn.


9

Nó sẽ phá vỡ bộ nhớ cache một lần, sau khi máy khách đã tải xuống tài nguyên, mọi phản hồi khác sẽ được phân phát từ bộ đệm của máy khách trừ khi:

  1. tham số v được cập nhật.
  2. khách hàng xóa bộ nhớ cache của họ

6

Nói chung, điều này sẽ ổn, nhưng điều này có thể không hoạt động nếu có một bộ đệm trung gian (một proxy) được cấu hình để bỏ qua các tham số yêu cầu.

Ví dụ: nếu bạn đang cung cấp nội dung tĩnh thông qua Akamai CDN, nó có thể được định cấu hình để bỏ qua các tham số yêu cầu nhằm ngăn chặn việc truy xuất bộ nhớ cache bằng phương pháp này.


5

Nó phụ thuộc rất nhiều vào mức độ mạnh mẽ mà bạn muốn bộ nhớ đệm của mình. Ví dụ: máy chủ proxy mực (và có thể cả những máy khác) mặc định không lưu vào bộ nhớ đệm các URL được phân phát với một chuỗi truy vấn - ít nhất, nó đã làm như vậy khi bài báo đó được viết. Nếu bạn không bận tâm về một số trường hợp sử dụng nhất định gây ra bỏ lỡ bộ nhớ cache không cần thiết, thì hãy tiếp tục với các tham số truy vấn. Nhưng rất dễ dàng để thiết lập một lược đồ chặn bộ nhớ cache dựa trên tên tệp để tránh vấn đề này.


5
Proxy mực được trích dẫn trong bài viết của Steve Souders đã thay đổi chính sách bộ nhớ đệm mặc định của họ. Kể từ phiên bản 2.7 (tháng 5 năm 2008) và phiên bản 3.1 (tháng 3 năm 2010), hành vi mặc định là lưu nội dung động vào bộ đệm.
Josh Rack

5

Đã tìm thấy so sánh giữa 2 kỹ thuật (chuỗi truy vấn và tên tệp) tại đây :

Phiên bản dưới dạng một chuỗi truy vấn có hai vấn đề.

Đầu tiên, nó có thể không phải lúc nào cũng là một trình duyệt triển khai bộ nhớ đệm mà chúng ta cần phải xử lý. Người ta nói rằng một số proxy (có thể cũ hơn) bỏ qua chuỗi truy vấn đối với hành vi lưu vào bộ nhớ đệm của chúng.

Thứ hai, trong một số tình huống triển khai phức tạp hơn, nơi bạn có nhiều giao diện người dùng và / hoặc nhiều máy chủ phụ trợ, việc nâng cấp chỉ là tức thời. Bạn cần có thể phân phối cả phiên bản nội dung cũ và mới cùng một lúc. Xem ví dụ: điều này ảnh hưởng đến bạn như thế nào khi sử dụng Google App Engine.


4

Một cách tiếp cận tương tự khác là sử dụng htaccess mod_rewrite để bỏ qua một phần của đường dẫn khi cung cấp tệp. Trang chỉ mục không bao giờ được lưu trong bộ nhớ cache của bạn tham chiếu đến đường dẫn mới nhất đến các tệp.

Từ góc độ phát triển, nó dễ dàng như sử dụng các tham số cho số phiên bản, nhưng nó mạnh mẽ như cách tiếp cận tên tệp.

Sử dụng phần bị bỏ qua của đường dẫn cho số phiên bản và máy chủ chỉ bỏ qua nó và cung cấp tệp chưa được lưu vào bộ nhớ cache.

1.2.3/css/styles.csscung cấp cùng một tệp css/styles.cssvì thư mục đầu tiên bị tệp htaccess loại bỏ và bỏ qua

Bao gồm các tệp được tạo phiên bản

<?php
  $version = "1.2.3";
?>

<html>
  <head>
    <meta http-equiv="cache-control" content="max-age=0" />
    <meta http-equiv="cache-control" content="no-cache" />
    <meta http-equiv="expires" content="0" />
    <meta http-equiv="expires" content="Tue, 01 Jan 1980 1:00:00 GMT" />
    <meta http-equiv="pragma" content="no-cache" />
    <link rel="stylesheet" type="text/css" href="<?php echo $version ?>/css/styles.css">
  </head>
  <body>
    <script src="<?php echo $version ?>/js/main.js"></script>
  </body>
</html>

Lưu ý rằng phương pháp này có nghĩa là bạn cần phải tắt bộ nhớ đệm của trang chỉ mục của mình - Sử dụng thẻ <meta> để tắt bộ nhớ đệm trong tất cả các trình duyệt?

tệp .htaccess

RewriteEngine On

# if you're requesting a file that exists, do nothing
RewriteCond %{REQUEST_FILENAME} !-f 
# likewise if a directory that exists, do nothing
RewriteCond %{REQUEST_FILENAME} !-d 

# otherwise, rewrite foo/bar/baz to bar/baz - ignore the first directory
RewriteRule ^[^/]+/(.+)$ $1 [L] 

Bạn có thể thực hiện cách tiếp cận tương tự trên bất kỳ nền tảng máy chủ nào cho phép ghi lại url

(viết lại điều kiện được điều chỉnh từ mod_rewrite - viết lại thư mục thành chuỗi truy vấn ngoại trừ / #! / )

... và nếu bạn cần chặn bộ nhớ cache cho trang chỉ mục / điểm nhập trang web của mình, bạn luôn có thể sử dụng JavaSript để làm mới nó.


2
<script type="text/javascript">
// front end cache bust

var cacheBust = ['js/StrUtil.js', 'js/protos.common.js', 'js/conf.js', 'bootstrap_ECP/js/init.js'];   
for (i=0; i < cacheBust.length; i++){
     var el = document.createElement('script');
     el.src = cacheBust[i]+"?v=" + Math.random();
     document.getElementsByTagName('head')[0].appendChild(el);
}
</script> 

Trong quá trình phát triển / thử nghiệm các bản phát hành mới, bộ nhớ cache có thể là một vấn đề vì trình duyệt, máy chủ và thậm chí đôi khi viễn thông 3G (nếu bạn triển khai trên thiết bị di động) sẽ lưu nội dung tĩnh (ví dụ: JS, CSS, HTML, img). Bạn có thể khắc phục điều này bằng cách thêm số phiên bản, số ngẫu nhiên hoặc dấu thời gian vào URL, ví dụ: JSP: <script src = "js / excel.js? Time = <% = new java.util.Date ()%>"> </ script> Trong trường hợp bạn đang chạy HTML thuần túy (thay vì các trang máy chủ JSP, ASP, PHP) thì máy chủ sẽ không giúp bạn. Trong trình duyệt, liên kết được nạp trước khi chạy JS, do đó bạn phải gỡ bỏ các liên kết và tải chúng với JS
Conete Cristian

Tôi không nghĩ rằng điều này sẽ tải đồng bộ các tệp JS theo thứ tự.
Stealth Rabbi

0
 <script>
    var storedSrcElements = [
         "js/exampleFile.js",
         "js/sampleFile.js",
         "css/style.css"
          ];

    var head= document.getElementsByTagName('head')[0];
    var script;
    var link;
    var versionNumberNew = 4.6;

    for(i=0;i<storedSrcElements.length;i++){
     script= document.createElement('script');
     script.type= 'text/javascript';
     script.src= storedSrcElements[i] + "?" + versionNumberNew;
     head.appendChild(script);
    }     


     </script> 


       ### Change the version number  (versionNumberNew) when you want the new files to be loaded  ###

0

Hy vọng điều này sẽ giúp bạn chèn tệp JS bên ngoài

<script type="text/javascript"> 
var cachebuster = Math.round(new Date().getTime() / 1000); 
document.write('<scr'+'ipt type="text/javascript" src="external.js?cb=' +cachebuster+'"></scr' + 'ipt>');
</script>

Nguồn - Mã bộ nhớ cache trong JavaScript

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.