Эта статья адресована техническим руководителям, которым суждено терпеть немые укоры из-за низкой UI-производительности.
HTML — самый распространенный подход к отображению данных в виде таблиц, что вполне логично, поскольку HTML предоставляет исчерпывающую модель форматирования, избавляя нас от изобретения колеса.
И все было бы замечательно, если бы при рендеринге больших или потенциально объемных данных не возникали некоторые проблемы. Одна из них — появление большого количества DOM-узлов, что чревато:
- снижением производительности;
- существенными затратами на рефлоу (reflow) — пересчет размеров составных блоков веб-страницы.
Новомодный Macbook M3 наверняка легко справится с подобными вызовами, но для маломощного устройства они могут стать серьезным испытанием.
Каждая компания-разработчик ПО, выпускающая популярные веб-приложения, рано или поздно сталкивается с этими проблемами. В таких случаях проводится совещание с дизайнерами и фронтенд-разработчиками, на котором принимаются следующие решения:
- очистка с целью сокращения DOM-узлов и дорогостоящих CSS-правил;
- ограничение или отказ от анимации;
- ограничение или устранение возможности прокрутки для пользователей.
Серьезные HTML-проекты имеют множество подобных ограничений, и инструменты профилирования становятся лучшими друзьями разработчика.
Теперь можно решить проблему большого количества DOM-узлов, применив виртуализацию списков. Такое решение позволяет загружать в память большие объемы данных и при этом рендерить только части DOM, представляемые пользователю. Этот процесс подобен исключению из обработки невидимых элементов 3D-изображения в видеоиграх.
Однако виртуализация списка элементов не решает всех проблем. Не исключено, что рефлоу сделает анимацию нестабильной. Будем предельно честны: языкам HTML и CSS давно пора стать преемниками, но пока приходится работать с тем, что есть.
Я не сторонник жертвовать опытом пользователя из-за технологических ограничений. У нас есть Canvas 2D и WebGL, скоро появится WebGPUContext. Причины ограничений этих технологий не являются чисто техническими. Они связаны скорее с ограниченностью количества специалистов для работы с GPU в веб-среде. Three.js вносит свою лепту в эту сферу, но в целом она довольно узка.
Так что же делать?
В свое время кто-то рассказал мне о человеке, заплатившем $2000 за сайт, который в итоге оказался просто веб-страницей, а весь UI представлял собой jpeg-изображение.
Но шутки в сторону — обсудим передовую UI-стратегию. Посмотрим, что можно извлечь из нее в реальной практике.
Плюсы:
- Сокращение количества узлов: изображение может уменьшить количество узлов на сайте.
- Снижение рефлоу: изображения не идеальны, но их производительность намного выше, чем у вложенных DOM-деревьев.
- Возможность генерации: можно сгенерировать изображение в браузере по ходу работы, используя Canvas или OffscreenCanvas с помощью BlobURL.
- Экономия памяти: такие форматы изображений, как jpg, png, webp и avif, используют меньше памяти, чем интерфейс Canvas или любое количество узлов DOM, роль которых они выполняют.
- Браузеры.
Минусы:
- Отсутствие интерактивности.
- Низкий уровень доступности.
- Нет возможности выбирать данные.
- Требуется высокое разрешение для различных устройств с соотношением пикселей или масштабированием.
В некоторых случаях можно вернуться к временам PlayStation 1 и отказаться от билинейной фильтрации текстур, используя свойство image rendering со значением pixelated.
Стратегия для подвижных больших табличных данных
3D-трансформации CSS создают композитные слои для рендеринга DOM на высокой скорости GPU. Единственная проблема этой стратегии в том, что она не во всех случаях полностью обходит рефлоу и иногда приводит к низкому качеству рендеринга в режиме простоя (в условиях движения это для нас не играет особой роли).
Но вы можете использовать эту стратегию для создания псевдокомпозитного слоя, чтобы заменять большие табличные данные в периоды движения. Вот основные этапы этого процесса:
- Получение данных и их рендеринг с помощью OffscreenCanvas. Нативный Canvas не слишком сложен в освоении, если вы понимаете, что контекст Canvas зависит от состояния. Можно также использовать что-то вроде html2canvas (этот проект не поддерживается).
- Рендеринг холста в изображение/я. Использование BlobURL’ов (Blob — большой двоичный объект) позволяет успешно заменить сложный UI DOM изображениями.
- Интерактивное наложение DOM. Создаваемый UI накладывает часть данных, находящихся в текущий момент в зоне видимости, и представляет эти данные в зоне видимости. Это наложение исчезает во время анимации или прокрутки, а затем появляется снова после завершения перехода. HTML-наложение напоминает данные изображения, но не является идеальным, так как реальное изображение будет в основном находиться в зоне видимости во время изменения размера, прокрутки или анимации.
Насколько целесообразна эта UI-стратегия?
Как всегда, все зависит от ситуации. При умеренных объемах данных такой подход будет явным излишеством. Настоятельно не рекомендую использовать его для типовых приложений или статистических отчетов.
Применение его может быть оправдано только в случае возникновения проблем с производительностью, но при этом необходимо учитывать размер изображения const.
Допустим, вы хотите использовать в сценариях «данные в движении» 10 изображений avif размером 2000 x 1000 пикселей каждое. Несмотря на сжатие каждое изображение будет занимать 8 МБ памяти, что в общей сложности составит 80 МБ долгосрочной памяти кучи (BlobURL’ы обычно хранятся в куче). Для сравнения: эквивалентные DOM-узлы, скорее всего, будут занимать гораздо меньший объем — примерно 1 МБ.
Напоследок
Описанная стратегия — гораздо более амбициозная задача, чем виртуализация списков, хотя в некотором смысле является разновидностью виртуализации списков. Конечный результат должен позволить пользователю получить невероятную пластичность изображения, создающую иллюзию, что тысячи или миллионы узлов DOM проносятся через страницу.
Это что-то вроде революционной технологии «Нанит для HTML-данных», но более доступное.
Читайте также:
- Переход с Webpack на Rspack
- Несложное WebGPU-программирование с использованием taichi.js
- Как использовать WebGL для интерактивной 3D-графики
Читайте нас в Telegram, VK и Дзен
Перевод статьи Julien Etienne: Rendering Large Tabular Data in the Browser