Хабрахабр

[Из песочницы] Vue.js SSR & мобильный Safari: неочевидная проблема со слишком умным ПО

На днях столкнулись с такой проблемой. Сгенерированный на стороне сервера код отказывался гидратироваться в Safari.

Подробнее тут.
Гидратация относится к процессу на стороне клиента, в течение которого Vue берёт статический HTML, отправленный сервером, и превращает его в динамический DOM, который может реагировать на изменения данных на стороне клиента.

«Прод» просто падал, а dev-версия сообщала, что имеются расхождения в dom. А так как dev-версия не падает при попытке гидратации, а только сообщает об этом в консоли, ошибка была неочевидна и пока мы ее нашли, прошло довольно много времени.

Очень интересная стратегия от Vue – подождать продакшена и там упасть!

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

И когда нашли нужную строку, просто не поверили глазам. В итоге выяснилось, что падает наше приложение при подключении компонента футера. Когда начали копаться, выяснилось, что Safari после получения html-верстки подставлял рядом с телефоном тег a, который вызывал, собственно, приложение набора номера. Ожидали все, что угодно, только не этого.
Оказалось, что когда удаляешь номер телефона, гидратация проходила без проблем.

Приложение падало без объявления войны. Естественно, когда начиналась гидратация, dom-а пришедшей с сервера страницы и вновь построенного виртуального не совпадали.

До сего момента телефон мы вставляли обычным образом: Решилась это проблема тоже довольно неожиданно.

<div>8 (800) 111 2 333</div>

Решением проблемы стал биндинг v-text:

<div v-text=”8 (800) 111 2 333”></div>

У меня есть теория на этот счет. Если кто-то сможет подтвердить ее или опровергнуть (предложив новую), буду очень признателен. Как я понимаю, после того, как Safari получил документ, Vue строит виртуальный dom и сравнивает его с этим документом и пока он этот документ гидратирует, Safari занимается своим тёмным делом и меняет телефон на ссылку. Когда доходит дело до этого поля, Vue с помощью v-text снова заменяет содержимое нашего дива на нужное нам. В итоге на момент сравнения dom-а совпадают, полет нормальный.

Показать больше

Похожие публикации

Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *

Кнопка «Наверх»