Візуалізація web-сторінки що про це повинен знати front-end розробник

Вітаю вас, шановні читачі! Сьогодні я б хотів висвітлити питання рендеринга в веб-розробці. Звичайно, на цю тему вже написано багато статей, але, як мені здалося, вся інформація досить розрізнена і уривчаста. По крайней мере, щоб зібрати всю картину в своїй голові і осмислити її, мені довелося проаналізувати чимало інформації (в основному - англомовної). Саме тому я вирішив формалізувати свої знання до статті, і поділитися результатом з спільнотою Хабра. Думаю, інформація буде корисна як початківцям веб-розробникам, так і більш досвідченим, щоб освіжити і структурувати свої знання.

Даний напрямок можна і потрібно оптимізувати на етапі верстки / frontend-розробки, оскільки, очевидно, що розмітка, стилі і скрипти приймають в рендеринге безпосередню участь. Для цього відповідні фахівці повинні знати деякі тонкощі.

Процес обробки WEB-сторінки браузером

Для початку, розглянемо послідовність роботи браузера при відображенні документа:

  1. З отриманого від півночі HTML-документа формується DOM (Document Object Model).
  2. Завантажуються і розпізнаються стилі, формується CSSOM (CSS Object Model).
  3. На основі DOM і CSSOM формується дерево рендеринга, або render tree - набір об'єктів рендеринга (Webkit використовує термін «renderer», або «render object», а Gecko - «frame»). Render tree дублює структуру DOM, але сюди не потрапляють невидимі елементи (наприклад - . або елементи зі стилем display: none; ). Також, кожен рядок тексту представлена ​​в дереві рендеринга як окремий renderer. Кожен об'єкт рендеринга містить відповідний йому об'єкт DOM (або блок тексту), і розрахований для цього об'єкту стиль. Простіше кажучи, render tree описує візуальне уявлення DOM.
  4. Для кожного елемента render tree розраховується становище на сторінці - відбувається layout. Браузери використовують потоковий метод (flow), при якому в більшості випадків достатньо одного проходу для розміщення всіх елементів (для таблиць проходів потрібно більше).
  5. Нарешті, відбувається отрисовка всього цього добра в браузері - painting.

В процесі взаємодії користувача зі сторінкою, а також виконання скриптів, вона змінюється, що вимагає повторного виконання деяких з перерахованих вище операцій.

У разі зміни стилів елемента, які не впливають на його розміри і положення на сторінці (наприклад, background-color. Border-color. Visibility), браузер просто отрісовиваєт його заново, з урахуванням нового стилю - відбувається repaint (або restyle).

Якщо ж зміни зачіпають вміст, структуру документа, положення елементів - відбувається reflow (або relayout). Причинами таких змін зазвичай є:

  • Маніпуляції з DOM (додавання, видалення, зміна, перестановка елементів);
  • Зміна вмісту, в т.ч. тексту в полях форм;
  • Розрахунок або зміна CSS-властивостей;
  • Додавання, видалення таблиць стилів;
  • Маніпуляції з атрибутом «class»;
  • Маніпуляції з вікном браузера - зміни розмірів, прокрутка;
  • Активація псевдо-класів (наприклад. Hover).

Оптимізація з боку браузера

Браузери по можливості локалізують repaint і reflow в межах елементів, які були піддані зміни. Наприклад, зміна розмірів абсолютно або фіксоване позиційований елемента торкнеться тільки сам елемент і його нащадків, в той час як зміна статично позиційований - спричинить reflow всіх елементів, наступних за ним.

Однак, як описано вище, звернення до властивостей елементів викличе примусовий reflow. Тобто, якщо ми в наведений блок коду додамо звернення до властивості елемента, це викличе зайвий reflow:

У підсумку ми отримаємо 2 reflow замість одного. Тому, звернення до властивостей елементів по можливості потрібно групувати в одному місці, щоб оптимізувати продуктивність (див. Детальніший приклад на JSBin).

Але, на практиці зустрічаються ситуації, коли без примусового reflow не обійтися. Припустимо, у нас є завдання: до елементу потрібно застосувати один і той же властивість (візьмемо «margin-left») спочатку без анімації (встановити в 100px), а потім - анімувати за допомогою transition в значення 50px. Можете відразу подивитися цей приклад на JSBin. але я розпишу його і тут.
Для початку заведемо клас з transition:

Потім, спробуємо реалізувати задумане наступним чином:

Дане рішення не буде працювати, як очікується, тому що зміни кешуються і застосовуються тільки в кінці блоку коду. Нас врятує примусовий reflow, в результаті код буде мати наступний вигляд, і буде в точності виконувати поставлене завдання:

Практичні поради щодо оптимізації

На основі даної статті, а також інших статей на окупантів, де висвітлюється питання оптимізації JS, можна вивести наступні поради, які стануть в нагоді при створенні ефективного фронтенда:

  • Пишіть валідний HTML і CSS, з зазначенням кодування. Стилі краще включати в . а скрипти - в кінці .
  • Варто уникати складних вкладень селекторів в CSS (цим часто грішать розробники, що використовують препроцесори). Також замість тегів краще використовувати класи, або ідентифікатори. А також, слід уникати універсального селектора (*).

Сподіваюся, кожен читач витягнув зі статті що-небудь корисне. У будь-якому випадку - спасибі за увагу!

Схожі статті