Что происходит в навигации
Это вторая часть серии блогов из четырех частей, посвященной внутренней работе Chrome. В предыдущем посте мы рассмотрели, как разные процессы и потоки обрабатывают разные части браузера. В этом посте мы углубимся в то, как взаимодействуют каждый процесс и поток для отображения веб-сайта.
Давайте рассмотрим простой вариант использования просмотра веб-страниц: вы вводите URL-адрес в браузер, затем браузер извлекает данные из Интернета и отображает страницу. В этом посте мы сосредоточимся на той части, где пользователь запрашивает сайт, а браузер готовится отобразить страницу — также известную как навигация.
Все начинается с процесса браузера
![Процессы браузера](https://developer.chrome.com/static/blog/inside-browser-part2/image/browser-processes-1abcf214c73ef.png?authuser=5&hl=ru)
Как мы рассмотрели в части 1: ЦП, графический процессор, память и многопроцессная архитектура , все, что находится за пределами вкладки, обрабатывается процессом браузера. Процесс браузера имеет такие потоки, как поток пользовательского интерфейса, который рисует кнопки и поля ввода браузера, сетевой поток, который работает с сетевым стеком для получения данных из Интернета, поток хранилища, который контролирует доступ к файлам и многое другое. Когда вы вводите URL-адрес в адресную строку, ваш ввод обрабатывается потоком пользовательского интерфейса процесса браузера.
Простая навигация
Шаг 1. Обработка ввода
Когда пользователь начинает вводить текст в адресную строку, первое, что спрашивает поток пользовательского интерфейса: «Это поисковый запрос или URL-адрес?». В Chrome адресная строка также является полем ввода для поиска, поэтому поток пользовательского интерфейса должен проанализировать и решить, отправить ли вас в поисковую систему или на запрошенный вами сайт.
![Обработка ввода пользователя](https://developer.chrome.com/static/blog/inside-browser-part2/image/handling-user-input-24fea2c817a6a.png?authuser=5&hl=ru)
Шаг 2. Запустите навигацию.
Когда пользователь нажимает Enter, поток пользовательского интерфейса инициирует сетевой вызов для получения содержимого сайта. Индикатор загрузки отображается в углу вкладки, а сетевой поток проходит через соответствующие протоколы, такие как поиск DNS и установление TLS-соединения для запроса.
![Начало навигации](https://developer.chrome.com/static/blog/inside-browser-part2/image/navigation-start-4aeb163d61a8c.png?authuser=5&hl=ru)
На этом этапе сетевой поток может получить заголовок перенаправления сервера, например HTTP 301. В этом случае сетевой поток сообщает потоку пользовательского интерфейса, что сервер запрашивает перенаправление. Затем будет инициирован другой запрос URL.
Шаг 3: Прочтите ответ
![HTTP-ответ](https://developer.chrome.com/static/blog/inside-browser-part2/image/http-response-0ae2751b24973.png?authuser=5&hl=ru)
Как только тело ответа (полезная нагрузка) начинает поступать, сетевой поток при необходимости просматривает первые несколько байтов потока. В заголовке Content-Type ответа должно быть указано, какой это тип данных, но поскольку он может отсутствовать или быть неверным, здесь выполняется анализ типа MIME . Как сказано в исходном коде, это «хитрое дело». Вы можете прочитать комментарий, чтобы узнать, как разные браузеры обрабатывают пары «тип контента/полезная нагрузка».
Если ответом является HTML-файл, следующим шагом будет передача данных в процесс рендеринга, но если это zip-файл или какой-либо другой файл, это означает, что это запрос на загрузку, поэтому им необходимо передать данные в менеджер загрузки.
![Обнюхивание MIME-типа](https://developer.chrome.com/static/blog/inside-browser-part2/image/mime-type-sniffing-444e1a2f5b037.png?authuser=5&hl=ru)
Здесь также происходит проверка SafeBrowsing . Если домен и данные ответа соответствуют известному вредоносному сайту, сетевой поток выдает предупреждение и отображает страницу с предупреждением. Кроме того, выполняется проверка блокировки чтения блоков перекрестного происхождения ( CORB ) , чтобы гарантировать, что конфиденциальные межсайтовые данные не попадут в процесс рендеринга.
Шаг 4. Найдите процесс рендеринга
Как только все проверки выполнены и сетевой поток уверен, что браузер должен перейти на запрошенный сайт, сетевой поток сообщает потоку пользовательского интерфейса, что данные готовы. Затем поток пользовательского интерфейса находит процесс рендеринга для продолжения рендеринга веб-страницы.
![Найти процесс рендеринга](https://developer.chrome.com/static/blog/inside-browser-part2/image/find-renderer-process-4d4055665d4a7.png?authuser=5&hl=ru)
Поскольку для получения обратного ответа сетевому запросу может потребоваться несколько сотен миллисекунд, применяется оптимизация для ускорения этого процесса. Когда поток пользовательского интерфейса отправляет URL-запрос сетевому потоку на шаге 2, он уже знает, на какой сайт они переходят. Поток пользовательского интерфейса пытается заранее найти или запустить процесс отрисовки параллельно с сетевым запросом. Таким образом, если все пойдет так, как ожидалось, процесс рендеринга уже находится в состоянии ожидания, когда сетевой поток получил данные. Этот резервный процесс может не использоваться, если навигация перенаправляет между сайтами, и в этом случае может потребоваться другой процесс.
Шаг 5. Зафиксируйте навигацию
Теперь, когда данные и процесс рендеринга готовы, IPC отправляется из процесса браузера в процесс рендеринга для фиксации навигации. Он также передает поток данных, чтобы процесс рендеринга мог продолжать получать данные HTML. Как только процесс браузера получит подтверждение того, что в процессе рендеринга произошла фиксация, навигация будет завершена и начнется этап загрузки документа.
На этом этапе адресная строка обновляется, а индикатор безопасности и пользовательский интерфейс настроек сайта отражают информацию о сайте на новой странице. История сеансов для вкладки будет обновлена, поэтому кнопки «Назад» и «Вперед» будут перемещаться по сайту, на который только что был осуществлен переход. Чтобы облегчить восстановление вкладки/сеанса при закрытии вкладки или окна, история сеанса сохраняется на диске.
![Зафиксировать навигацию](https://developer.chrome.com/static/blog/inside-browser-part2/image/commit-navigation-bc2943921c6f6.png?authuser=5&hl=ru)
Дополнительный шаг: начальная загрузка завершена
После фиксации навигации процесс рендеринга продолжает загрузку ресурсов и визуализирует страницу. Подробности того, что происходит на этом этапе, мы рассмотрим в следующем посте. Как только процесс рендеринга «завершает» рендеринг, он отправляет IPC обратно в процесс браузера (это происходит после того, как все события onload
были запущены во всех кадрах на странице и завершили выполнение). На этом этапе поток пользовательского интерфейса останавливает счетчик загрузки на вкладке.
Я говорю «завершается», потому что клиентский JavaScript все еще может загружать дополнительные ресурсы и отображать новые представления после этого момента.
![Загрузка страницы завершена](https://developer.chrome.com/static/blog/inside-browser-part2/image/page-finish-loading-1bee6888e9e56.png?authuser=5&hl=ru)
Переход на другой сайт
Простая навигация завершена! Но что произойдет, если пользователь снова вставит другой URL-адрес в адресную строку? Что ж, процесс браузера выполняет те же шаги для перехода на другой сайт. Но прежде чем он сможет это сделать, ему необходимо проверить на отображаемом в данный момент сайте, заботится ли он о событии beforeunload
.
beforeunload
можно создать команду «Покинуть этот сайт?» предупреждение, когда вы пытаетесь уйти или закрыть вкладку. Все внутри вкладки, включая ваш код JavaScript, обрабатывается процессом рендеринга, поэтому процесс браузера должен сверяться с текущим процессом рендеринга при поступлении нового запроса навигации.
![обработчик событий перед выгрузкой](https://developer.chrome.com/static/blog/inside-browser-part2/image/beforeunload-event-handle-53b6fa7dd9be3.png?authuser=5&hl=ru)
Если навигация была инициирована из процесса отрисовки (например, пользователь щелкнул ссылку или клиентский JavaScript запустил window.location = "https://newsite.com"
), процесс отрисовки сначала проверяет обработчики beforeunload
. Затем он проходит тот же процесс, что и навигация, инициированная процессом браузера. Единственное отличие состоит в том, что запрос навигации передается от процесса рендеринга к процессу браузера.
Когда новая навигация выполняется на сайт, отличный от отображаемого в данный момент, вызывается отдельный процесс рендеринга для обработки новой навигации, в то время как текущий процесс рендеринга сохраняется для обработки таких событий, как unload
. Дополнительные сведения см. в обзоре состояний жизненного цикла страницы и о том, как можно подключиться к событиям с помощью API жизненного цикла страницы .
![новая навигация и выгрузка](https://developer.chrome.com/static/blog/inside-browser-part2/image/new-navigation-unload-29ee714c3fcf4.png?authuser=5&hl=ru)
В случае сервисного работника
Одним из недавних изменений в этом процессе навигации является введение работника службы . Service Worker — это способ записи сетевого прокси в коде вашего приложения; позволяя веб-разработчикам иметь больший контроль над тем, что кэшировать локально и когда получать новые данные из сети. Если сервис-воркер настроен на загрузку страницы из кэша, нет необходимости запрашивать данные из сети.
Важно помнить, что Service Worker — это код JavaScript, который выполняется в процессе рендеринга. Но когда приходит навигационный запрос, как процесс браузера узнает, что на сайте есть сервис-воркер?
![Поиск области действия сервисного работника](https://developer.chrome.com/static/blog/inside-browser-part2/image/service-worker-scope-look-f48a8d509535a.png?authuser=5&hl=ru)
Когда сервис-воркер зарегистрирован, его область действия сохраняется в качестве ссылки (подробнее об области можно прочитать в статье «Жизненный цикл сервис-воркера »). Когда происходит навигация, сетевой поток проверяет домен по зарегистрированным областям Service Worker. Если Service Worker зарегистрирован для этого URL-адреса, поток пользовательского интерфейса находит процесс рендеринга, чтобы выполнить код Service Worker. Сервисный работник может загружать данные из кэша, устраняя необходимость запрашивать данные из сети, или может запрашивать новые ресурсы из сети.
![навигация для работника сферы обслуживания](https://developer.chrome.com/static/blog/inside-browser-part2/image/serviceworker-navigation-8576df1bffcf9.png?authuser=5&hl=ru)
Предварительная загрузка навигации
Вы можете видеть, что этот обратный путь между процессом браузера и процессом рендеринга может привести к задержкам, если сервис-воркер в конечном итоге решит запросить данные из сети. Предварительная загрузка навигации — это механизм, ускоряющий этот процесс за счет загрузки ресурсов параллельно с запуском сервисного работника. Он помечает эти запросы заголовком, позволяя серверам принимать решение об отправке различного контента для этих запросов; например, только что обновленные данные вместо полного документа.
![Предварительная загрузка навигации](https://developer.chrome.com/static/blog/inside-browser-part2/image/navigation-preload-a859b1ad065e3.png?authuser=5&hl=ru)
Заворачивать
В этом посте мы рассмотрели, что происходит во время навигации и как код вашего веб-приложения, такой как заголовки ответов и клиентский JavaScript, взаимодействует с браузером. Знание шагов, которые браузер выполняет для получения данных из сети, облегчает понимание того, почему были разработаны API, такие как предварительная загрузка навигации. В следующем посте мы углубимся в то, как браузер оценивает наш HTML/CSS/JavaScript для отображения страниц.
Вам понравился пост? Если у вас есть какие-либо вопросы или предложения по поводу будущего поста, я буду рад услышать ваше мнение в разделе комментариев ниже или на @kosamari в Твиттере.