Làm cách nào để buộc trình duyệt tải lại các tệp CSS / JS được lưu trong bộ nhớ cache?


993

Tôi đã nhận thấy rằng một số trình duyệt (đặc biệt là Firefox và Opera) rất nhiệt tình trong việc sử dụng các bản sao của tệp .css.js được lưu trong bộ nhớ cache , ngay cả giữa các phiên trình duyệt. Điều này dẫn đến sự cố khi bạn cập nhật một trong những tệp này nhưng trình duyệt của người dùng vẫn tiếp tục sử dụng bản sao được lưu trong bộ nhớ cache.

Câu hỏi đặt ra là: cách thức thanh lịch nhất để buộc trình duyệt của người dùng tải lại tệp khi nó đã thay đổi?

Lý tưởng nhất, giải pháp sẽ không buộc trình duyệt tải lại tệp mỗi lần truy cập vào trang. Tôi sẽ đăng giải pháp của riêng tôi dưới dạng câu trả lời, nhưng tôi tò mò liệu có ai có giải pháp tốt hơn không và tôi sẽ để phiếu bầu của bạn quyết định.

Cập nhật:

Sau khi cho phép thảo luận ở đây một thời gian, tôi đã thấy đề xuất của John Millikinda5id là hữu ích. Hóa ra có một thuật ngữ cho việc này: phiên bản tự động .

Tôi đã đăng một câu trả lời mới dưới đây là sự kết hợp giữa giải pháp ban đầu của tôi và đề xuất của John.

Một ý tưởng khác được đề xuất bởi SCdF sẽ là nối thêm chuỗi truy vấn không có thật vào tệp. (Một số mã Python để tự động sử dụng dấu thời gian dưới dạng chuỗi truy vấn không có thật đã được gửi bởi pi .). Tuy nhiên, có một số cuộc thảo luận về việc liệu trình duyệt có lưu trữ tệp với chuỗi truy vấn hay không. (Hãy nhớ rằng, chúng tôi muốn trình duyệt lưu tệp vào bộ đệm và sử dụng nó trong các lần truy cập trong tương lai. Chúng tôi chỉ muốn nó tải lại tệp khi nó đã thay đổi.)

Vì không rõ điều gì xảy ra với chuỗi truy vấn không có thật, tôi không chấp nhận câu trả lời đó.


Tôi có điều này trong .htaccess của tôi và không bao giờ có bất kỳ vấn đề nào với các tệp được lưu trong bộ nhớ cache : ExpiresActive On ExpiresDefault "modification".
Frank Conijn

2
Tôi chắc chắn đồng ý rằng việc thêm thông tin phiên bản vào URL của tệp là cách tốt nhất để đi. Nó hoạt động, tất cả thời gian, cho tất cả mọi người. Nhưng, nếu bạn không sử dụng nó và thỉnh thoảng bạn chỉ cần tải lại một tệp CSS hoặc JS đó trong trình duyệt của riêng bạn ... chỉ cần mở nó trong tab riêng của nó và nhấn SHIFT-reload (hoặc CTRL-F5)! Bạn có thể thực hiện hiệu quả điều tương tự bằng cách sử dụng JS bằng cách tải tệp trong iframe (ẩn), đợi cho đến khi tải và sau đó gọi iframe.contentWindow.location.reload(true). Xem phương pháp (4) của stackoverflow.com/a/22429796/999120 - đó là về hình ảnh, nhưng áp dụng tương tự.
Doin

2
Tôi thực sự đánh giá cao cách câu hỏi này đã được hỏi và đã được cập nhật kể từ đó. Nó hoàn toàn mô tả những gì tôi nên mong đợi trong các câu trả lời. Tôi sẽ làm theo phương pháp này trong các câu hỏi của tôi từ bây giờ. Chúc mừng!
22

Câu trả lời:


455

Cập nhật: Viết lại để kết hợp các đề xuất từ John Millikinda5id . Giải pháp này được viết bằng PHP, nhưng nên dễ dàng thích nghi với các ngôn ngữ khác.

Cập nhật 2: Kết hợp các bình luận từ Nick Johnson rằng .htaccessregex ban đầu có thể gây ra sự cố với các tệp như json-1.3.js. Giải pháp là chỉ viết lại nếu có chính xác 10 chữ số ở cuối. (Vì 10 chữ số bao gồm tất cả các dấu thời gian từ 9/9/2001 đến 11/20/2286.)

Đầu tiên, chúng tôi sử dụng quy tắc viết lại sau đây trong .htaccess:

RewriteEngine on
RewriteRule ^(.*)\.[\d]{10}\.(css|js)$ $1.$2 [L]

Bây giờ, chúng ta viết hàm PHP sau:

/**
 *  Given a file, i.e. /css/base.css, replaces it with a string containing the
 *  file's mtime, i.e. /css/base.1221534296.css.
 *  
 *  @param $file  The file to be loaded.  Must be an absolute path (i.e.
 *                starting with slash).
 */
function auto_version($file)
{
  if(strpos($file, '/') !== 0 || !file_exists($_SERVER['DOCUMENT_ROOT'] . $file))
    return $file;

  $mtime = filemtime($_SERVER['DOCUMENT_ROOT'] . $file);
  return preg_replace('{\\.([^./]+)$}', ".$mtime.\$1", $file);
}

Bây giờ, bất cứ nơi nào bạn bao gồm CSS của bạn, hãy thay đổi nó từ đây:

<link rel="stylesheet" href="/css/base.css" type="text/css" />

Về điều này:

<link rel="stylesheet" href="<?php echo auto_version('/css/base.css'); ?>" type="text/css" />

Bằng cách này, bạn không bao giờ phải sửa đổi thẻ liên kết nữa và người dùng sẽ luôn thấy CSS mới nhất. Trình duyệt sẽ có thể lưu trữ tệp CSS, nhưng khi bạn thực hiện bất kỳ thay đổi nào đối với CSS, trình duyệt sẽ xem đây là một URL mới, vì vậy nó sẽ không sử dụng bản sao được lưu trong bộ nhớ cache.

Điều này cũng có thể hoạt động với hình ảnh, favicon và JavaScript. Về cơ bản bất cứ điều gì không được tạo ra năng động.


16
Máy chủ nội dung tĩnh của riêng tôi thực hiện chính xác như vậy, ngoại trừ tôi sử dụng tham số để tạo phiên bản (base.css? V = 1221534296) thay vì thay đổi tên tệp (base.1221534296.css). Tôi nghi ngờ cách của bạn có thể hiệu quả hơn một chút mặc dù. Rất tuyệt.
Jens Roland

4
@Kip: Giải pháp rất lắt léo. Viết lại URL rõ ràng có nhiều thứ để cung cấp hơn là các url khá hay.
James P.

37
Tôi thấy một vấn đề với điều này, rằng nó truy cập hệ thống tập tin nhiều lần - chính xác - số lượng liên kết * số lượng yêu cầu / giây ... có thể hoặc không phải là vấn đề đối với bạn.
Tomáš Fejfar

3
@AlixAxel: Không, các trình duyệt sẽ tìm nạp lại khi tham số thay đổi, nhưng một số proxy công khai sẽ không lưu các tệp với các tham số url, vì vậy cách tốt nhất là đưa phiên bản vào đường dẫn. Và chi phí hoạt động của mod_rewrite rất nhỏ so với mọi nút thắt hiệu suất khác trong WPO
Jens Roland

8
file_existskiểm tra đầu tiên thực sự cần thiết? filemtimesẽ trả về false khi thất bại, vậy tại sao không chỉ định giá trị filemtime cho một biến và kiểm tra xem nó có sai không trước khi đổi tên tệp? Điều đó sẽ cắt giảm một thao tác tập tin không cần thiết mà thực sự sẽ tăng lên.
Gavin

184

Kỹ thuật đơn giản phía khách hàng

Nói chung, bộ nhớ đệm là tốt .. Vì vậy, có một số kỹ thuật, tùy thuộc vào việc bạn tự khắc phục sự cố khi bạn phát triển trang web hay bạn đang cố gắng kiểm soát bộ đệm trong môi trường sản xuất.

Khách truy cập chung vào trang web của bạn sẽ không có cùng trải nghiệm mà bạn có khi bạn phát triển trang web. Vì khách truy cập trung bình đến trang web ít thường xuyên hơn (có thể chỉ một vài lần mỗi tháng, trừ khi bạn là Google hoặc Mạng của Google), nên họ ít có khả năng để các tệp của bạn trong bộ nhớ cache và điều đó có thể là đủ. Nếu bạn muốn buộc một phiên bản mới vào trình duyệt, bạn luôn có thể thêm chuỗi truy vấn vào yêu cầu và tăng số phiên bản khi bạn thực hiện các thay đổi lớn:

<script src="/myJavascript.js?version=4"></script>

Điều này sẽ đảm bảo rằng tất cả mọi người có được các tập tin mới. Nó hoạt động vì trình duyệt xem URL của tệp để xác định xem nó có bản sao trong bộ đệm hay không. Nếu máy chủ của bạn không được thiết lập để làm bất cứ điều gì với chuỗi truy vấn, nó sẽ bị bỏ qua, nhưng tên sẽ trông giống như một tệp mới cho trình duyệt.

Mặt khác, nếu bạn đang phát triển một trang web, bạn không muốn thay đổi số phiên bản mỗi khi bạn lưu thay đổi cho phiên bản phát triển của mình. Điều đó sẽ tẻ nhạt.

Vì vậy, trong khi bạn đang phát triển trang web của mình, một mẹo hay sẽ là tự động tạo tham số chuỗi truy vấn:

<!-- Development version: -->
<script>document.write('<script src="/myJavascript.js?dev=' + Math.floor(Math.random() * 100) + '"\><\/script>');</script>

Thêm một chuỗi truy vấn vào yêu cầu là một cách tốt để phiên bản tài nguyên, nhưng đối với một trang web đơn giản, điều này có thể không cần thiết. Và hãy nhớ rằng, bộ nhớ đệm là một điều tốt.

Cũng đáng lưu ý rằng trình duyệt không nhất thiết phải keo kiệt về việc giữ các tệp trong bộ nhớ cache. Các trình duyệt có chính sách cho loại điều này và chúng thường được chơi theo các quy tắc được đặt trong đặc tả HTTP. Khi trình duyệt đưa ra yêu cầu đến máy chủ, một phần của phản hồi là tiêu đề EXPIRES .. một ngày cho trình duyệt biết thời gian cần lưu trong bộ nhớ cache. Lần tiếp theo trình duyệt bắt gặp một yêu cầu cho cùng một tệp, nó thấy rằng nó có một bản sao trong bộ đệm và tìm đến ngày EXPIRES để quyết định xem có nên sử dụng nó không.

Vì vậy, tin hay không, thực sự máy chủ của bạn đang khiến bộ nhớ cache của trình duyệt trở nên quá dai dẳng. Bạn có thể điều chỉnh cài đặt máy chủ của mình và thay đổi các tiêu đề EXPIRES, nhưng kỹ thuật nhỏ mà tôi đã viết ở trên có lẽ là cách đơn giản hơn nhiều để bạn thực hiện. Vì bộ nhớ đệm là tốt, bạn thường muốn đặt ngày đó đến tương lai ("Tiêu đề hết hạn trong tương lai xa") và sử dụng kỹ thuật được mô tả ở trên để buộc thay đổi.

Nếu bạn quan tâm đến nhiều thông tin hơn về HTTP hoặc cách thực hiện các yêu cầu này, một cuốn sách hay là "Trang web hiệu suất cao" của Steve Souder. Đó là một giới thiệu rất tốt về chủ đề này.


3
Thủ thuật nhanh để tạo chuỗi truy vấn với Javascript hoạt động rất tốt trong quá trình phát triển hoạt động. Tôi đã làm điều tương tự với PHP.
Alan Turing

2
Đây là cách dễ nhất để thực hiện kết quả mong muốn của người đăng ban đầu. Phương thức mod_rewrite hoạt động tốt nếu bạn muốn tải lại tệp .css hoặc .js MERYI lần bạn tải trang. Phương pháp này vẫn cho phép lưu vào bộ đệm cho đến khi bạn thực sự thay đổi tệp và thực sự muốn nó buộc tải lại.
scott80109

@keparo, tôi có rất nhiều jquery trong tất cả các trang nếu tôi sẽ thay đổi điều này bằng tay thì sẽ mất một tháng. Nếu bạn có thể giúp tôi giải quyết tất cả mà không cần mã hóa đến từng trang.
cracker

1
Điều này dường như không hoạt động với CSS của tôi khi tôi sử dụng:<link href='myCss.css?dev=14141'...>
Noumenon 24/07/2015

3
Đây không phải là một giải pháp khả thi. Một số lượng tốt các trình duyệt sẽ từ chối lưu trữ bất cứ thứ gì có chuỗi truy vấn trên đó. Đây là lý do tại sao Google, GTMetrix và các công cụ tương tự sẽ treo cờ nếu bạn có chuỗi truy vấn trên các tham chiếu đến nội dung tĩnh. Trong khi nó chắc chắn là một giải pháp tốt cho sự phát triển, nó hoàn toàn không phải là một giải pháp cho sản xuất. Ngoài ra, trình duyệt kiểm soát bộ nhớ đệm, không phải máy chủ. Máy chủ chỉ đơn giản là SUGGESTS khi cần được làm mới; một trình duyệt KHÔNG PHẢI lắng nghe máy chủ (và thường không). Thiết bị di động là một ví dụ điển hình của việc này.
Nate I

113

Plugin mod_pagespeed của Google cho apache sẽ tự động phiên bản cho bạn. Nó thực sự trơn tru.

Nó phân tích HTML trên đường ra khỏi máy chủ web (hoạt động với PHP, rails, python, HTML tĩnh - bất cứ thứ gì) và viết lại các liên kết đến CSS, JS, các tệp hình ảnh để chúng bao gồm mã id. Nó phục vụ các tệp tại các URL đã sửa đổi với điều khiển bộ đệm rất dài trên chúng. Khi các tệp thay đổi, nó sẽ tự động thay đổi các URL để trình duyệt phải tìm nạp lại chúng. Về cơ bản nó chỉ hoạt động, không có bất kỳ thay đổi nào đối với mã của bạn. Nó thậm chí sẽ thu nhỏ mã của bạn trên đường ra.


1
Điều đó thật tuyệt, nhưng vẫn đang trong giai đoạn thử nghiệm. Nó có thể được sử dụng cho dịch vụ doanh nghiệp?
Sanghyun Lee

26
Đây là SAI (tự động thay đổi nguồn) khi nó rõ ràng là một vấn đề của trình duyệt. Cung cấp cho chúng tôi (nhà phát triển) một chương trình làm sạch não thực sự: <ctrl> + F5
T4NK3R

25
mod_pagespeed có chức năng tương đương với bước xây dựng / biên dịch hoàn toàn tự động cho html / css / js của bạn. Tôi nghĩ rằng bạn khó có thể tìm thấy bất kỳ nhà phát triển nghiêm túc nào nghĩ rằng hệ thống xây dựng về bản chất là sai, hoặc có bất cứ điều gì sai với nó là hoàn toàn tự động. Sự tương tự của một bản dựng sạch là để xóa bộ nhớ cache của mod_pagespeed: code.google.com/p/modpagespeed/wiki/ tựa ?
Leopd

3
@ T4NK3R mod_pagespeed không phải làm bất cứ điều gì với nguồn của bạn để thực hiện quản lý bộ đệm, nó được đề cập đơn giản rằng nó có thể giúp với những việc như thu nhỏ. Về việc nó có "SAI" hay không, điều đó hoàn toàn chủ quan. Nó có thể sai đối với bạn, nhưng điều đó không có nghĩa là nó thực sự xấu .
Madbreaks

2
Nó cũng hoạt động với nginx mặc dù bạn phải xây dựng nó từ nguồn: developers.google.com/speed/pagespeed/module/
mẹo

93

Thay vì thay đổi phiên bản theo cách thủ công, tôi khuyên bạn nên sử dụng hàm băm MD5 của tệp CSS thực tế.

Vì vậy, URL của bạn sẽ giống như

http://mysite.com/css/[md5_hash_here]/style.css

Bạn vẫn có thể sử dụng quy tắc viết lại để loại bỏ hàm băm, nhưng ưu điểm là bây giờ bạn có thể đặt chính sách bộ đệm của mình thành "bộ đệm vĩnh viễn", vì nếu URL giống nhau, điều đó có nghĩa là tệp không thay đổi.

Sau đó, bạn có thể viết một tập lệnh shell đơn giản để tính toán hàm băm của tệp và cập nhật thẻ của bạn (có thể bạn muốn chuyển nó sang một tệp riêng để đưa vào).

Đơn giản chỉ cần chạy tập lệnh đó mỗi khi CSS thay đổi và bạn ổn. Trình duyệt sẽ CHỈ tải lại các tệp của bạn khi chúng bị thay đổi. Nếu bạn thực hiện chỉnh sửa và sau đó hoàn tác nó, sẽ không có gì khó khăn để tìm ra phiên bản nào bạn cần quay lại để khách truy cập của bạn không tải xuống lại.


1
Thật không may, tôi không biết làm thế nào để thực hiện nó. Tư vấn xin vui lòng ... biết thêm chi tiết ...
Michael Phelps

Một triển khai trong vỏ, hồng ngọc, v.v. sẽ rất tuyệt
Peter

3
Giải pháp rất hay .. nhưng tôi nghĩ rằng việc tiêu tốn băm của tệp trong mỗi yêu cầu tệp (css, js, hình ảnh, html..vv) cho mỗi lần truy cập trang là rất tốn tài nguyên.
DeepBlue

Đây là một giải pháp tiêu chuẩn cho những người sử dụng gói js hoặc css với gulp, grunt hoặc webpack, việc triển khai khác nhau cho mỗi giải pháp, nhưng băm các tệp của bạn như một bước xây dựng là phổ biến và được đề xuất cho các ứng dụng đi kèm hiện đại
Brandon Søren Culley

@DeepBlue - câu trả lời cho biết "chạy tập lệnh đó mỗi khi CSS thay đổi" . Điều đó KHÔNG có trên mỗi lượt truy cập trang. OTOH Câu trả lời bỏ qua các chi tiết chính - làm thế nào hàm băm thay đổi trở thành một phần của URL? Tôi không biết ...
ToolmakerSteve

70

Không chắc chắn tại sao các bạn đang mất quá nhiều đau đớn để thực hiện giải pháp này.

Tất cả những gì bạn cần làm nếu lấy dấu thời gian đã sửa đổi của tệp và nối nó dưới dạng chuỗi truy vấn vào tệp

Trong PHP tôi sẽ làm như sau:

<link href="mycss.css?v=<?= filemtime('mycss.css') ?>" rel="stylesheet">

filemtime là một hàm PHP trả về dấu thời gian đã sửa đổi của tệp.


Bạn chỉ có thể sử dụng mycss.css?1234567890.
Gavin

3
rất thanh lịch, mặc dù tôi đã chút thay đổi nó để <link rel="stylesheet" href="mycss.css?<?php echo filemtime('mycss.css') ?>"/>, chỉ trong trường hợp một số tranh cãi về chủ đề này về bộ nhớ đệm URL với các biến GET (ở định dạng các gợi ý) là chính xác
luke_mclachlan

xa hơn với bình luận cuối cùng của tôi, tôi đã thấy rằng wordpress sử dụng ?ver=để ai biết!
luke_mclachlan

Giải pháp tuyệt vời. Ngoài ra, tôi thấy rằng thời gian quay phim không hoạt động đối với một tên miền đủ điều kiện (FQDN) nên tôi đã sử dụng FQDN cho phần href và $ _SERVER ["DOCUMENT_ROOT"] cho phần thời gian quay phim. EX: <link rel = "styleheet" href = "http: //theurl/mycss.css? V = <? Php echo filemtime ($ _ SERVER [" DOCUMENT_ROOT "]. '/Mycss.css')?>" />
rrtx2000

Cảm ơn rất nhiều. Đơn giản và tốt. Đây là trong Python: progpath = os.path.dirname (sys.argv [0]) def versionize (file): timestamp = os.path.getmtime ('% s /../ web /% s'% (progpath , tệp)) trả về '% s? v =% s'% (tệp, dấu thời gian) in <link href = "% s" rel = "bản định kiểu" '' type = "text / css" /> '\% versionize ( 'css / main.css')
dlink

52

Bạn chỉ có thể đặt ?foo=1234vào cuối quá trình nhập css / js của mình, thay đổi 1234 thành bất cứ điều gì bạn thích. Có một cái nhìn vào nguồn html SO cho một ví dụ.

Ý tưởng đó là gì? dù sao thì các tham số sẽ bị loại bỏ / bỏ qua yêu cầu và bạn có thể thay đổi số đó khi bạn tung ra một phiên bản mới.


Lưu ý: Có một số đối số liên quan đến chính xác làm thế nào điều này ảnh hưởng đến bộ nhớ đệm. Tôi tin rằng ý chính chung của nó là các yêu cầu GET, có hoặc không có tham số nên được lưu trong bộ nhớ cache, vì vậy giải pháp trên sẽ hoạt động.

Tuy nhiên, tùy thuộc vào cả máy chủ web để quyết định xem nó có muốn tuân thủ phần đó của thông số kỹ thuật và trình duyệt mà người dùng sử dụng hay không, vì dù sao nó cũng có thể đi trước và yêu cầu phiên bản mới.


Vô lý. Chuỗi truy vấn (còn gọi là tham số GET) là một phần của URL. Họ có thể, và sẽ được lưu trữ. Đây là một giải pháp tốt.
troelskn

9
@troelskn: Thông số HTTP 1.1 nói khác (đối với các yêu cầu GET và HEAD với các tham số truy vấn): bộ nhớ cache KHÔNG PHẢI xử lý các phản hồi cho các URI đó như mới trừ khi máy chủ cung cấp thời gian hết hạn rõ ràng. Xem w3.org/Prot Protocol / rfc2616 / rfc2616
Michael Johnson

4
Tôi đã thử loại chuỗi truy vấn của phiên bản với tất cả các trình duyệt chính và chúng có lưu bộ đệm vào tệp, thông số kỹ thuật hay không. Tuy nhiên, tôi nghĩ tốt hơn là sử dụng định dạng style.TIMESTAMP.css mà không lạm dụng các chuỗi truy vấn vì vẫn có khả năng bộ nhớ cache phần mềm proxy S NOT KHÔNG lưu tệp.
Tomas Andrle

34
Đáng chú ý, vì bất kỳ lý do gì, chính Stackoverflow đó sử dụng phương thức chuỗi truy vấn.
jason

2
Đã xác minh rằng việc sử dụng? = Tham số sẽ không khiến trình duyệt tìm nạp lại tệp đã lưu trong bộ nhớ cache khi tham số thay đổi. Cách duy nhất là tự thay đổi tên tệp theo chương trình ở cuối máy chủ như được trả lời bởi Kip
arunskrish

41

Tôi đã nghe điều này được gọi là "phiên bản tự động". Phương pháp phổ biến nhất là bao gồm mtime của tệp tĩnh ở đâu đó trong URL và loại bỏ nó bằng cách sử dụng trình xử lý viết lại hoặc confs URL:

Xem thêm:


3
Cảm ơn, tôi đoán đây là một trường hợp khác mà ý tưởng của tôi đã được thảo luận, tôi chỉ không biết nó được gọi là gì nên tôi không bao giờ tìm thấy nó trên các tìm kiếm của Google.
Kip

27

30 câu trả lời hiện có là lời khuyên tuyệt vời cho một trang web vào khoảng năm 2008. Tuy nhiên, khi nói đến một ứng dụng một trang hiện đại (SPA), có lẽ đã đến lúc bạn nên suy nghĩ lại một số giả định cơ bản, cụ thể là ý tưởng rằng máy chủ web mong muốn chỉ phục vụ phiên bản duy nhất, gần đây nhất của một tập tin.

Hãy tưởng tượng bạn là người dùng có phiên bản M của một SPA được tải vào trình duyệt của bạn:

  1. Đường ống CD của bạn triển khai phiên bản N mới của ứng dụng lên máy chủ
  2. Bạn điều hướng trong SPA, nơi gửi XHR đến máy chủ để nhận /some.template
    • (Trình duyệt của bạn chưa làm mới trang, vì vậy bạn vẫn đang chạy phiên bản M )
  3. Máy chủ phản hồi với nội dung của /some.template- bạn có muốn nó trả về phiên bản M hoặc N của mẫu không?

Nếu định dạng /some.templatethay đổi giữa các phiên bản MN (hoặc tệp được đổi tên hoặc bất cứ thứ gì), bạn có thể không muốn phiên bản N của mẫu được gửi tới trình duyệt chạy phiên bản M cũ của trình phân tích cú pháp .

Các ứng dụng web gặp phải vấn đề này khi hai điều kiện được đáp ứng:

  • Tài nguyên được yêu cầu không đồng bộ đôi khi sau khi tải trang ban đầu
  • Logic ứng dụng giả định những điều (có thể thay đổi trong các phiên bản trong tương lai) về nội dung tài nguyên

Khi ứng dụng của bạn cần phân phát song song nhiều phiên bản, việc giải quyết bộ đệm và "tải lại" trở nên tầm thường:

  1. Cài đặt tất cả các tệp trang web vào các thư mục được phiên bản : /v<release_tag_1>/…files…,/v<release_tag_2>/…files…
  2. Đặt tiêu đề HTTP để cho phép trình duyệt lưu tệp vĩnh viễn
    • (Hoặc tốt hơn nữa, đặt mọi thứ vào CDN)
  3. Cập nhật tất cả <script><link>các thẻ, v.v. để trỏ đến tệp đó trong một trong các thư mục được phiên bản

Bước cuối cùng đó nghe có vẻ khó khăn, vì nó có thể yêu cầu gọi trình tạo URL cho mỗi URL trong mã phía máy chủ hoặc phía máy khách của bạn. Hoặc bạn có thể sử dụng <base>thẻ một cách thông minh và thay đổi phiên bản hiện tại ở một nơi.

Một cách để giải quyết vấn đề này là phải tích cực buộc trình duyệt tải lại mọi thứ khi một phiên bản mới được phát hành. Nhưng vì mục đích để cho bất kỳ hoạt động đang thực hiện nào hoàn thành, có thể vẫn dễ dàng nhất để hỗ trợ ít nhất hai phiên bản song song: v-current và v-trước.


Michael - bình luận của bạn rất phù hợp. Tôi cam ở đây chính xác cố gắng tìm một giải pháp cho SPA của tôi. Tôi có một số gợi ý, nhưng phải tự đưa ra giải pháp. Cuối cùng, tôi thực sự hài lòng với những gì tôi nghĩ ra nên tôi đã viết một bài đăng trên blog và một câu trả lời cho câu hỏi này (bao gồm cả mã). Cảm ơn các con trỏ
statler

Nhận xét tuyệt vời. Tôi không thể hiểu trong khi mọi người cứ nói về việc phá bộ đệm và bộ đệm HTTP là giải pháp thực sự cho các vấn đề về bộ đệm của các trang web mà không gặp phải các vấn đề mới của các SPA, như thể đây là một trường hợp ngoài lề.
David Casillas

1
Phản ứng tuyệt vời và chiến lược hoàn toàn lý tưởng! Và điểm thưởng cho việc đề cập đến basethẻ! Đối với việc hỗ trợ mã cũ: đây không phải là một khả năng, cũng không phải luôn luôn là một ý tưởng tốt. Các phiên bản mã mới có thể hỗ trợ phá vỡ các thay đổi đối với các phần khác của ứng dụng hoặc có thể liên quan đến các bản sửa lỗi khẩn cấp, các bản vá lỗ hổng, v.v. Tôi vẫn chưa tự mình thực hiện chiến lược này, nhưng tôi luôn cảm thấy kiến ​​trúc tổng thể nên cho phép các nhà triển khai gắn thẻ một phiên bản cũ obsoletevà buộc tải lại lần sau khi một cuộc gọi không đồng bộ được thực hiện (hoặc chỉ thực hiện hủy tất cả các phiên thông qua WebSockets ).
Jonny Asmar

Rất vui khi thấy một câu trả lời được suy nghĩ tốt liên quan đến các ứng dụng trang đơn.
Nate I

Đó là "triển khai màu xanh lam" nếu bạn muốn tìm kiếm thêm thông tin.
Fil

15

Không sử dụng foo.css? Phiên bản = 1! Các trình duyệt không được yêu cầu lưu trữ URL với các biến GET. Theo http: //www.thinkv Vitamin.com/features/webapps/serving-javascript-fast , mặc dù IE và Firefox bỏ qua điều này, Opera và Safari thì không! Thay vào đó, sử dụng foo.v1234.css và sử dụng quy tắc viết lại để loại bỏ số phiên bản.


1
Trước hết các trình duyệt không lưu cache, đó là chức năng của HTTP. Tại sao http quan tâm đến cấu trúc của một URI? Có một tài liệu tham khảo nào cho một thông số kỹ thuật nói rằng bộ đệm HTTP sẽ hiểu ngữ nghĩa của một URI để nó không lưu các mục trong bộ đệm với một chuỗi truy vấn không?
AnthonyWJones

13
Trình duyệt web bao gồm chức năng của các đối tượng lưu trữ (kiểm tra thư mục bộ đệm của trình duyệt của bạn). HTTP là một giao thức bao gồm các chỉ thị từ máy chủ đến máy khách (proxy, trình duyệt, trình thu, v.v.) đề xuất kiểm soát bộ đệm.
tzot

13

Trong Laravel (PHP), chúng ta có thể thực hiện theo cách rõ ràng và thanh lịch (sử dụng dấu thời gian sửa đổi tệp):

<script src="{{ asset('/js/your.js?v='.filemtime('js/your.js')) }}"></script>

Và tương tự cho CSS

<link rel="stylesheet" href="{{asset('css/your.css?v='.filemtime('css/your.css'))}}">

Ví dụ đầu ra html ( filemtimethời gian trả về dưới dạng dấu thời gian Unix )

<link rel="stylesheet" href="assets/css/your.css?v=1577772366">

đầu ra của lệnh này trong html là gì? Và nếu tôi chỉ cần gia hạn các phiên bản như? V = 3 ,? V = 4, v.v. - Không bắt buộc trình duyệt tải css mỗi khi người dùng vào trang web
Gediminas

filemtime : "Hàm này trả về thời gian các khối dữ liệu của tệp được ghi vào, nghĩa là thời gian khi nội dung của tệp được thay đổi." src: php.net/manual/en/function.filemtime.php
Kamil Kiełczewski

11

RewriteRule cần một bản cập nhật nhỏ cho các tệp js hoặc css có chứa phiên bản ký hiệu dấu chấm ở cuối. Ví dụ: json-1.3.js.

Tôi đã thêm một lớp phủ định dấu chấm [^.] Vào regex vì vậy .number. bị bỏ qua.

RewriteRule ^(.*)\.[^.][\d]+\.(css|js)$ $1.$2 [L]

2
Cảm ơn các đầu vào! Kể từ khi tôi viết bài đăng này, tôi cũng đã bị đốt cháy bởi điều này. Giải pháp của tôi là chỉ viết lại nếu phần cuối của tên tệp chứa chính xác mười chữ số. (10 chữ số bao gồm tất cả các dấu thời gian từ 9/9/2001 đến 11/20/2286.) Tôi đã cập nhật câu trả lời của mình để bao gồm regex này:^(.*)\.[\d]{10}\.(css|js)$ $1.$2
Kip

Tôi hiểu regex, nhưng tôi không hiểu bạn đang giải quyết vấn đề gì [^.]ở đây. Ngoài ra, không có lợi ích gì khi viết \dbên trong lớp nhân vật - \d+sẽ làm điều tương tự. Như đã đăng, mẫu của bạn sẽ khớp với bất kỳ số lượng ký tự nào (tham lam), sau đó là một dấu chấm, sau đó là một dấu chấm, rồi một hoặc nhiều chữ số, sau đó là một dấu chấm, sau đó css, hoặc jscuối tên tệp. Không khớp với đầu vào mẫu của bạn: regex101.com/r/RPGC62/1
mickmackusa

10

Đối với ASP.NET 4.5 trở lên, bạn có thể sử dụng gói script .

Yêu cầu http://localhost/MvcBM_time/bundles/AllMyScripts?v=r0sLDicvP58AIXN_mc3QdyVvVj5euZNzdsa2N1PKvb81dành cho gói AllMyScripts và chứa cặp chuỗi truy vấn v = r0sLDicvP58AIXN_mc3QdyVvVj5euZNzdsa2N1PKvb81. Chuỗi truy vấn v có mã thông báo giá trị là mã định danh duy nhất được sử dụng để lưu trữ. Miễn là gói không thay đổi, ứng dụng ASP.NET sẽ yêu cầu gói AllMyScripts sử dụng mã thông báo này. Nếu bất kỳ tệp nào trong gói thay đổi, khung tối ưu hóa ASP.NET sẽ tạo mã thông báo mới, đảm bảo rằng các yêu cầu trình duyệt cho gói sẽ nhận được gói mới nhất.

Có các lợi ích khác để đóng gói bao gồm tăng hiệu suất khi tải trang lần đầu với thu nhỏ.


Xin hãy giúp tôi Tôi không thực hiện bất kỳ thay đổi nào trong bundle.config chỉ thay đổi trong các tệp css hoặc js thì làm cách nào để giải quyết vấn đề bộ đệm?
vedankita kumbhar

10

Đây là một giải pháp JavaScript thuần túy

(function(){

    // Match this timestamp with the release of your code
    var lastVersioning = Date.UTC(2014, 11, 20, 2, 15, 10);

    var lastCacheDateTime = localStorage.getItem('lastCacheDatetime');

    if(lastCacheDateTime){
        if(lastVersioning > lastCacheDateTime){
            var reload = true;
        }
    }

    localStorage.setItem('lastCacheDatetime', Date.now());

    if(reload){
        location.reload(true);
    }

})();

Ở trên sẽ tìm kiếm lần cuối cùng người dùng truy cập trang web của bạn. Nếu lần truy cập trước là trước khi bạn phát hành mã mới, nó sẽ sử dụng location.reload(true)để buộc làm mới trang từ máy chủ.

Tôi thường có đoạn mã này là tập lệnh đầu tiên trong phạm vi <head>để nó được đánh giá trước khi tải bất kỳ nội dung nào khác. Nếu tải lại cần phải xảy ra, người dùng hầu như không nhận thấy.

Tôi đang sử dụng bộ nhớ cục bộ để lưu dấu thời gian truy cập cuối cùng trên trình duyệt, nhưng bạn có thể thêm cookie vào hỗn hợp nếu bạn đang muốn hỗ trợ các phiên bản IE cũ hơn.


Tôi đã thử một cái gì đó như thế này, nó sẽ chỉ hoạt động trên trang được tải lại, nhưng nếu trang web có nhiều trang chia sẻ cùng css / hình ảnh thì các trang khác vẫn sẽ sử dụng tài nguyên cũ.
DeepBlue

9

Bài viết thú vị. Đã đọc tất cả các câu trả lời ở đây kết hợp với thực tế là tôi chưa bao giờ có bất kỳ vấn đề nào với chuỗi truy vấn "không có thật" (tôi không chắc tại sao mọi người lại miễn cưỡng sử dụng điều này) Tôi đoán giải pháp (loại bỏ sự cần thiết phải viết lại quy tắc apache như trong câu trả lời được chấp nhận) là tính HASH ngắn của nội dung tệp CSS (thay vì datetime tệp) dưới dạng chuỗi truy vấn không có thật.

Điều này sẽ dẫn đến kết quả như sau:

<link rel="stylesheet" href="/css/base.css?[hash-here]" type="text/css" />

Tất nhiên các giải pháp datetime cũng hoàn thành công việc trong trường hợp chỉnh sửa tệp CSS nhưng tôi nghĩ đó là về nội dung tệp css chứ không phải về datetime tệp, vậy tại sao chúng lại bị lẫn lộn?


8

Đối với sự phát triển của tôi, tôi thấy rằng chrome có một giải pháp tuyệt vời.

https://developer.chrome.com/devtools/docs/tips-and-tricks#hard-reload

Khi các công cụ dành cho nhà phát triển mở ra, chỉ cần nhấp vào nút refresh và thả ra một khi bạn di chuột qua "Bộ nhớ cache trống và Tải lại cứng".

Đây là người bạn tốt nhất của tôi, và là một cách siêu nhẹ để có được những gì bạn muốn!


Và nếu bạn đang sử dụng Chrome làm môi trường phát triển của mình, một giải pháp không xâm lấn khác là vô hiệu hóa bộ đệm: Trong cog Cài đặt, bạn có thể vô hiệu hóa bộ đệm đĩa bằng cách chọn 'Tắt bộ đệm' (lưu ý: DevTools phải hiển thị / mở để làm việc này).
Velojet

7

Cảm ơn tại Kip cho giải pháp hoàn hảo của mình!

Tôi đã mở rộng nó để sử dụng nó như một Zend_view_Helper. Bởi vì khách hàng của tôi chạy trang của mình trên một máy chủ ảo, tôi cũng đã mở rộng nó cho điều đó.

Hy vọng nó sẽ giúp người khác quá.

/**
 * Extend filepath with timestamp to force browser to
 * automatically refresh them if they are updated
 *
 * This is based on Kip's version, but now
 * also works on virtual hosts
 * @link http://stackoverflow.com/questions/118884/what-is-an-elegant-way-to-force-browsers-to-reload-cached-css-js-files
 *
 * Usage:
 * - extend your .htaccess file with
 * # Route for My_View_Helper_AutoRefreshRewriter
 * # which extends files with there timestamp so if these
 * # are updated a automatic refresh should occur
 * # RewriteRule ^(.*)\.[^.][\d]+\.(css|js)$ $1.$2 [L]
 * - then use it in your view script like
 * $this->headLink()->appendStylesheet( $this->autoRefreshRewriter($this->cssPath . 'default.css'));
 *
 */
class My_View_Helper_AutoRefreshRewriter extends Zend_View_Helper_Abstract {

    public function autoRefreshRewriter($filePath) {

        if (strpos($filePath, '/') !== 0) {

            // path has no leading '/'
            return $filePath;
        } elseif (file_exists($_SERVER['DOCUMENT_ROOT'] . $filePath)) {

            // file exists under normal path
            // so build path based on this
            $mtime = filemtime($_SERVER['DOCUMENT_ROOT'] . $filePath);
            return preg_replace('{\\.([^./]+)$}', ".$mtime.\$1", $filePath);
        } else {

            // fetch directory of index.php file (file from all others are included)
            // and get only the directory
            $indexFilePath = dirname(current(get_included_files()));

            // check if file exist relativ to index file
            if (file_exists($indexFilePath . $filePath)) {

                // get timestamp based on this relativ path
                $mtime = filemtime($indexFilePath . $filePath);

                // write generated timestamp to path
                // but use old path not the relativ one
                return preg_replace('{\\.([^./]+)$}', ".$mtime.\$1", $filePath);
            } else {

                return $filePath;
            }
        }
    }

}

Chúc mừng và cảm ơn.


7

Không tìm thấy cách tiếp cận DOM phía máy khách tạo phần tử nút script (hoặc css) một cách linh hoạt:

<script>
    var node = document.createElement("script"); 
    node.type = "text/javascript";
    node.src = 'test.js?'+Math.floor(Math.random()*999999999);
    document.getElementsByTagName("head")[0].appendChild(node);
</script>

6

google chrome có tùy chọn Tải lại cứng cũng như Lưu trữ trống và Tải lại cứng. Bạn có thể nhấp và giữ nút tải lại (Trong Chế độ kiểm tra) để chọn một.


Để làm rõ, bởi "Kiểm tra Chế độ", tức là nói tới "Dev Tools" aka F12, aka ctrl + shift + i, aka ant menu> More Tools> Developer Tools, aka right click> Inspect Element. Ngoài ra còn có một thiết lập được chôn ở đâu đó trong các công cụ dev (tôi quên vị trí) để tải lại cứng trên mỗi lần tải lại.
Jonny Asmar

5

Bạn có thể buộc "bộ nhớ đệm toàn phiên" nếu bạn thêm id phiên làm tham số không chính xác của tệp js / css:

<link rel="stylesheet" src="myStyles.css?ABCDEF12345sessionID" />
<script language="javascript" src="myCode.js?ABCDEF12345sessionID"></script>

Nếu bạn muốn bộ đệm ẩn toàn phiên bản, bạn có thể thêm một số mã để in ngày tệp hoặc tương tự. Nếu bạn đang sử dụng Java, bạn có thể sử dụng thẻ tùy chỉnh để tạo liên kết một cách trang nhã.

<link rel="stylesheet" src="myStyles.css?20080922_1020" />
<script language="javascript" src="myCode.js?20080922_1120"></script>

5

Giả sử bạn có một tệp có sẵn tại:

/styles/screen.css

bạn có thể nối thêm một tham số truy vấn với thông tin phiên bản vào URI, ví dụ:

/styles/screen.css?v=1234

hoặc bạn có thể thêm thông tin phiên bản, ví dụ:

/v/1234/styles/screen.css

IMHO phương pháp thứ hai tốt hơn cho các tệp CSS vì chúng có thể tham chiếu đến hình ảnh bằng các URL tương đối, điều đó có nghĩa là nếu bạn chỉ định background-imagenhư vậy:

body {
    background-image: url('images/happy.gif');
}

URL của nó sẽ có hiệu quả là:

/v/1234/styles/images/happy.gif

Điều này có nghĩa là nếu bạn cập nhật số phiên bản được sử dụng, máy chủ sẽ coi đây là tài nguyên mới và không sử dụng phiên bản được lưu trong bộ nhớ cache. Nếu bạn căn cứ số phiên bản của mình vào Subversion / CVS / vv. sửa đổi điều này có nghĩa là những thay đổi đối với hình ảnh được tham chiếu trong tệp CSS sẽ được chú ý. Đó là không được bảo đảm với các chương trình đầu tiên, tức là URL images/happy.gifliên quan đến /styles/screen.css?v=1235/styles/images/happy.gifmà không chứa bất kỳ thông tin phiên bản.

Tôi đã triển khai một giải pháp lưu trữ bằng cách sử dụng kỹ thuật này với các máy chủ Java và chỉ cần xử lý các yêu cầu /v/*với một máy chủ ủy nhiệm cho tài nguyên cơ bản (tức là /styles/screen.css). Trong chế độ phát triển tôi thiết lập bộ nhớ đệm header mà nói với khách hàng để luôn luôn kiểm tra độ tươi của tài nguyên với máy chủ (điều này thường dẫn đến một 304 nếu bạn uỷ thác cho nhân Tomcat DefaultServlet.css, .jsvv tập tin đã không thay đổi) khi ở chế độ triển khai Tôi đặt tiêu đề cho biết "bộ nhớ cache mãi mãi".


Chỉ cần thêm một thư mục mà bạn có thể đổi tên khi cần thiết sẽ hoạt động nếu bạn chỉ sử dụng các URL tương đối. Và sau đó bạn đảm bảo chuyển hướng đến thư mục thích hợp từ thư mục cơ sở, tức là trong PHP : <?php header( 'Location: folder1/login.phtml' ); ?>.
Gruber

1
Sử dụng phương pháp thứ hai, một thay đổi đối với CSS sẽ làm mất hiệu lực các bản sao được lưu trong bộ nhớ cache của tất cả các hình ảnh được tham chiếu với các URL tương đối, có thể hoặc không thể mong muốn.
TomG

5

Bạn chỉ có thể thêm một số số ngẫu nhiên với url CSS / JS như

example.css?randomNo=Math.random()

5

Đối với ASP.NET tôi cho rằng giải pháp tiếp theo với các tùy chọn nâng cao (chế độ gỡ lỗi / phát hành, phiên bản):

Các tệp Js hoặc Css được bao gồm theo cách đó:

<script type="text/javascript" src="Scripts/exampleScript<%=Global.JsPostfix%>" />
<link rel="stylesheet" type="text/css" href="Css/exampleCss<%=Global.CssPostfix%>" />

Global.JsPostfix và Global.CssPostfix được tính theo cách sau trong Global.asax:

protected void Application_Start(object sender, EventArgs e)
{
    ...
    string jsVersion = ConfigurationManager.AppSettings["JsVersion"];
    bool updateEveryAppStart = Convert.ToBoolean(ConfigurationManager.AppSettings["UpdateJsEveryAppStart"]);
    int buildNumber = System.Reflection.Assembly.GetExecutingAssembly().GetName().Version.Revision;
    JsPostfix = "";
#if !DEBUG
    JsPostfix += ".min";
#endif      
    JsPostfix += ".js?" + jsVersion + "_" + buildNumber;
    if (updateEveryAppStart)
    {
        Random rand = new Random();
        JsPosfix += "_" + rand.Next();
    }
    ...
}

4

Gần đây tôi đã giải quyết điều này bằng Python. Ở đây mã (nên dễ dàng chấp nhận cho các ngôn ngữ khác):

def import_tag(pattern, name, **kw):
    if name[0] == "/":
        name = name[1:]
    # Additional HTML attributes
    attrs = ' '.join(['%s="%s"' % item for item in kw.items()])
    try:
        # Get the files modification time
        mtime = os.stat(os.path.join('/documentroot', name)).st_mtime
        include = "%s?%d" % (name, mtime)
        # this is the same as sprintf(pattern, attrs, include) in other
        # languages
        return pattern % (attrs, include)
    except:
        # In case of error return the include without the added query
        # parameter.
        return pattern % (attrs, name)

def script(name, **kw):
    return import_tag("""<script type="text/javascript" """ +\
        """ %s src="/%s"></script>""", name, **kw)

def stylesheet(name, **kw):
    return import_tag('<link rel="stylesheet" type="text/css" ' +\
        """%s href="/%s">', name, **kw) 

Mã này về cơ bản sẽ thêm dấu thời gian của tệp dưới dạng tham số truy vấn vào URL. Cuộc gọi của hàm sau

script("/main.css")

sẽ cho kết quả

<link rel="stylesheet" type="text/css"  href="/main.css?1221842734">

Ưu điểm của khóa học là bạn không bao giờ phải thay đổi html của mình nữa, chạm vào tệp CSS sẽ tự động kích hoạt tính năng vô hiệu hóa bộ đệm. Hoạt động rất tốt và chi phí không đáng chú ý.


os.stat () có thể tạo ra một nút cổ chai?
hoju

@Richard stat có thể là một nút cổ chai nếu đĩa rất chậm và các yêu cầu rất nhiều. Trong trường hợp đó, bạn có thể lưu dấu thời gian ở đâu đó trong bộ nhớ và xóa bộ đệm này sau mỗi lần triển khai mới. Tuy nhiên, sự phức tạp này sẽ không cần thiết trong phần lớn các trường hợp sử dụng.
pi.

4

Nếu bạn đang sử dụng git + PHP, bạn có thể tải lại tập lệnh từ bộ đệm mỗi lần có thay đổi trong repo git, sử dụng mã sau:

exec('git rev-parse --verify HEAD 2> /dev/null', $gitLog);
echo '  <script src="/path/to/script.js"?v='.$gitLog[0].'></script>'.PHP_EOL;

4

Nếu bạn là nhà phát triển muốn tránh bộ nhớ đệm, tab mạng chrome đã tắt tùy chọn bộ đệm. Nếu không, bạn có thể làm điều đó mà không cần khung kết xuất máy chủ bằng hai thẻ script.

<script type="text/javascript">
    document.write('<script type="text/javascript" src="myfile.js?q=' + Date.now() + '">
    // can't use myfile.js stuff yet
</script>')
<script type="text/javascript">
    // do something with myfile.js
</script>

4

Câu hỏi này là siêu cũ, và xuất hiện điều đầu tiên khi bất kỳ ai giải quyết vấn đề này. Đây không phải là một câu trả lời cho câu hỏi theo cách mà op muốn, thay vào đó là một câu trả lời cho các nhà phát triển với vấn đề này trong khi phát triển và thử nghiệm. Và tôi không thể đăng một câu hỏi mới về chủ đề này vì sẽ được đánh dấu là trùng lặp.

Giống như nhiều người khác, tôi chỉ muốn loại bỏ bộ nhớ đệm một thời gian ngắn.

"keep caching consistent with the file" .. cách của nó quá nhiều rắc rối ..

Nói chung, tôi không ngại tải thêm - thậm chí tải lại các tệp không thay đổi - trên hầu hết các dự án - thực tế không liên quan. Trong khi phát triển một ứng dụng - chúng tôi chủ yếu tải từ đĩa, localhost:port vì vậy - increase in network trafficvấn đề này không phải là vấn đề vi phạm thỏa thuận .

Hầu hết các dự án nhỏ chỉ chơi xung quanh - chúng không bao giờ kết thúc trong sản xuất. Vì vậy, đối với họ bạn không cần thêm gì nữa ..

Như vậy, nếu bạn sử dụng Chrome Dev Tools , bạn có thể làm theo cách tiếp cận vô hiệu hóa bộ đệm này như trong hình dưới đây: Làm thế nào để buộc chrome tải lại các tập tin lưu trữ

Và nếu bạn có vấn đề về bộ nhớ đệm firefox : Làm thế nào để buộc tải lại tài sản trên firefox

Làm cách nào để tắt bộ nhớ đệm trong Firefox khi đang phát triển Chỉ thực hiện điều này khi phát triển, bạn cũng cần một cơ chế để buộc tải lại cho sản xuất, vì người dùng của bạn sẽ sử dụng các mô-đun bị vô hiệu hóa bộ đệm cũ nếu bạn cập nhật ứng dụng thường xuyên và bạn không cung cấp cơ chế đồng bộ hóa bộ đệm chuyên dụng như mô tả trong câu trả lời ở trên.

Vâng, thông tin này đã có trong các câu trả lời trước nhưng tôi vẫn cần phải thực hiện tìm kiếm google để tìm thấy nó.

Hy vọng câu trả lời này rất rõ ràng và bây giờ bạn không cần phải làm vậy.


OP đã hỏi một cái gì đó và trả lời một cái gì đó khác. Đây không phải là về tải lực cục bộ mà là trong sản xuất và bạn không thể yêu cầu người dùng cuối theo dõi ở trên để tắt bộ đệm, v.v.
Jitendra Pancholi

3

Dường như tất cả các câu trả lời ở đây đề xuất một số loại phiên bản trong sơ đồ đặt tên, có nhược điểm của nó.

Các trình duyệt nên nhận thức rõ về những gì cần lưu trữ và những gì không lưu vào bộ đệm bằng cách đọc phản hồi của máy chủ web, đặc biệt là các tiêu đề http - tài nguyên này có hiệu lực trong bao lâu? tài nguyên này có được cập nhật kể từ lần cuối tôi lấy nó không? vân vân.

Nếu mọi thứ được cấu hình 'chính xác', chỉ cần cập nhật các tệp trong ứng dụng của bạn (đôi khi) sẽ làm mới bộ đệm của trình duyệt. Ví dụ, bạn có thể định cấu hình máy chủ web của mình để báo cho trình duyệt không bao giờ lưu trữ tệp (đây là một ý tưởng tồi).

Một lời giải thích sâu hơn về cách thức hoạt động của nó ở đây https://www.mnot.net/cache_docs/#WORK


3

Chỉ cần thêm mã này, nơi bạn muốn thực hiện tải lại cứng (buộc trình duyệt tải lại các tệp CSS / JS được lưu trong bộ nhớ cache) Thực hiện việc này bên trong .load để nó không làm mới như một vòng lặp

 $( window ).load(function() {
   location.reload(true);
});

Không hoạt động trên Chrome. Vẫn đang tải tài sản từ bộ đệm đĩa
Jason Kim

3

Chỉ cần sử dụng mã phía máy chủ để thêm ngày của tệp ... theo cách đó SILL được lưu vào bộ đệm và chỉ được tải lại khi tệp thay đổi

Trong ASP.NET

<link rel="stylesheet" href="~/css/custom.css?d=@(System.Text.RegularExpressions.Regex.Replace(File.GetLastWriteTime(Server.MapPath("~/css/custom.css")).ToString(),"[^0-9]", ""))" />

<script type="text/javascript" src="~/js/custom.js?d=@(System.Text.RegularExpressions.Regex.Replace(File.GetLastWriteTime(Server.MapPath("~/js/custom.js")).ToString(),"[^0-9]", ""))"></script>    

Điều này có thể được đơn giản hóa để:

<script src="<%= Page.ResolveClientUrlUnique("~/js/custom.js") %>" type="text/javascript"></script>

Bằng cách thêm một phương thức mở rộng vào dự án của bạn để mở rộng Trang:

public static class Extension_Methods
{
    public static string ResolveClientUrlUnique(this System.Web.UI.Page oPg, string sRelPath)
    {
        string sFilePath = oPg.Server.MapPath(sRelPath);
        string sLastDate = System.IO.File.GetLastWriteTime(sFilePath).ToString();
        string sDateHashed = System.Text.RegularExpressions.Regex.Replace(sLastDate, "[^0-9]", "");

        return oPg.ResolveClientUrl(sRelPath) + "?d=" + sDateHashed;
    }
}

2

Tôi đề nghị thực hiện quy trình sau:

  • phiên bản các tệp css / js của bạn bất cứ khi nào bạn triển khai, đại loại như: screen.1233.css (số có thể là bản sửa đổi SVN của bạn nếu bạn sử dụng hệ thống tạo phiên bản)

  • giảm thiểu chúng để tối ưu hóa thời gian tải

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.