Робота з кешем браузера в односторінкових додатках


27

Я намагаюся розібратися, як правильно обробляти кеш веб-браузера для програм на одній сторінці.

У мене досить типовий дизайн: кілька файлів HTML, JS та CSS, що реалізують SPA, і купа даних JSON, які споживаються SPA. Проблеми виникають, коли я хочу натиснути оновлення: я оновлюю статичну частину сайту та код, який генерує JSON одночасно, але клієнтські браузери часто мають статичну кешовану частину, тому старий код намагається обробити нові дані та може (залежно від внесених змін) виникнути в проблемах. (Зокрема, IE здається більш агресивним, ніж Chrome або Firefox щодо використання кешованого JS без повторної перевірки.)

Який найкращий спосіб впоратися з цим?

  1. Переконайтесь, що мої зміни JSON сумісні з зворотним ходом, і припускайте, що кеш-пам’яті браузера закінчуються в розумні часові рамки.
  2. Вставте якийсь номер версії в статичний JS та JSON, а потім виконайте, window.location.reload(true);якщо вони не збігаються.
  3. Визначте відповідну комбінацію заголовків ( must-revalidateабо no-cacheбудь-яких інших; джерела залежать від того, як це зробити), щоб переконатися, що веб-переглядачі завжди оновлюють усі ресурси при кожному завантаженні, навіть якщо це означає кілька додаткових турів для завантаження сайту.
  4. Мікро-керування кеш-керуванням та закінчує термін дії заголовків, щоб статичний вміст закінчувався, коли я хочу натиснути оновлення.
  5. Щось ще?

1
Чули, що №3 та №4 несподівано не спрацьовують у вбудованих елементах керування веб-браузером, якщо ваше середовище є злим ( кашель iOS) від колег. №1 і №2 можуть бути вибором рівня додатків, але все ж можуть (?) Викликати проблеми з кешем для інших ресурсів або для часткового завантаження ресурсів. Єдине, що я бачив надійно працювати у готовому до виробництва коді - це отримання yoururl.html? <SomeTimeStamp>, оскільки це дозволить підробити більшість механізмів кешування. Бонус: згорніть весь веб-додаток у файл, щоб завантажувати атомно або успішно. Знизу: найкраще працює на локальному посиланні. Ваш пробіг може відрізнятися. Удачі!
J Trana

2
+1 до використання номера версії або часової позначки в якості параметра URL для ресурсів.
9000

Відповіді:


14

Вам потрібно розв’язання кешу . Роль перебору кешу:

  1. Перейменуйте ресурси на унікальне ім’я залежно від їх вмісту.
  2. Оновіть усі посилання на ці ресурси.

У проекті, що базується на Grunt, звичайно використовувати grunt-rev, щоб усі файли, які потребують оновлення, отримали унікальні імена, виходячи з їх вмісту.

Якщо ви гарантуєте, що ваші файли JSON отримують файли кеш-пам'яті разом із посиланнями на них у вашому Javascript, клієнти завжди завантажуватимуть файли JSON, на які очікує Javascript.

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

Очевидно, це та річ, яку ви хочете автоматизувати як частину складання виробництва вашого проекту, тому вам не доведеться стежити за зміною імен файлів та посилань вручну.


2
+1 за курсив "busting" кеша, який відкриває двері, щоб насправді продуктивно гуглити цей матеріал.
Зак Кус

@ Ted Percival - yeoman Framework робить це, чим я користуюся, але я бачу проблему. коли я випускаю нову збірку, у веб-переглядача може бути індекс керований з посиланням на старі файли index.html ... і браузер отримує помилку. як я повинен це виправити? (A.) символізує всі старі імена файлів до нових (це працює) (B.) додайте заголовок no-cache до index.html (але це завжди дотримується) (C.) додайте .htaccess для розпізнавання файлу, що відновлюється і шукайте базовий (тобто 12345.main.js -> main.js)
час

5

Ви можете використовувати if-modified-since + last-modifiedабо if-none-match + etagзаголовки разом із належним cache-controlзаголовком. (Можуть бути помилки в браузері , але нічого, чим ви не можете керувати в останніх браузерах.)

Якщо файли статичні, я пропоную вам скористатися if-modified-since, оскільки це можна зробити автоматично з добре налаштованим сервером HTTP. Він повинен відправити назад 304, якщо файл не змінено з моменту останнього завантаження.

Я не думаю, що ваші №1 і №2 будуть працювати довгостроково. №3 або №4 можуть працювати. №3 простіше, але вам доведеться навчитися вирішувати цю проблему лише один раз. Тож я б спробував №4, якби я був ти, але рішення може залежати від того, якими браузерами користуються ваші клієнти ... Наприклад, у IE8 є проблеми з оновленням кеша ajax тощо.


2

Якщо ви можете включити фільтр сервлетів Java у свій SPA, ось робоче рішення: CorrectBrowserCacheHandlerFilter.java

В основному, коли ваш браузер запитує статичні файли, сервер буде перенаправляти всі запити на той самий, але з параметром хеш-запиту ( ?v=azErTнаприклад), який залежить від вмісту цільового статичного файлу.

Роблячи це, браузер ніколи не кешуватиме статичні файли, оголошені у вашому, index.htmlнаприклад (тому, що він завжди отримує 302 Moved Temporarily), а кешуватиме лише ті, що мають хеш-версію (сервер відповість 200за них). Таким чином кеш браузера буде ефективно використовуватися для тих статичних файлів з хеш-версією.

Відмова: Я автор автора CorrectBrowserCacheHandlerFilter.java.

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.