Пытаюсь сделать single page app с автообновлением.
Есть открытая в браузере страница. Иногда выкатывается новая версия приложения. Браузер каким-то образом должен это обнаружить и перезагрузить эту страницу.
Для обнаружения у меня в данный момент открывается websocket — если соединение прервано — считается, что время проверить версию на сервере. Если способ попроще? Или сойдёт?
Допустим мы обнаружили что надо перезагрузить страницу. Наивный window.reload может не сработать если в этот момент сервер лежит, например. Поэтому надо как-то убедиться, что сервер в порядке и возвращает ожидаемый результат. Ну это можно как-то попинговать какой-нибудь урл, или открывая websocket. Но даже если пинг прошел, во время reload тоже может что-нибудь упасть. Загрузка страницы может прерваться в произвольный момент и страница опять будет поломана.
Т.е. в идеале надо как-то вначале загрузить файлы (как минимум index.html и необходимые зависимости .js и .css. В принципе webpack позволяет все .js+.css в один bundle собрать. Т.е. нужно как минимум index.html+bundle.js как-то предварительно подргузить, проверить, что они загрузились целиком и без ошибок в кеш браузера, потом как-то объяснить браузеру, чтобы он отобразил страницу целиком из кеша атомарно.
Как правильно сделать надёжное обновление?
Интересуют современные браузеры, совместимость с IE5 не требуется.
но это не зря, хотя, может быть, невзначай
гÅрмония мира не знает границ — сейчас мы будем пить чай
Здравствуйте, ·, Вы писали:
·>Пытаюсь сделать single page app с автообновлением.
·>Есть открытая в браузере страница. Иногда выкатывается новая версия приложения. Браузер каким-то образом должен это обнаружить и перезагрузить эту страницу.
Обычно делают простейший вариант — переименовывают все js и css файлы в новой версии. Большинство фреймворков делают это автоматически при сборке приложения (или "дедовский" вариант с добавлением суффикса версии к файлам). Браузер подгрузит такие изменения автоматически, после того как загрузит новый index.html
То есть, тебе ничего не надо делать, все и так будет обновляться. Достаточно использовать любой фреймворк для сборки, типа webpack.
Не очень понял почему ты хочешь файлы с сервера загружать "вручную". Это как-то супер подозрительно
Здравствуйте, ·, Вы писали:
·>Допустим мы обнаружили что надо перезагрузить страницу. Наивный window.reload может не сработать если в этот момент сервер лежит, например. Поэтому надо как-то убедиться, что сервер в порядке и возвращает ожидаемый результат. Ну это можно как-то попинговать какой-нибудь урл, или открывая websocket. Но даже если пинг прошел, во время reload тоже может что-нибудь упасть. Загрузка страницы может прерваться в произвольный момент и страница опять будет поломана.
Софт для космической атомной станции?
Тебе надо только index.html перезачитать, дальше браузер все вытащит по новым ссылкам (вебпак умеет давать новые имена для скриптов и статики). Вероятность, что при работающем сервер вдруг упадет загрузка очень мала. А если все же в каких-то редких случаях и упадет, то что? Пользователь увидит ошибку, сделает обновление страницы и все загрузится, хм?
bnk>·>Есть открытая в браузере страница. Иногда выкатывается новая версия приложения. Браузер каким-то образом должен это обнаружить и перезагрузить эту страницу. bnk>Обычно делают простейший вариант — переименовывают все js и css файлы в новой версии. Большинство фреймворков делают это автоматически при сборке приложения (или "дедовский" вариант с добавлением суффикса версии к файлам). Браузер подгрузит такие изменения автоматически, после того как загрузит новый index.html bnk>То есть, тебе ничего не надо делать, все и так будет обновляться. Достаточно использовать любой фреймворк для сборки, типа webpack.
bnk>Не очень понял почему ты хочешь файлы с сервера загружать "вручную". Это как-то супер подозрительно
Я хочу себя обезопасить от внезапных ошибок сети. Допустим index.html загрузился. Дальше браузер идёт загружать bundle.js и тут wifi пропадает на минуту. Имеем поломанную страницу.
Страница предназначена для отображения на мониторе, комп стоит в шкафу, без клавы/мыши. Если страница сломалась во время обновления надо заходить на комп удалённо лишь ради того, чтобы нажать F5.
но это не зря, хотя, может быть, невзначай
гÅрмония мира не знает границ — сейчас мы будем пить чай
Я бы попробовал сделать AJAX-запрос /index.html и потом заменить тело страницы на полученные данные при успешной загрузке.
Чтобы обезопасить себя от недозагруженных скриптов, можно сделать так:
В самом начале страницы сделай reloadIndexHtmlTimeout = setTimeout(reloadIndexHtml, 10000). Прям в теге скрипт. Первый кусок страницы-то уж точно придёт. Ну и эту функцию reloadIndexHtml туда же. В общем 1-2 IP пакета и в браузере этот скрипт выполнится и пойдёт отсчёт. Дальше, если будут любые проблемы с загрузкой, через 10 секунд опять пойдёт попытка AJAX-ом загрузить и тд. Тут уже сам пиши, чтобы было надёжно отработаны ошибки, ретраи и тд. А так — в самом конце сделай аналог document.addEventListener("DOMContentLoaded", function() { clearTimeout(reloadIndexHtmlTimeout); }). Конкретно этот код, мне кажется, не сработает, то бишь он будет работать даже при загрузке JS с ошибками, поэтому надо погуглить, как определить тот факт, что JS не загрузился и тут прописать эти условия. Ну или в конце своего JS-файла просто поставляй флажок, если полностью прогрузится, то этот флажок проставится.
Здравствуйте, ·, Вы писали:
·>Я хочу себя обезопасить от внезапных ошибок сети. Допустим index.html загрузился. Дальше браузер идёт загружать bundle.js и тут wifi пропадает на минуту. Имеем поломанную страницу.
По идее, можно добавить в конце body небольшой JavaScript-код, который будет проверять по каким-то признакам, загрузился ли bundle.js, и при необходимости принудительно обновит страницу.
Здравствуйте, ·, Вы писали:
·>Страница предназначена для отображения на мониторе, комп стоит в шкафу, без клавы/мыши. Если страница сломалась во время обновления надо заходить на комп удалённо лишь ради того, чтобы нажать F5.
Можно посмотреть на PWA (Progressive Web App), т.е. добваить к твоему приложению манифест и воркер скрипт. Минимальный пример здесь
Там ты полностью контролируешь то что именно браузер получает из сети, и решаешь за него, что вернуть (из кэша например), если сервер недоступен или при загрузке произошла ошибка.
Обновление там тоже делается явно.
Или ещё вариант: периодически запускаемый bash-скрипт проверяет заголовок окна браузера (командой wmctrl). Если заголовок не соответствует заголовку сайта, значит произошёл сбой и нужно "нажать" F5 (командой xdotool). Заголовок ставится яваскриптом после диагностики страницы (загрузились ли все скрипты и стили).
Здравствуйте, ·, Вы писали:
·>Я хочу себя обезопасить от внезапных ошибок сети. Допустим index.html загрузился. Дальше браузер идёт загружать bundle.js и тут wifi пропадает на минуту. Имеем поломанную страницу. ·>Страница предназначена для отображения на мониторе, комп стоит в шкафу, без клавы/мыши. Если страница сломалась во время обновления надо заходить на комп удалённо лишь ради того, чтобы нажать F5.
Вроде как Service Workers для этого придуманы, но сам я с ними еще не работал. Насколько их можно применить для обновления Js-кода самого приложения —
Здравствуйте, L.K., Вы писали:
LK>·>Допустим index.html загрузился. Дальше браузер идёт загружать bundle.js и тут wifi пропадает на минуту. Имеем поломанную страницу. LK>Ну тогда index.html должен загружаться один раз — и всё. LK>А обновления (html,css,js) должны загружаться аяксом (с проверкой контрольной суммы) и потом вставляться внутрь index.html.
Я опасаюсь, что какие-то глобальные объекты страницы (таймеры, например) будут застревать в текущей странице и вообще бардак начнётся из-за месива разных версий кода...
но это не зря, хотя, может быть, невзначай
гÅрмония мира не знает границ — сейчас мы будем пить чай
Здравствуйте, Lazytech, Вы писали:
L>·>Я хочу себя обезопасить от внезапных ошибок сети. Допустим index.html загрузился. Дальше браузер идёт загружать bundle.js и тут wifi пропадает на минуту. Имеем поломанную страницу. L>По идее, можно добавить в конце body небольшой JavaScript-код, который будет проверять по каким-то признакам, загрузился ли bundle.js, и при необходимости принудительно обновит страницу.
Если в момент принудительного обновления страницы не будет сети или сервак будет лежать, то всё сломается. Браузер покажет какой-нибудь "page not found" и усё.
но это не зря, хотя, может быть, невзначай
гÅрмония мира не знает границ — сейчас мы будем пить чай
Здравствуйте, ·, Вы писали:
·>Я опасаюсь, что какие-то глобальные объекты страницы (таймеры, например) будут застревать в текущей странице и вообще бардак начнётся из-за месива разных версий кода...
Честно говоря, твои опасения совершенно непонятны. Выглядит как боязнь темноты. Типа, вдруг я пойду ночью в туалет, а из толчка вылезет питон и укусит меня за жопу
Возможно есть какие-то особенности твоего приложения, что его отличает от миллионов других?
·>Я опасаюсь, что какие-то глобальные объекты страницы (таймеры, например) будут застревать в текущей странице и вообще бардак начнётся из-за месива разных версий кода...
Все таймеры перед обновлением, разумеется, останавливаются. Обработчики событий тоже останавливаются. HTML-объекты удаляются.
Остаётся только "изначальный"/"неизменный" скрипт, который умеет проверять наличие новой версии, закачивать её, проверять контрольную сумму и добавлять полученные скрипты на страницу.
Здравствуйте, vsb, Вы писали:
vsb>В самом начале страницы сделай reloadIndexHtmlTimeout = setTimeout(reloadIndexHtml, 10000). Прям в теге скрипт. Первый кусок страницы-то уж точно придёт.
Не понял почему "точно"? Вот у нас есть загруженная работающая страница. Поступил сигнал "обновиться". Если просто тупо сделать window.reload, то index.html может вообще не прийти, а покажется например какой-нибудь "DNS error", если сеть временно отвалилась. Что конкретно ты предлагаешь делать при поступлении сигнала?
но это не зря, хотя, может быть, невзначай
гÅрмония мира не знает границ — сейчас мы будем пить чай
Здравствуйте, bnk, Вы писали:
bnk>·>Я опасаюсь, что какие-то глобальные объекты страницы (таймеры, например) будут застревать в текущей странице и вообще бардак начнётся из-за месива разных версий кода... bnk>Честно говоря, твои опасения совершенно непонятны. Выглядит как боязнь темноты. Типа, вдруг я пойду ночью в туалет, а из толчка вылезет питон и укусит меня за жопу bnk>Возможно есть какие-то особенности твоего приложения, что его отличает от миллионов других?
Обычно веб-приложениями пользуются интерактивно. А у меня приложение просто отображает информацию, не подразумевает что юзер что-то нажимает, только смотрит. Один раз открыл в окошке — и всё, только глядеть туда.
но это не зря, хотя, может быть, невзначай
гÅрмония мира не знает границ — сейчас мы будем пить чай
Здравствуйте, ·, Вы писали:
bnk>>Честно говоря, твои опасения совершенно непонятны. Выглядит как боязнь темноты. Типа, вдруг я пойду ночью в туалет, а из толчка вылезет питон и укусит меня за жопу bnk>>Возможно есть какие-то особенности твоего приложения, что его отличает от миллионов других?
·>Обычно веб-приложениями пользуются интерактивно. А у меня приложение просто отображает информацию, не подразумевает что юзер что-то нажимает, только смотрит. Один раз открыл в окошке — и всё, только глядеть туда.
Это что-то типа календаря?
Тогда возможно имеет смысл все закэшировать (то есть, все файлы иметь на клиенте).
Насколько я знаю, сейчас для этого две возможности — servece workers (можно просто, можно PWA), или (устаревшая) cache manifest
Оба варианта предоставляют вполне документированный и детерминированный механизм обновления, обеспечивающий целостность приложения.
Здравствуйте, bnk, Вы писали:
bnk>·>Обычно веб-приложениями пользуются интерактивно. А у меня приложение просто отображает информацию, не подразумевает что юзер что-то нажимает, только смотрит. Один раз открыл в окошке — и всё, только глядеть туда. bnk>Это что-то типа календаря?
Ну да, что-то вроде. Точнее типа summary health monitor, набор красных/зелёных лампочек, номера текущих версий, етс.
bnk>Тогда возможно имеет смысл все закэшировать (то есть, все файлы иметь на клиенте). bnk>Насколько я знаю, сейчас для этого две возможности — servece workers (можно просто, можно PWA), или (устаревшая) cache manifest bnk>Оба варианта предоставляют вполне документированный и детерминированный механизм обновления, обеспечивающий целостность приложения.
Ага, PWA и SW уже смотрю... cache manifest вообще стоит смотреть, раз он устарел? Поддержка старых браузеров мне не нужна.
но это не зря, хотя, может быть, невзначай
гÅрмония мира не знает границ — сейчас мы будем пить чай
Здравствуйте, ·, Вы писали:
vsb>>В самом начале страницы сделай reloadIndexHtmlTimeout = setTimeout(reloadIndexHtml, 10000). Прям в теге скрипт. Первый кусок страницы-то уж точно придёт. ·>Не понял почему "точно"? Вот у нас есть загруженная работающая страница. Поступил сигнал "обновиться". Если просто тупо сделать window.reload, то index.html может вообще не прийти, а покажется например какой-нибудь "DNS error", если сеть временно отвалилась. Что конкретно ты предлагаешь делать при поступлении сигнала?
Если мы перезагружаем работающую страницу, то я написал — делаем это аяксом. То, что я написал выше это для варианта, когда страница загружается браузером изначально (или перезагружается через F5).
Здравствуйте, ·, Вы писали:
bnk>>Тогда возможно имеет смысл все закэшировать (то есть, все файлы иметь на клиенте). bnk>>Насколько я знаю, сейчас для этого две возможности — servece workers (можно просто, можно PWA), или (устаревшая) cache manifest bnk>>Оба варианта предоставляют вполне документированный и детерминированный механизм обновления, обеспечивающий целостность приложения.
·>Ага, PWA и SW уже смотрю... cache manifest вообще стоит смотреть, раз он устарел? Поддержка старых браузеров мне не нужна.
Я бы тогда только на sw смотрел. "cache manifest" упомянул поскольку постольку.
Кстати, как ты вообще запускаешь обновление, если панель никак не взаимодействует с пользователем?