Як змусити браузер припинити кешування GWT nocache.js

Я розробляю веб-додаток за допомогою GWT і бачу безумну проблему з кешуванням файлу app.nocache.js у браузері, навіть якщо веб-сервер надіслав нову копію файлу!

Я використовую Eclipse для компіляції програми, яка працює в режимі dev. Для тестування режиму виробництва у мене є віртуальна машина (Oracle VirtualBox) з гостьовою ОС Ubuntu, що працює на моїй машині (Windows 7). Я запускаю веб-сервер lighttpd у VM. Віртуальна машина надає спільний доступ до каталогу мого проекту, і веб-сервер обслуговує цей каталог.

Я використовую Chrome як браузер, але те ж саме відбувається і в Firefox.

Ось сценарій:

  • The web page for the app is blank. Accorind to Chrome's "Inspect Element" tool, it's because it is trying fetch 6E89D5C912DD8F3F806083C8AA626B83.cache.html, which doesn't exist (404 not found).
  • I check the war directory, and sure enough, that file doesn't exist.
  • The app.nocache.js on the browser WAS RELOADED from the web server (200 OK), because the file on the server was newer than the browser cache. I verified that file size and timestamp for the new file returned by the server were correct. (This is info Chrome reports about the server's HTTP response)
  • However, if I open the app.nocache.js on the browser, the JavaScript is referring to 6E89D5C912DD8F3F806083C8AA626B83.cache.html!!! That is, even though the web server sent a new app.nocache.js, the browser seems to have ignored that and kept using its cached copy!

  • Goto Google->GWT Compile in Eclipse. Recompile the whole thing.

  • Verify in the war directory that the app.nocache.js was overwritten and has a new timestamp.
  • Reload the page from Chrome and verify once again that the server sent a 200 OK response to the app.nocache.js.
  • The browser once again tries to load 6E89D5C912DD8F3F806083C8AA626B83.cache.html and fails. The browser is still using the old cached copy of app.nocache.js.
  • Made absolutely certain in the war directory that nothing is referring to 6E89D5C912DD8F3F806083C8AA626B83.cache.html (via find and grep)

Що відбувається неправильно? Чому браузер кешує цим файлом nocache.js навіть тоді, коли сервер надсилає йому нову копію?


Ось копія заголовків запиту/відповіді HTTP, коли натискається перезавантаження в браузері. У цьому трафіку вміст сервера не перекомпілювався з часу останнього GET (але зауважимо, що кешована версія nocache.js все ще помилкова!)

Request URL:http://192.168.2.4/xbts_ui/xbts_ui.nocache.js
Request Method:GET
Status Code:304 Not Modified
Request Headersview source
Accept:*/*
Accept-Charset:ISO-8859-1,utf-8;q=0.7,*;q=0.3
Accept-Encoding:gzip,deflate,sdch
Accept-Language:en-US,en;q=0.8
Cache-Control:max-age=0
Connection:keep-alive
Host:192.168.2.4
If-Modified-Since:Thu, 25 Oct 2012 17:55:26 GMT
If-None-Match:"2881105249"
Referer:http://192.168.2.4/XBTS_ui.html
User-Agent:Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.4 (KHTML, like Gecko) Chrome/22.0.1229.94 Safari/537.4
Response Headersview source
Accept-Ranges:bytes
Content-Type:text/javascript
Date:Thu, 25 Oct 2012 20:27:55 GMT
ETag:"2881105249"
Last-Modified:Thu, 25 Oct 2012 17:55:26 GMT
Server:lighttpd/1.4.31
10
додано Автор Andrei Volgin, джерело
До речі, це схоже на stackoverflow .com/questions/3407649/& hellip; , але він не містив жодної інформації, яка допомогла мені вирішити цю проблему.
додано Автор jfritz42, джерело
Так, і здається, що правильна річ відбувається, тому що на цій сторінці написано "достатньо вибірки If-Modified-since". Я можу сказати з інструменту Chrome Inspect, що браузер надіслав "If-Modified-Since: Thu, 25 Oct 2012 17:03:53 GMT" у запит GET, і сервер відповів "Last-Modified: Thu, 25 Oct 2012 17:55:26 GMT "
додано Автор jfritz42, джерело
Додано трейлінг заголовка запиту/відповіді HTTP, щоб зробити його більш зрозумілим для потенційних помічників.
додано Автор jfritz42, джерело
Я підозрюю, що проблема полягає в тому, що веб-переглядач робить припущення щодо часу свіжості файлу nocache.js, а визначення файлу залишається "свіжим". Це відбувається з прочитання розділу 13.2.4 HTC RFC: "Якщо жоден з Expires, Cache-Control: max-age або Cache-Control: s- maxage (див. Розділ 14.9.3) не з'являється у відповіді, і відповідь не включати інші обмеження на кешування, кэш може обчислити час свіжості за допомогою евристики. " (від w3.org/Protocols/rfc2616/rfc2616-sec13.html# sec13 )
додано Автор jfritz42, джерело

6 Відповіді

Найкращий спосіб уникнути кешування веб-переглядача полягає в тому, щоб встановити час закінчення терміну дії, а також додати max-age = 0 і елементи, які необхідно перевірити.

Це конфігурація, яку я використовую з apache-httpd

ExpiresActive on

   ExpiresDefault "now"
   Header set Cache-Control "public, max-age=0, must-revalidate"


   ExpiresDefault "now plus 1 year"

Ваша конфігурація для lighthttpd повинна бути

server.modules = (
    "mod_expire",
    "mod_setenv",
)
...
$HTTP["url"] =~ "\.nocache\." {
  setenv.add-response-header = ( "Cache-Control" => "public, max-age=0, must-revalidate" )
  expire.url = ( "" => "access plus 0 days" )
}

$HTTP["url"] =~ "\.cache\." {
  expire.url = ( "" => "access plus 1 years" )
}
5
додано
Дякую. Я виправив деякі помилки в конфігурації lighttpd. Дякуємо за перенесення конфігурації Apache в lighttpd.
додано Автор jfritz42, джерело

We had a similar issue. We found out that timestamp of the nocache.js was not updated with gwt compile so had to touch the file on build. And then we also applied the fix from @Manolo Carrasco Moñino. I wrote a blog about this issue. http://programtalk.com/java/gwt-nocachejs-cached-by-browser/

Ми використовуємо версію 2.7 GWT, оскільки коментар також вказує.

5
додано
Чудова відповідь. Тепер я дізнався, що Shift + F5 - це тимчасове рішення вперше.
додано Автор Tom, джерело
Час, що не змінюється, це наша проблема. Я вважаю, що це лише помилка в GWT 2.7. Дякуємо за повідомлення в блозі!
додано Автор Craigo, джерело

Є два простих рішення (друге - це модифікована версія першого)

1) Перейменуйте файл * .html, який має посилання на * .nocache.js, тобто на MyProject.html, на MyProject.jsp Тепер шукайте місце розташування сценарію * .nocache.js в MyProject.html

<script language="javascript" src="MyProject/MyProject.nocache.js"></script>

додайте динамічну змінну як параметр для JS-файлу, це гарантує повернення фактичного вмісту з сервера кожного разу. Нижче наведено приклад

<script language="javascript" src="MyProject/MyProject.nocache.jsp?dummyParam=<%= "" + new java.util.Date().getTime() %>"></script>

Пояснення: dummyParam не використовуватиме НІ, але отримає наші намічені результати, тобто повернемо нам 200 код замість 304

Примітка: Якщо ви будете використовувати цю техніку, то вам потрібно переконатися, що ви вказуєте на правий jsp-файл для завантаження вашої програми (до цієї зміни ви завантажували вашу програму за допомогою файлу HTML).

2) Якщо ви не хочете використовувати рішення JSP і хочете дотримуватися вашого html-файлу, то вам буде потрібно java-скрипт для динамічного додавання унікального значення параметра на стороні клієнта при завантаженні файлу nocache. Я припускаю, що тепер не варто робити велику справу за те, що ви вирішили вище.

Я успішно використав першу техніку, сподіваюся, що це допоможе.

3
додано
      
  • Додаток app.nocache.js на веб-переглядачі було перезавантажено з веб-сервера (200 ОК), оскільки файл на сервері був новим, ніж кеш браузера. Я перевірив, що розмір файлу та мітка часу для нового файлу, повернутого сервером, є правильними. (Це інформація про звіти Chrome про відповідь HTTP сервера)
  •   

Я б не покладався на це. Я бачив дещо дивну поведінку в інструментах розробки Chrome з вкладкою мережі в комбінації з кешуванням (принаймні, це не 100% прозорість для мене). У разі сумнівів, я, як правило, досі звертаюся до Firebug.

Тому, можливо, Chrome все ще використовує стару версію. Можливо, давно вирішили, що йому ніколи більше не доведеться перезавантажувати ресурс. Очищення кешу має вирішити цю проблему. Переконайтеся, що перед перезавантаженням сторінки встановлено правильні заголовки кешування, див. Ідеальні заголовки керування кешем HTTP для різних типів ресурсів .

2
додано

Після безуспішного запобігання кешуванню через Apache я створив bash-скрипт, котрий корінь запускає кожну хвилину в cron завдання на моєму сервері Linux Tomcat.

#!/bin/bash
#
# Touches GWT nocache.js files in the Tomcat web app directory to prevent caching.
# Execute this script every minute in a root cron job.
#
cd /var/lib/tomcat7/webapps
find . -name '*nocache.js' | while read file; do
    logger "Touching file '$file'"
    touch "$file"
done
1
додано
Використання кореневого скрипта для того, щоб торкнутися файлу, який обслуговує ваш веб-сервер, дійсно погана ідея - esp. тому що ви повинні робити це, щоб забезпечити вміст подається з належними HTTP-заголовками замість цього (ваш сервер навіть не запитається, якщо браузер - або проміжний проксі-сервер - кешував вміст добросовісно).
додано Автор R4zorax, джерело

Відкрийте сторінку в когнітному режимі лише для того, щоб позбутися проблеми кешу та розблокувати себе.

Вам потрібно налаштувати час кешу, як зазначено в інших коментарях.

0
додано