Как я могу принудительно обновить клиенты SPA, если есть новая сборка?

У меня есть одностраничное приложение, и мне нужно, чтобы клиенты были в последней версии. Кэширование является агрессивным, поэтому ждать, пока они станут недействительными, невозможно.

Есть ли способ сказать клиенту посмотреть ресурс (скажем, что-то вроде build.txt), и если этот ресурс содержит номер сборки больше, чем текущий загруженный, аннулировать кеш и обновить?

У меня было промежуточное ПО, которое прикрепляло текущий идентификатор фиксации git в качестве заголовка ко всем ответам API. Если он изменился, я сделал полную перезагрузку. Возможно, что-то в этом духе?

ceejayoz 30.05.2019 02:42

Просто используя location.reload()?

David Alsh 30.05.2019 02:49

В моем случае да, так как мы использовали управление версиями ресурсов CSS/JS/изображений.

ceejayoz 30.05.2019 02:51

@DavidAlsh location.reload() перезагрузит главную страницу, но не сделает недействительным кеш всех загружаемых ресурсов, таких как файлы CSS и JS.

Barmar 30.05.2019 02:53

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

Barmar 30.05.2019 02:54

Чтобы сделать это в облачном фронте, мне просто нужно установить собственную длину кэша, верно? Он перезапишет заголовки кеша, поступающие из источника?

David Alsh 30.05.2019 03:33
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Улучшение производительности загрузки с помощью Google Tag Manager и атрибута Defer
Улучшение производительности загрузки с помощью Google Tag Manager и атрибута Defer
В настоящее время производительность загрузки веб-сайта имеет решающее значение не только для удобства пользователей, но и для ранжирования в...
Безумие обратных вызовов в javascript [JS]
Безумие обратных вызовов в javascript [JS]
Здравствуйте! Юный падаван 🚀. Присоединяйся ко мне, чтобы разобраться в одной из самых запутанных концепций, когда вы начинаете изучать мир...
Система управления парковками с использованием HTML, CSS и JavaScript
Система управления парковками с использованием HTML, CSS и JavaScript
Веб-сайт по управлению парковками был создан с использованием HTML, CSS и JavaScript. Это простой сайт, ничего вычурного. Основная цель -...
JavaScript Вопросы с множественным выбором и ответы
JavaScript Вопросы с множественным выбором и ответы
Если вы ищете платформу, которая предоставляет вам бесплатный тест JavaScript MCQ (Multiple Choice Questions With Answers) для оценки ваших знаний,...
2
6
4 651
2
Перейти к ответу Данный вопрос помечен как решенный

Ответы 2

Ответ принят как подходящий

Поскольку этот вопрос был помечен progressive-web-apps, я предполагаю, что он устанавливает сервис-воркер, который агрессивно кэширует ресурсы.

Эта почта работает, но показывает всплывающее окно «доступна новая версия» для PWA — даже если это не то поведение, которое вам нужно, оно многое объясняет в том, как обновляются сервис-воркеры.

Этот вопрос/ответ также указывает, как часто сервис-воркер проверяет наличие обновлений.

Этот вопрос/ответ рассказывает о плюсах и минусах постоянного использования skipWaiting, чтобы клиент всегда был в курсе последних событий.

Редактировать: Если вы имеете дело только с обычным кэшем HTTP, попробуйте использовать location.reload(true) (перезагрузить с установленным флагом forcedReload), когда обнаружите, что на сервере есть более новая версия. В прошлом я делал это, помещая номер выпуска в код js во время сборки/выпуска и заставляя сервер добавлять свой номер выпуска к каждому ответу в качестве заголовка. Простое сравнение значений после вызова ajax может подтвердить, совпадают ли номера выпусков пользовательского интерфейса и сервера, и принять меры, если они не совпадают.

У него есть сервисворкер, я забыл упомянуть выше. На данном этапе сервисворкер имеет только пустой обработчик выборки — будет ли это все же изменять поведение кэширования?

David Alsh 30.05.2019 10:33

Хм, я бы так не подумал - обычно вам нужен какой-то код, чтобы включить предварительное кэширование, с чем, как я думал, вы будете иметь дело. Если вы имеете дело с обычным http-кэшем, вы можете обойтись Location.reload(true) — обратите внимание на набор параметров forceReload. Я немного обновлю свой ответ.

Jono Job 31.05.2019 01:02

Я написал следующий сервис Angular. По сути, он опрашивает файл build.txt, который находится в папке /assets, и проверяет, отличается ли он от сборки в своей собственной среде. gist.github.com/alshdavid/032ea535f222646dc74420e20b28faa1

David Alsh 15.06.2019 03:31

Спасибо Джоно Джоб за помощь в достижении этого решения.

В итоге я сделал следующее:

В моем конвейере сборки я добавил следующие две строки перед сборкой клиента.

- sed -i -e "s/{{build-number}}/${CI_COMMIT_SHORT_SHA}/g" ./src/environments/environment.prod.ts
- echo $CI_COMMIT_SHORT_SHA > ./src/assets/build.txt

Первая строка помещает хэш фиксации в скомпилированный пакет javascript, вторая создает текстовый файл с хэшем фиксации в качестве содержимого.

Затем я настроил службу Angular, которая использует http-клиент для опроса текстового файла, содержащего хэш фиксации. Он проверяет, отличается ли хэш в текстовом файле от хеша, загруженного из пакета javascript.

Теория здесь заключается в том, что пакет Javascript может быть кэширован, но HTTP-запрос на получение файла build.txt не будет. Позволяя мне проверить разницу между хэшами сборки, хранящимися в двух.

Если служба обнаружит разницу в сборках, она отобразит подсказку пользователю, уведомляющую его об обновлении, которое при нажатии обновит страницу.

Обновление выполняется с помощью window.location.reload(true). TypeScript сообщает мне, что параметр устарел, хотя он все еще работает.

Вот суть вышеупомянутого сервиса Angular: https://gist.github.com/alshdavid/032ea535f222646dc74420e20b28faa1

В моем APM я вижу, что в течение нескольких часов после отправки обновления все клиенты были обновлены до последней версии.

Так что наверное работает.

Другие вопросы по теме