Механизм рендеринга страницы в браузере, вы действительно понимаете?

внешний интерфейс браузер
Оханс Эммануэль Переводчик|Шелли

Целью данной статьи интерпретируется браузером в очень простом условиях, как HTML, CSS и JavaScript, мы можем преобразовать сайт для взаимодействия. Об этом процессе может помочь вам оптимизировать веб-приложения, чтобы получить больше скорости и повышения производительности.

Введение

Как браузеры отображают веб-сайты? В ближайшее время я разберу этот процесс, но сначала стоит рассмотреть некоторые основы.

Веб-браузер — это часть программного обеспечения, которое загружает файл с удаленного сервера (или локального диска) и отображает его вам, позволяя пользователям взаимодействовать с ним.

Я знаю, что вы знаете, что такое браузер. Однако в браузере есть часть программного обеспечения, называемая движком браузера. В разных браузерах некоторая часть браузера определяет, что отображать, на основе получаемых файлов, что называется движком браузера. Браузерный движок является основным программным компонентом каждого основного браузера, и разные разработчики браузеров называют свои движки разными именами. Браузерный движок Firefox называется Gecko, а движок Chrome называется Blink, который является ответвлением Webkit. Не путайтесь в названиях. Это просто имена. Ничего глубокого нет.

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

Посмотрите сравнение различных браузерных движков, если вам интересно.

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

Отправка и получение информации

Это не курс по компьютерным сетям, но вам, возможно, придется помнить, что данные отправляются через Интернет в «пакетах», а пакеты измеряются в байтах.

Компьютер сказал: пришлите мне количество байтов!

Я пытаюсь сказать, что когда вы пишете HTML, CSS и JS и пытаетесь открыть файл HTML в браузере, браузер считывает необработанные байты HTML с вашего жесткого диска (или из сети).

компьютер получает байтовые данные

Вы понимаете? Браузеры читают необработанные байты данных, а не фактические символы кода, который вы написали.

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

От необработанных байтов HTML к DOM

Объекты браузера должны иметь дело с объектами объектной модели документа (DOM). Итак, откуда берутся объекты DOM? это очень просто. Сначала преобразуйте необработанные байты данных в символы.

из байтов в символы

Вы можете увидеть это по символам кода, который вы пишете. Это преобразование выполняется на основе кодировки символов файла HTML. На этом этапе браузер преобразовал необработанные байты данных в фактические символы в файле. Но это не конечный результат. Эти символы далее анализируются в то, что называется «токен».

От персонажей к токенам

Итак, что же это за знаки? Куча символов в текстовом файле мало полезна для движка браузера. Без этого процесса токенизации эта куча символов просто генерировала бы серию бессмысленного текста, HTML-кода, а не настоящий веб-сайт.

Когда вы сохраняете файл с расширением .html, вы указываете механизму браузера анализировать файл как HTML-документ. Браузер «интерпретирует» этот файл, сначала анализируя его. Во время синтаксического анализа, особенно во время токенизации, браузер анализирует каждый открывающий и закрывающий «тег» в файле HTML. Синтаксический анализатор может распознавать каждую строку в угловых скобках, например «», «

», а также может вывести набор правил, применимых к любой из них. Например, теги, представляющие теги привязки, имеют свойства, отличные от свойств тегов, представляющих теги абзаца.

Концептуально разметку можно представить как некую структуру данных, содержащую информацию о HTML-теге. По сути, файлы HTML разбиты на небольшие единицы анализа, называемые тегами. Так браузеры начинают распознавать то, что вы написали.

Концептуальные заметки по тегам

Но разметка — это еще не конечный результат. После завершения токенизации токены будут преобразованы в узлы. Вы можете думать об узлах как о разных объектах с определенными свойствами. Фактически, лучшее объяснение состоит в том, чтобы думать об узлах как об отдельных объектах в дереве объектов документа. Но узел — это еще не окончательный результат.

Теперь давайте посмотрим на последний пункт. После создания эти узлы связываются в древовидную структуру данных, называемую DOM. DOM устанавливает отношения родитель-потомок, смежные родственные отношения и т. д. В этом объекте DOM отношения устанавливаются между каждым узлом. Теперь это то, что мы можем использовать.

Графический пример DOM

Если вы помните веб-дизайн 101, вы не открываете файлы CSS или JS в браузере для просмотра веб-страницы. Таким образом вы открываете файл HTML, в основном index.html.

Вы делаете это, потому что браузер сначала преобразует необработанные байты данных HTML в DOM.

HTML идет первым

В зависимости от размера файла HTML процесс построения модели DOM может занять некоторое время. Независимо от того, насколько мал файл, это займет некоторое время.

Теперь он был преобразован из разметки в узел и обратно в DOM. Как трансформируется CSS?

ДОМ создан. Типичный HTML-файл с некоторым количеством CSS будет содержать ссылку на таблицу стилей, подобную этой:

<!DOCTYPE html>
<html>
<head>
    <link rel="stylesheet" type="text/css" media="screen" href="main.css" />
</head>
<body>

</body>
</html>скопировать код

Когда браузер получает необработанные байты данных и запускает процесс построения DOM, он также делает запрос на получение связанной таблицы стилей main.css. Когда браузер начинает анализировать HTML, как только он находит тег ссылки файла css, он делает запрос на его получение. Как вы могли догадаться, браузеры по-прежнему получают необработанные байты данных CSS либо из Интернета, либо с локального диска.

Но как браузер обрабатывает необработанные байты данных этих CSS?

От необработанных байтов CSS к CSSOM

Когда браузер получает необработанные байты CSS, он инициирует процесс, аналогичный обработке необработанных байтов HTML. То есть необработанные байты данных преобразуются в символы, затем размечаются, затем формируются в узлы и, наконец, в древовидную структуру.

Что такое древовидная структура? Большинство людей знают термин DOM. Точно так же существует древовидная структура CSS, называемая объектной моделью CSS или сокращенно CSSOM.

Вы знаете, браузеры не могут использовать необработанные байты HTML или CSS. Его нужно преобразовать в форму, которую он может распознать, а именно в эти древовидные структуры.

Тот же процесс для байтов CSS!

В CSS есть нечто, называемое каскадированием. Каскадирование — это механизм браузера для определения того, как применять стили к элементам.

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

всего наилучшего. Браузеры имеют объекты DOM и CSSOM. Теперь мы можем отобразить что-нибудь на экране?

визуализировать дерево

Теперь у нас есть две отдельные древовидные структуры, у которых, похоже, нет общей цели.

DOM и CSSOM — это отдельные древовидные структуры.

Древовидные структуры DOM и CSSOM — это две отдельные древовидные структуры. DOM содержит всю информацию о взаимосвязи HTML-элементов страницы, а CSSOM содержит информацию о стилях элементов.

Теперь браузер объединяет деревья DOM и CSSOM в одно дерево рендеринга.

DOM + CSSOM = дерево рендеринга

Дерево рендеринга содержит всю информацию о видимом содержимом DOM на странице и всю информацию CSSOM, необходимую для различных узлов. Обратите внимание, что если элемент скрыт с помощью CSS, например, с display; none, то этот узел не будет включен в дерево рендеринга. Скрытые элементы отображаются в DOM, но не в дереве рендеринга. Это связано с тем, что дерево рендеринга объединяет информацию из DOM и CSSOM, поэтому оно знает, что не следует включать скрытые элементы в дерево.

После построения дерева рендеринга браузер переходит к следующему шагу: компоновке!

Теперь у нас есть содержимое на экране и информация о стилях для всего видимого содержимого, но на самом деле мы ничего не отображаем на экране.

Во-первых, браузер должен рассчитать точный размер и положение каждого объекта на странице. Это похоже на передачу информации о содержании и стиле всех элементов, которые должны отображаться на странице, талантливому математику. Затем математик использует окно просмотра браузера для вычисления точного положения и размера каждого элемента.

макет в процессе

Этот шаг макета учитывает контент и стили, полученные из DOM и CSSOM, и выполняет все необходимые расчеты макета. Иногда вы можете услышать, как люди называют эту фазу «макета» «перекомпоновкой».

Появление художника

Теперь, когда точное положение каждого элемента вычислено, остается только «отрисовать» элемент на экране.

подумай об этом. У нас есть вся информация, необходимая для отображения элемента на экране. Мы просто показываем это пользователю. Это все для этого этапа. Вооружившись содержимым элемента (DOM), стилями (CSSOM) и рассчитанной точной информацией о макете элемента, браузер теперь может «отрисовывать» узлы на экране один за другим. Теперь элемент наконец отображается на экране!

визуализировать блокирующие ресурсы

О чем вы думаете, когда слышите «блокировка рендеринга»? Я предполагаю, что вы думаете, что «что-то мешает фактическому рисованию узла на экране». Если вы так говорите, то вы абсолютно правы!

Первое эмпирическое правило оптимизации веб-сайта — как можно быстрее предоставить клиенту самые важные HTML и CSS. DOM и CSSOM должны быть созданы до того, как их можно будет успешно отрисовать, поэтому и HTML, и CSS являются ресурсами, блокирующими рендеринг. Суть в том, что вы должны предоставить HTML и CSS клиенту как можно скорее, чтобы оптимизировать время первого рендеринга вашего приложения.

Как выполняется JavaScript?

Хорошее веб-приложение обязательно будет использовать JavaScript. Это точно. «Проблема» с JavaScript заключается в том, что вы можете использовать JavaScript для изменения содержимого и стиля страницы. Таким образом, вы можете удалять и добавлять элементы из дерева DOM, а также изменять свойства CSSOM элементов с помощью JavaScript.

Здорово! Но есть цена, которую нужно заплатить. Рассмотрим следующий HTML-документ:

<!DOCTYPE html>
<html>

<head>
    <meta name="viewport" content="width=device-width,initial-scale=1">
    <title>Medium Article Demo</title>
    <link rel="stylesheet" href="style.css">
</head>

<body>
    <p id="header">How Browser Rendering Works</p>
    <div><img src="https://i.imgur.com/jDq3k3r.jpg"></div>
</body>

</html>скопировать код

Это очень простой документ. Таблица стилей style.css содержит только следующее утверждение:

body {
  background: #8cacea;
}скопировать код

Базовый рендеринг HTML-страницы

На экране отображается простой текст и изображение.

Как объяснялось ранее, браузер считывает необработанные байты HTML-файла с диска (или из сети) и преобразует их в символы. Далее символы разбиваются на токены. Когда синтаксический анализатор встречает , он запрашивает CSS-файл style.css. Построение DOM продолжается, и когда файл CSS возвращает некоторый контент, начинается построение CSSOM.

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

Это связано с тем, что JavaScript может одновременно изменять как DOM, так и CSSOM. Поскольку браузер не уверен, что будет делать тот или иной код JavaScript, он принимает меры предосторожности, чтобы полностью остановить построение DOM.

Посмотрим, насколько это плохо. В базовом HTML-документе, опубликованном ранее, мы вводим тег сценария, который содержит некоторые основные операторы JavaScript:

<!DOCTYPE html>
<html>

<head>
    <meta name="viewport" content="width=device-width,initial-scale=1">
    <title>Medium Article Demo</title>
    <link rel="stylesheet" href="style.css">
</head>

<body>

    <p id="header">How Browser Rendering Works</p>
    <div><img src="https://i.imgur.com/jDq3k3r.jpg"></div>

    <script>
        let header = document.getElementById("header");

        console.log("header is: ", header);
    </script>
</body>

</html>скопировать код

В теге script я посещу узел DOM с заголовком id и затем выведу его на консоль. который отлично работает следующим образом:

DOM успешная операция

Однако вы заметили, что этот тег сценария находится в нижней части теги тела? Давайте поставим это в голову и посмотрим, что произойдет:

<!DOCTYPE html>
<html>

<head>
    <meta name="viewport" content="width=device-width,initial-scale=1">
    <title>Medium Article Demo</title>
    <link rel="stylesheet" href="style.css">
    <script>
        let header = document.getElementById("header");

        console.log("header is: ", header);
    </script>
</head>

<body>

    <p id="header">How Browser Rendering Works</p>
    <div><img src="https://i.imgur.com/jDq3k3r.jpg"></div>
</body>

</html>скопировать код

Как только я это сделаю, заголовок станет нулевым.

Не удалось манипулировать DOM

Почему это происходит? Простой. Тег скрипта был обнаружен, когда парсер HTML строил модель DOM. На данный момент тег body и все его содержимое не проанализированы. Построение DOM остановится до завершения выполнения скрипта:

Строительство DOM остановлено

Когда скрипт пытается получить доступ к узлу DOM с идентификатором заголовка, он еще не существует, потому что DOM еще не завершил синтаксический анализ документа. Это подводит нас к другому важному вопросу. Расположение скрипта важно.

Это не все. Поведение такое же, если вы извлекаете встроенный скрипт во внешний локальный файл app.js. Строительство DOM все еще останавливается:

<!DOCTYPE html>
<html>

<head>
    <meta name="viewport" content="width=device-width,initial-scale=1">
    <title>Medium Article Demo</title>
    <link rel="stylesheet" href="style.css">
    <script src="app.js"></script>
</head>

<body>

    <p id="header">How Browser Rendering Works</p>
    <div><img src="https://i.imgur.com/jDq3k3r.jpg"></div>
</body>

</html>скопировать код

Так что, если app.js не является локальным и его нужно получать через Интернет?

<!DOCTYPE html>
<html>

<head>
    <meta name="viewport" content="width=device-width,initial-scale=1">
    <title>Medium Article Demo</title>
    <link rel="stylesheet" href="style.css">
    <script src="https://some-link-to-app.js"></script>
</head>

<body>

    <p id="header">How Browser Rendering Works</p>
    <div><img src="https://i.imgur.com/jDq3k3r.jpg"></div>
</body>

</html>скопировать код

Если интернет медленный и получение app.js занимает тысячи миллисекунд, построение DOM также будет приостановлено на тысячи миллисекунд! ! ! Это большая проблема с производительностью, и она не останавливается на достигнутом. JavaScript также может получить доступ к CSSOM и изменить его. Например, это допустимый оператор JavaScript:

document.getElementsByTagName("body")[0].style.backgroundColor = "red";скопировать код

Так что же происходит, когда синтаксический анализатор встречает тег скрипта, а CSSOM еще не готов? Ответ прост. Выполнение Javascript остановится, пока CSSOM не будет готов.

Таким образом, хотя построение DOM останавливается при встрече с тегом script, этого не происходит с CSSOM. Для CSSOM выполнение JS ожидает. Без CSSOM нет выполнения JS.

асинхронное свойство

По умолчанию каждый скрипт является блокировщиком парсера! Строительство DOM всегда прерывается. Однако есть способ изменить это поведение по умолчанию. Если вы добавите ключевое слово async в тег script, построение DOM не остановится. Создание DOM продолжится, и скрипт будет выполнен после завершения загрузки и готовности.

Вот пример:

<!DOCTYPE html>
<html>

<head>
    <meta name="viewport" content="width=device-width,initial-scale=1">
    <title>Medium Article Demo</title>
    <link rel="stylesheet" href="style.css">
    <script src="https://some-link-to-app.js" async></script>
</head>

<body>

    <p id="header">How Browser Rendering Works</p>
    <div><img src="https://i.imgur.com/jDq3k3r.jpg"></div>
</body>

</html>скопировать код
критический путь рендеринга

До сих пор мы обсудили все шаги от получения байтов HTML, CSS и JS до преобразования их в пиксели на экране. Весь этот процесс называется критическим путем рендеринга. Оптимизация производительности веб-сайта заключается в оптимизации критического пути рендеринга.

Хорошо оптимизированный сайт должен иметь возможность прогрессивного рендеринга и не допускать блокировки всего процесса.

В этом разница между медленным и быстрым веб-приложением. Продуманная стратегия оптимизации критического пути рендеринга (CRP) позволяет браузеру максимально быстро загружать страницы, определяя, какие ресурсы загружать первыми и в каком порядке.

резюме

Теперь, когда вы понимаете основы того, как браузеры отображают HTML, CSS и JS, я предлагаю вам уделить время изучению того, как вы можете использовать эти знания для оптимизации скорости своих страниц.

Глава о производительности в документации Google Web Fundamentals (https://developers.google.com/web/fundamentals/performance/why-performance-matters/) — хорошее место для начала.

Английский оригинал

https://blog.logrocket.com/how-browser-rendering-works-behind-the-scenes-6782b0e8fb10

Рекомендация курса

Цю Юэ, известный как «Второй мастер» в Цзянху, менеджер по продукту из технического специалиста, за 7 месяцев увеличил количество пользователей «Лотерейного помощника» с 0 до 20 миллионов. В колонке «Примечания о продуктах Цю Юэ» он поделится своим 10-летним опытом работы в области продуктов с 45 классами, которые помогут вам развить мышление о продукте и повысить осведомленность о вашем продукте.

Ограниченные по времени преимущества:

В течение ограниченного времени всего 68 иен для 24-часовой группы, сэкономьте 31 иен.

Отсканируйте код для бесплатного пробного чтения или подписки