CSS и JS блокируют две или три вещи

JavaScript
CSS и JS блокируют две или три вещи

Все в отпуске, я желаю всем счастливого Праздника Весны, всем, у кого нет предмета, удачного свидания вслепую, а тому, у кого есть предмет, удачного свидания вслепую~

Шаги рендеринга в браузере

Процесс рендеринга веб-страницы:

  1. Разобрать HTML в дерево DOM и CSS в дерево CSSOM
  2. Объедините дерево DOM и дерево CSSOM в дерево рендеринга
  3. Сгенерировать макет Layout, рассчитать размер и положение элементов в Render Tree
  4. Нарисуйте дерево рендеринга в пикселях и, наконец, отобразите его на экране.

Описанный выше процесс выполняется потоком рендеринга GUI.

Ядро браузера (процесс рендеринга)

В браузере есть несколько процессов, и процесс рендеринга называется ядром браузера, которое отвечает за рендеринг страницы и выполнение JS-скриптов. Процесс рендеринга отвечает за синтаксический анализ и рендеринг браузера.Внутри есть потоки движка JS, потоки рендеринга графического интерфейса, потоки управления циклом событий, потоки таймера и потоки HTTP.

Поток движка JS отвечает за выполнение сценариев JS, а поток рендеринга GUI отвечает за синтаксический анализ и рендеринг страницы.Они являются взаимоисключающими, то есть при выполнении JS страница прекращает синтаксический анализ и рендеринг. Это связано с тем, что если движок JS изменяет элементы страницы во время рендеринга страницы, например очищает страницу, это вызовет ненужные ошибки и ошибки при последующем рендеринге страницы. И поскольку JS часто требуется для работы с DOM, он включает в себя связь между потоком движка JS и потоком рендеринга графического интерфейса, а связь между потоками очень дорогая, что также является причиной того, что JS неэффективен в работе с DOM.

Разбирать, отображать и блокировать

Пример в этой статье нужно протестировать, когда консоль переключена в слабую сеть и без буфера:

Парсинг и рендеринг HTML/CSS в браузере принадлежат потоку рендеринга GUI, поэтому они взаимоисключающие и блокируются потоком движка JS. Ниже анализируется порядок синтаксического анализа и рендеринга браузера, а также отношения блокировки между ними с точки зрения фактической работы кода:

Блокировка CSS

  1. Загрузка и разрешение файлов CSS не повлияет на DOM, но заблокирует рендеринг DOM. Потому что дерево CSSOM должно синтезировать дерево рендеринга для отрисовки страницы. Следующий Test1 является стилем по умолчанию до завершения загрузки и синтаксического анализа CSS, Test2 не отображается до загрузки и синтаксического анализа CSS:
<button class="btn btn-primary">test1</button>
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/bootstrap@4.4.1/dist/css/bootstrap.min.css">
<div>test2</div>
  1. Последующие сценарии js не могут быть выполнены до тех пор, пока файл css не будет загружен и проанализирован. последующийalert('ok')Он не появится, пока css не будет загружен и проанализирован:
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/bootstrap@4.4.1/dist/css/bootstrap.min.css">
<script>
    alert('ok')
</script>
  1. Загрузка файла css не будет блокировать выполнение предыдущего сценария js. последующийalert('ok')Он появится до завершения загрузки css:
<script>
    alert('ok')
</script>
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/bootstrap@4.4.1/dist/css/bootstrap.min.css">

Поэтому, когда вам нужно выполнить js, которые не работают с элементами dom заранее, вы можете поместить js перед файлом css.

блокировка js

Загрузка и разбор файлов js блокирует процесс рендеринга графического интерфейса, то есть парсинг и рендеринг DOM и CSS будут заблокированы.

  1. Последующие HTML и CSS не могут быть проанализированы, пока файл js не будет загружен и проанализирован:
    <script src="https://code.jquery.com/jquery-3.4.1.js"></script>
    <div>test</div>
  1. Загрузка файла js не будет блокировать предыдущий анализ HTML и CSS:
    <div>test</div>
    <script src="https://code.jquery.com/jquery-3.4.1.js"></script>

Пункты к сведению

Во-первых, поток рендеринга GUI будет отображать содержимое на экране как можно раньше и не будет ждать, пока весь HTML будет проанализирован перед построением и размещением дерева рендеринга, а отобразит часть содержимого после его синтаксического анализа. остальное через сеть. Следующий test1 будет отображаться до загрузки файла js, а test2 будет отображаться после загрузки и выполнения файла js:

  <div>test1</div>
  <script src="https://code.jquery.com/jquery-3.4.1.js"></script>
  <div>test2</div>

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

<body>
  <script>
    document.body.remove()
  </script>  
  <link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/bootstrap@4.4.1/dist/css/bootstrap.min.css">
  <script src="https://code.jquery.com/jquery-3.4.1.js"></script>
</body>

Суммировать

Короче говоря, независимо от того, загружаете ли вы файлы js или файлы css, он будет блокировать рендеринг следующей страницы, но не будет блокировать предыдущий рендеринг, что соответствует нашей ожидаемой логике кодирования.