[БЕЗ_ЗВУКА] Мы рассмотрели с вами, как браузер загружает данные по сети, как он их обрабатывает, как формирует 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-у, и на ней мы не будем останавливаться. Здесь несколько ссылок, которые будут выложены к данным видео, в них подробнее рассмотрены принципы работы современных веб-браузеров. Я настоятельно рекомендую вам их прочитать, чтобы глубже понимать то, как работают браузеры.