Стоит ли выгружать старые элементы при бесконечном скролле?

Проанализировал популярные соцсети и блоги с бесконечным скроллингом. Ни одна из них не удаляет уже загруженные элементы из DOM. Та же стена пользователя на Фейсбук занимает в памяти под 100 МБ. И это мы берем оптимизированные сайты, где ссылки и лайки под каждым сообщением скорее всего биндятся общим обработчиком через всплытие событий. Если же взять Ангуляр и подобные фреймворки, то там обработчик повесится на каждый элемент списка. Возникла идея выгрузки из DOM загруженных ранее элементов (в кэше они остаются). Почему-то нашел всего парочку подобных решений и ни одного исследования.

Подскажите что-нибудь по теме. Интересуют прежде всего вопросы: 1) насколько больше памяти занимает DOM (за пределами экрана) чем данные в модели, на основе которых он формируется (напр., текст комментария) и как браузер оптимизирует элементы за пределами экрана; 2) делая выгрузку уже загруженных элементов стоит их просто удалять или вставлять вместо них пустой блок высотой с эти элементы, чтобы сохранить позицию ползунка прокрутки, как это отразится на производительности?

  • Вопрос задан
  • 5060 просмотров
Пригласить эксперта
Ответы на вопрос 8
Fesor
@Fesor
Full-stack developer (Symfony, Angular)

Разработчики linkedIn как-то публиковали описание подходов по оптимизации бесконечных скролов, которые они у себя применяли:
http://engineering.linkedin.com/linkedin-ipad-5-techniques-smooth-infinite-scrolling-html5

а фэйсбук не самый хороший пример оптимизации фронтэнда.

p.s. по поводу ангуляра и делигированных событий, у меня в некоторых частях проекта используется всплытие ивентов вместо непосредственной привязки к элементу. Делается это у меня через 2 директивы (fsDelegate, и далее всякие обработчики ивентов аля fsTap и т.д). Причем fsDelegate вешает обработчики на элемент списка, fsTap регистрируется у fsDelegate (если конечно оно там будет, связь между ними через контроллер fsDelegate и параметр require: '^?fsDelegate'). Опять же при отлове события определяется какой именно элемент отработал, берется его скоуп и выполняется выражение заключенное в fsTap.

Ответ написан
xaja
@xaja

А когда пользователь будет скроллить наверх - опять подгружать удаленные данные?

Ответ написан
AlexPTS
@AlexPTS
Full stack веб разработчик

Браузер однозначно что-то оптимизирует при выходе элементов за viewport, но на это сильно расчитывать не стоит.

а) Делал горизонтальную прокрутку viewport`а, анимация идет намного плавнее, если по бокам элементов намного меньше и те что не в области видимости прятать через display:none; Визуально разницу можно наблюдать. Можно проверить.

б) Делал бесконечную вертикальную прокрутку вниз, подобие стены в соцсети, где доходя до низа приходит новая пачка с медиа контнетном. В js все обработчики отвязывались своевременно, профайлил все долго и упорно, пытаясь ускорить сей процесс. Но после 1000-2000 элементов контента на странице, браузер начинал на ПК тупить и кушал все больше памяти. Хотя оптимизация самими браузером определенно есть. Но удалять элементы из DOM оказалось намного эффективнее.
2) Тут вопрос не в прокрутке, а в том, что когда ты удалишь вышерасположенные элементы, то представление схлопнется, элементы перепозиционируются. Вставлять пустую элементы такой же высоты вместо прежних это костыльно.

Посмотреть можно примеры отсюда - http://masonry.desandro.com/
Уверен что кто-то выгружает тоже элементы, чтобы GUI был более отзывчивым.

Ответ написан
Комментировать
@GreatRash

Можно не выгружать старые элементы, а прятать их (display: none;).

Ответ написан
@rozhik

1) насколько больше памяти занимает DOM (за пределами экрана) чем данные в модели
Это очень специфично. Здесь не столько вопрос о памяти, сколько нагрузка на layout engine (если не используется абсолютное позиционирование).
2) как браузер оптимизирует элементы за пределами экрана;
Зависит от браузера. Рендеринг их не происходит всегда, но лайаут пересчитывается в большинстве случаев. О webkit (chrome, safari) могу сказать, что оптимизация там отличная. Лайаут пересчитывается инкрементально. Сотни элементов почти не напрягают.

2) делая выгрузку уже загруженных элементов стоит их просто удалять или вставлять вместо них пустой блок высотой с эти элементы, чтобы сохранить позицию ползунка прокрутки, как это отразится на производительности?
Это будет накладнее. Удалить у блока детей, при установленной высоте блока - поможет браузеру. А с абсолютным позиционированием - вообще песня. Если есть возможность рассчитывать высоту блоков - то это лучший подход.

Вообще зачем гадать - есть ChromeDev tools timeline + profiles, в мозиле есть фаербаг итп.. Это и даст обьективный ответ.

Ответ написан
Комментировать
@artishok
кратко

Тоже давно задумываюсь об этом. Как-то даже написал на коленке юзерскрипт для ВК, чтобы прокрученные элементы скрывались, а при прокрутке вверх - обратно показывались. Но я не сильно оптимизировал, поэтому постоянно что-то прыгало и дергалось. Еще стоит помнить что лента автоматически обновляется, и новые посты тоже надо прятать а потом показывать.
Вообще я сделал чтобы скрывались рекламные посты, а скрытие постов при прокрутке стало побочным результатом.

Ответ написан
Комментировать
@bseva
Может быть Infinity.js от AirBnb поможет?
http://airbnb.github.io/infinity/
Ответ написан
Комментировать
tamtakoe
@tamtakoe Автор вопроса
Провел исследование: habrahabr.ru/post/204350/
Ответ написан
Комментировать
Ваш ответ на вопрос

Войдите, чтобы написать ответ

Войти через центр авторизации
Похожие вопросы