Когда я ранее брал интервью у Toutiao, интервьюер Toutiao спросил меня, выполнение JS будет блокировать синтаксический анализ и рендеринг дерева DOM, поэтому будет ли загрузка CSS блокировать синтаксический анализ и рендеринг дерева DOM? Итак, далее я проведу тест на синтаксический анализ и рендеринг дерева DOM с помощью загрузки CSS.
Чтобы завершить этот тест, давайте сначала поговорим о том, как использовать хром для установки скорости загрузки.
- Откройте консоль хрома (нажмите F12), вы можете увидеть картинку ниже, фокус на том месте, где я нарисовал красный кружок
- Нажимаем на то место, где я нарисовал красный кружок (Без троттлинга), вы увидите следующую картинку, выбираем вариант GPRS
- Таким образом, верхняя граница нашей скорости скачивания ресурсов будет ограничена 20кб/с, ладно, тогда и войдем в нашу основную тему
Будет ли загрузка CSS блокировать синтаксический анализ и рендеринг дерева DOM?
Говорите с кодом:
<!DOCTYPE html>
<html lang="en">
<head>
<title>css阻塞</title>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<style>
h1 {
color: red !important
}
</style>
<script>
function h () {
console.log(document.querySelectorAll('h1'))
}
setTimeout(h, 0)
</script>
<link href="https://cdn.bootcss.com/bootstrap/4.0.0-alpha.6/css/bootstrap.css" rel="stylesheet">
</head>
<body>
<h1>这是红色的</h1>
</body>
</html>
Предположение: загрузка CSS блокирует синтаксический анализ и рендеринг дерева DOM.
Предполагаемый результат: перед загрузкой bootstrap.css следующее содержимое не будет проанализировано и отрисовано, поэтому то, что мы видим в начале, должно быть белым экраном, а h1 отображаться не будет. И в это время результатом console.log должен быть пустой массив.
Фактический результат: как показано ниже
css будет блокировать разбор дерева DOM?
Как мы видим из рисунка выше, когда css не загружен, h1 не отображается, но вывод консоли выглядит следующим образом
Можно знать, что DOM-дерево на данный момент проанализировано как минимум до h1, а css еще не загружен, а это значит, что css не будет блокировать синтаксический анализ DOM-дерева.
Загрузка CSS блокирует рендеринг дерева DOM?
На изображении выше мы также можем видеть, что когда css не загружен, на странице отображается белый экран, а красный шрифт не отображается до тех пор, пока не будет загружен css, то есть, хотя следующий контент анализируется, это не отображается. Таким образом, загрузка css блокирует рендеринг дерева DOM.
Личная оценка этого механизма
На самом деле, я думаю, это тоже может быть механизм оптимизации браузера. Потому что когда вы загружаете css, вы можете изменить стиль следующих узлов DOM.Если загрузка css не блокирует рендеринг дерева DOM, то при загрузке css дерево DOM, возможно, придется перерисовывать или перекомпоновывать, что вызвал некоторые Нет необходимых потерь. Поэтому я просто сначала разбираю структуру дерева DOM, завершаю работу, которую можно сделать, а затем жду, пока загрузится ваш CSS, и визуализирую дерево DOM в соответствии с окончательным стилем.Этот подход действительно будет лучше с точки зрения производительности. . . .
Будет ли работать блок загрузки css js?
Из приведенного выше вывода мы можем сделать вывод, что загрузка CSS не блокирует синтаксический анализ дерева DOM, но блокирует рендеринг дерева DOM. Итак, будет ли загрузка css блокировать выполнение js?
Опять же, проверьте по коду.
<!DOCTYPE html>
<html lang="en">
<head>
<title>css阻塞</title>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<script>
console.log('before css')
var startDate = new Date()
</script>
<link href="https://cdn.bootcss.com/bootstrap/4.0.0-alpha.6/css/bootstrap.css" rel="stylesheet">
</head>
<body>
<h1>这是红色的</h1>
<script>
var endDate = new Date()
console.log('after css')
console.log('经过了' + (endDate -startDate) + 'ms')
</script>
</body>
</html>
Предположение: загрузка CSS заблокирует последующий запуск js
Ожидаемый результат: код js, стоящий за ссылкой, не должен запускаться до тех пор, пока не будет загружен css.
фактические результаты:
Как видно из рисунка выше, код js перед оператором загрузки css выполняется первым, но код после оператора загрузки css не выполняется до тех пор, пока загрузка css не будет завершена. Это также показывает, что загрузка css блокирует выполнение последующих операторов js. Подробные результаты см. на следующем рисунке (загрузка css заняла 5600+ мс):
в заключении
Из вышеизложенного мы можем сделать следующие выводы:
- Загрузка CSS не блокирует разбор дерева DOM
- Загрузка CSS блокирует рендеринг дерева DOM
- Загрузка CSS заблокирует выполнение последующих операторов js,
Поэтому, чтобы не позволить пользователям видеть долгое время белого экрана, мы должны максимально улучшить скорость загрузки CSS, например, можно использовать следующие методы:
- Используйте CDN (поскольку CDN выберет ближайший узел с кэшированным содержимым, чтобы предоставить вам ресурсы в зависимости от условий вашей сети, что может сократить время загрузки)
- Сжатие CSS (вы можете использовать множество инструментов для упаковки, таких как webpack, gulp и т. д., или вы можете включить сжатие gzip)
- Разумное использование кеша (set cache-control, expires и E-tag — это все хорошо, но обратите внимание на одну проблему, то есть после обновления файла нужно избегать влияния кеша. Один из решения находится в имени файла, за которым следует номер версии)
- Уменьшите количество HTTP-запросов, объедините несколько файлов css или просто напишите встроенные стили напрямую (одним из недостатков встроенных стилей является то, что они не могут кэшироваться).
возобновить
Принципиальный анализ
Так почему же происходит описанное выше явление? Давайте проанализируем это из процесса рендеринга браузера.
Разные браузеры используют разные ядра, поэтому их процесс рендеринга также отличается. В настоящее время существует два основных:
процесс рендеринга вебкита
Процесс рендеринга геккона
Из приведенных выше двух блок-схем видно, что процесс рендеринга в браузере выглядит следующим образом:
- Анализ файлов HTML, создание дерева DOM, анализ файлов CSS для создания дерева CSSOM
- Объедините дерево Dom и дерево CSSOM для создания дерева рендеринга.
- Согласно рендерингу Render Tree, пиксели визуализируются на экране.
Из процесса мы видим, что
- Парсинг DOM и парсинг CSS — это два параллельных процесса, поэтому это также объясняет, почему загрузка CSS не блокирует парсинг DOM.
- Однако, поскольку дерево рендеринга зависит от дерева DOM и дерева CSSOM, оно должно дождаться создания дерева CSSOM, то есть после завершения загрузки ресурса CSS (или после сбоя загрузки ресурса CSS), прежде чем можно будет начать рендеринг. Поэтому загрузка CSS будет блокировать рендеринг Dom.
- Поскольку js может манипулировать предыдущими узлами Dom и стилями css, браузер будет поддерживать порядок css и js в html. Следовательно, таблица стилей будет загружена и выполнена до того, как будут выполнены последующие js. Таким образом, css заблокирует выполнение следующих js.
Пополнить
DOMContentLoaded
Для браузеров существует два основных события загрузки страницы: одно — DOMContentLoaded, а другое — onLoad. И onLoad ни о чем не говорит, он должен дождаться загрузки всех ресурсов страницы перед срабатыванием, к этим ресурсам относятся css, js, картинки и видео и т.д.
И DOMContentLoaded, как следует из названия, запускает это событие при анализе содержимого страницы. Что ж, как мы обсуждали выше, css блокирует рендеринг Dom и выполнение js, а js блокирует синтаксический анализ Dom. Тогда мы можем сделать предположение
- Когда на странице существует только css или js находится перед css, то DomContentLoaded не нужно ждать, пока загрузится css.
- Когда на странице существуют и css, и js, а js находится позади css, DomContentLoaded должен дождаться загрузки и css, и js перед запуском.
Давайте сначала проверим первый случай:
<!DOCTYPE html>
<html lang="en">
<head>
<title>css阻塞</title>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<script>
document.addEventListener('DOMContentLoaded', function() {
console.log('DOMContentLoaded');
})
</script>
<link href="https://cdn.bootcss.com/bootstrap/4.0.0-alpha.6/css/bootstrap.css" rel="stylesheet">
</head>
<body>
</body>
</html>
Результаты эксперимента следующие:
Из анимации видно, что событие DOMContentLoaded было вызвано до загрузки CSS. Потому что за css нет кода js.
Далее мы проверим второй случай, который очень прост, просто добавим строчку кода после css
<!DOCTYPE html>
<html lang="en">
<head>
<title>css阻塞</title>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<script>
document.addEventListener('DOMContentLoaded', function() {
console.log('DOMContentLoaded');
})
</script>
<link href="https://cdn.bootcss.com/bootstrap/4.0.0-alpha.6/css/bootstrap.css" rel="stylesheet">
<script>
console.log('到我了没');
</script>
</head>
<body>
</body>
</html>
Результаты эксперимента следующие:
Мы видим, что событие DOMContentLoaded запускается только после загрузки css. Следовательно, мы можем сделать вывод:- Если на странице существуют и css, и js, а js существует за css, событие DOMContentLoaded будет выполнено после загрузки css.
- В других случаях DOMContentLoaded не будет ждать загрузки CSS, а событие DOMContentLoaded не будет ждать загрузки других ресурсов, таких как изображения и видео.
Сверху и все. Я думаю, что неплохо указать рекомендацию хххх, добро пожаловать на обмен
Адрес этой статьи находится по адресу ->Адрес моего блога, добро пожаловать, чтобы начать или подписаться