[БЕЗ_ЗВУКА] Мы рассмотрели с вами,
как браузер загружает данные по сети, как он их обрабатывает,
как формирует DOM, CSSOM деревья и render tree и как наконец компонует,
то есть высчитывает геометрию элементов.
Последнее, что делает браузер — это отрисовывает эти элементы.
Но процессы внутри браузера несколько сложнее, чем рисование кистью по холсту.
У каждого DOM-элемента с визуальным представлением есть RenderObject,
то есть это знание о том, как отобразить элемент в текущем юзер-агенте.
Вы, наверное, иногда замечали, что некоторые элементы, например,
селекты, отличаются в разных браузерах.
Ну, это означает, что в разных браузерах разные RenderObject'ы.
RenderObject'ы ассоциируются с RenderLayer'ами.
Важно понимать, что RenderLayer'ы нужны для того,
чтобы отобразить пересекающиеся элементы.
Такое иногда случается, что элементы накладываются друг на друга.
И есть условия, которые ведут к созданию новых RenderLayer'ов.
Ну, вот, например, некоторые из них.
И наконец, некоторые RenderLayer'ы создают собственную подложку отрисовки,
которую также иногда называют «композитный слой».
Создавать композитный слой на каждый RenderLayer очень дорого
в браузере и расточительно.
Но есть свойства, которые форсируют ее создание.
Эти свойства переносят отрисовку данного слоя на процессор видеокарты,
то есть ускоряют отрисовку, но ведут к некоторым side-эффектам.
Давайте же посмотрим на примере, как у нас выполняется компоновка.
[БЕЗ_ЗВУКА] Мы можем видеть здесь,
как браузер расставляет элементы на странице, то есть он высчитывает
геометрию и только потом высчитывает размеры родителя, мы можем это заметить.
Здесь у нас произошло какое-то событие, которое привело к глобальному reflow,
что нам пришлось пересчитать размеры всех элементов.
И наконец, в конце элементы отрисовались.
Вы легко сможете найти это видео сами.
Еще я также рекомендую вам доклад Саши Завьялова про
веб-анимации на JS и CSS с конференции FrontTalks,
где подробно рассмотрены все эти аспекты отрисовки.
Последнее, о чем хотелось бы поговорить — это о том,
как JavaScript может повлиять на рендеринг страницы.
В нашем процессе превращения документа в DOM-дерево есть одна тонкость.
Эта тонкость заключается в том,
что когда конструктор деревьев встречает тег <script>,
он останавливает формирование дерева.
Почему?
Потому что в скрипте могут быть какие-нибудь инструкции, ну например,
document.write, которые изменяют текущее дерево.
И именно поэтому во всех браузерах заложен такой механизм: если
вы встретили тег <script>, остановите конструирование дерева.
Чтобы избежать остановки конструирования DOM-дерева,
есть специальные атрибуты: defer и async.
Они немножко по-разному работают, и то, как они работают,
легко проиллюстрировать на данной диаграмме.
Если просто тег <script> останавливает работу HTML-парсера,
и мы дожидаемся, пока скрипт загрузится, а потом обработается,
то атрибут defer откладывает выполнение скрипта в конец,
то есть после того, как у нас отработал HTML-парсер, мы выполняем скрипт.
А тег async откладывает выполнение скрипта до момента полной загрузки скрипта.
Об этой тонкости важно помнить.
Внутри JavaScript-овых интерпретаторов есть также
JIT-компиляция, этап JIT-компиляции.
Но подробнее о ней, я думаю, вы узнаете из курса по JavaScript-у,
и на ней мы не будем останавливаться.
Здесь несколько ссылок, которые будут выложены к данным видео,
в них подробнее рассмотрены принципы работы современных веб-браузеров.
Я настоятельно рекомендую вам их прочитать, чтобы глубже понимать то,
как работают браузеры.