Статьи

10 способов минимизировать рефлоу и повысить производительность

Несмотря на то, что веб-страницы достигают 2 МБ, производительность остается горячей темой. Чем приятнее ваше приложение, тем лучше пользовательский опыт и выше коэффициент конверсии!

Тем не менее, я виновен в добавлении поверхностных CSS3-анимаций или манипулировании несколькими элементами DOM без учета последствий. При применении визуальных эффектов в мире браузера используются два термина:

перерисовывает
Перекрашивание происходит, когда вносятся изменения в элементы, которые влияют на видимость, но не на макет. Например, opacity , background-color , visibility и outline . Перекрашивание обходится дорого, потому что браузер должен проверить видимость всех других узлов в DOM — один или несколько могут стать видимыми под измененным элементом.

перекомпоновки
Reflow имеют большее влияние. Это относится к пересчету позиций и размеров всех элементов, что приводит к повторной визуализации части или всего документа. Изменение одного элемента может повлиять на всех детей, предков и братьев и сестер.

Оба они блокируют браузер; Ни пользователь, ни ваше приложение не могут выполнять другие задачи во время перекраски или перекомпоновки. В крайних случаях эффект CSS может привести к замедлению выполнения JavaScript. Это одна из причин, по которой вы сталкиваетесь с такими проблемами, как прерывистая прокрутка и не отвечающие интерфейсы.

Полезно понять, когда инициируются оплавления:

Добавление, удаление или изменение видимых элементов DOM
Первое очевидно; использование JavaScript для изменения DOM приведет к перекомпоновке.

Добавление, удаление или изменение стилей CSS
Точно так же непосредственное применение стилей CSS или изменение класса может изменить макет. Изменение ширины элемента может повлиять на все элементы в одной ветви DOM и на окружающие ее элементы.

CSS3 анимация и переходы
Каждый кадр анимации будет вызывать перекомпоновку.

Использование offsetWidth и offsetHeight
Как ни странно, чтение свойств элемента offsetWidth и offsetHeight может инициировать начальное переформатирование, чтобы можно было рассчитать цифры.

Действия пользователя
Наконец, пользователь может инициировать перекомпоновку, активируя эффект :hover , ввод текста в поле, изменение размера окна, изменение размеров шрифта, переключение таблиц стилей или шрифтов.

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

1. Используйте лучшие методы макета

Я не могу поверить, что мне нужно сказать это в 2015 году, но не используйте встроенные стили или таблицы для макета!

Встроенный стиль будет влиять на макет при загрузке HTML и запускать дополнительное перекомпонование. Таблицы дороги, потому что анализатору требуется более одного прохода для вычисления размеров ячейки. Использование table-layout: fixed может помочь при представлении табличных данных, поскольку ширина столбцов основана на содержимом строки заголовка.

Использование flexbox для макета главной страницы также может flexbox производительность, поскольку положение и размеры элементов flex могут меняться при загрузке HTML-кода.

2. Минимизируйте количество правил CSS

Чем меньше правил вы используете, тем быстрее будет переформатирование. Вы также должны избегать сложных CSS-селекторов, где это возможно.

Это может быть особенно проблематично, если вы используете фреймворк, такой как Bootstrap — лишь немногие сайты используют больше, чем часть предоставленных стилей. Такие инструменты, как Неиспользуемый CSS , uCSS , grunt-uncss и gulp-uncss, могут значительно уменьшить определения стилей и размеры файлов.

3. Минимизируйте глубину DOM

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

4. Обновите классы низко в дереве DOM

Сделайте изменения класса для элементов как можно ниже в дереве DOM (т.е. элементов, которые не имеют нескольких глубоко вложенных потомков). Это может ограничить область перекомпоновки до необходимого количества узлов. По сути, применять изменения класса только к родительским узлам, таким как оболочки, если влияние на вложенные дочерние элементы минимально.

5. Удалите сложные анимации из потока

Убедитесь, что анимации применяются к одному элементу, удалив их из потока документов с помощью position: absolute; или position: fixed; , Это позволяет изменять размеры и положение, не затрагивая другие элементы в документе.

6. Изменить скрытые элементы

Элементы скрыты с помощью display: none; не будет вызывать перекрашивание или переформатирование при их изменении. Если возможно, внесите изменения в элемент, прежде чем сделать его видимым.

7. Обновление элементов в пакете

Производительность может быть улучшена путем обновления всех элементов DOM за одну операцию. Этот простой пример вызывает три перекомпоновки:

 var myelement = document.getElementById('myelement'); myelement.width = '100px'; myelement.height = '200px'; myelement.style.margin = '10px'; 

Мы можем уменьшить это до единого оплавления, которое также легче поддерживать, например

 var myelement = document.getElementById('myelement'); myelement.classList.add('newstyles'); 
 .newstyles { width: 100px; height: 200px; margin: 10px; } 

Вы также можете минимизировать время, необходимое для прикосновения к DOM. Предположим, вы хотели создать этот список:

  • пункт 1
  • пункт 2
  • пункт 3

Добавление каждого элемента по одному вызывает до семи повторений — один при добавлении <ul> , три для каждого <li> и три для текста. Тем не менее, одно перекомпонование может быть реализовано с использованием фрагмента DOM и сначала построения узлов в памяти, например

 var i, li, frag = document.createDocumentFragment(), ul = frag.appendChild(document.createElement('ul')); for (i = 1; i <= 3; i++) { li = ul.appendChild(document.createElement('li')); li.textContent = 'item ' + i; } document.body.appendChild(frag); 

8. Ограничьте затронутые элементы

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

9. Признать, что гладкость снижает производительность

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

10. Анализируйте проблемы перекраски с помощью инструментов браузера

Все основные браузеры предоставляют инструменты для разработчиков, которые подчеркивают, как перефразирование влияет на производительность. В браузерах Blink / Webkit, таких как Chrome, Safari и Opera, откройте панель « Таймлайн» и запишите действие:

Инструмент Chrome Timeline

Аналогичная панель временной шкалы доступна в инструментах разработчика Firefox:

Инструмент временной шкалы Firefox

Панель называется Отзывчивость пользовательского интерфейса в инструментах разработчика Internet Explorer F12:

Инструмент отзывчивости IE UI

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

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