Почему Google использует термин "блокировка рендеринга JavaScript"?

Увидеть:

https://developers.google.com/speed/docs/insights/BlockingJS

Google говорит там о "JavaScript-блокировке рендеринга", но, по моему мнению, этот термин неправильный, сбивающий с толку и вводящий в заблуждение. Похоже, "Google" тоже не понимает это?

Этот момент заключается в том, что выполнение Javascript всегда приостанавливает / блокирует рендеринг, а также всегда приостанавливает / блокирует "HTML-парсер" (по крайней мере, в Chrome и Firefox). Он даже блокирует его в случае внешнего js-файла в сочетании с тегом асинхронного скрипта!

Таким образом, разговор об удалении "Javascript, блокирующего рендеринг", например, с помощью async, подразумевает, что также есть неблокирующий Javascript или что "асинхронное выполнение Javascript" не блокирует рендеринг, но это не так!

Правильный термин будет: "Блокировка загрузки рендеринга". С помощью async вы избежите этого: загрузка файла js не будет приостанавливать / блокировать рендеринг. Но выполнение все равно будет блокировать рендеринг.

Еще один пример, который подтверждает, что, похоже, Google не "понимает" это.

<!DOCTYPE html>
<html>
<head>
    <meta charset="utf-8" />
    <title>Test</title>
</head>
<body>
    Some HTML line and this is above the fold
    <script>
        // Synchronous delay of 5 seconds
        var timeWhile = new Date().getTime(); 
        while( new Date().getTime() - timeWhile < 5000 );
    </script>
</body>
</html>

Я протестировал его в Firefox и Chrome, и они показывают (рендеринг): "Некоторая строка HTML, и это выше сгиба" через 5 секунд, а не в течение 5 секунд!!!! Похоже, что Google думает, что в таком случае Javascript не будет блокировать рендеринг, но, как ожидается из теории, он заблокирует. Перед началом выполнения js весь html уже находится в DOM (за исключением конечного тела / html tag), но рендеринг еще не завершен и будет приостановлен. Так что, если Google действительно знает об этом, то Chrome сначала завершит рендеринг, прежде чем начинать выполнение javascript.

Если вы берете приведенный выше пример и используете:

<script src="delay.js" async></script>

или же

<script src="delay.js"></script>

вместо внутреннего JavaScript. Тогда он также может дать те же результаты, что и в примере выше. Например:

  • Если предварительный загрузчик (сканирующий файлы, которые уже загружены) уже загрузил "delay.js", то до появления "HTML-парсера" в части Javascript.
  • Обычно внешние файлы из Google, Facebook и так далее уже хранятся в кеше, поэтому загрузка не производится, и они просто берут файл из кеша.

В подобных случаях (а также с асинхронным) результат будет таким же, как в примере выше (по крайней мере, в большинстве случаев). Потому что, если нет дополнительного времени загрузки, "выполнение Javascript" будет / может начаться до того, как предыдущий html закончит рендеринг.

Таким образом, в таком случае вы могли бы даже подумать о том, чтобы поместить "no-cache" / "no-store" в delay.js (или даже дополнительную задержку), чтобы сделать вашу страницу более быстрой. Заставив загрузку (или дополнительную задержку), вы дадите браузеру дополнительное время для завершения рендеринга предыдущего html, прежде чем выполнять Javascript, блокирующий рендеринг.

Так что я действительно не понимаю, почему Google (и другие) используют термин "блокировка рендеринга JavaScript", в то время как из теории и примеров из "реальной жизни" кажется, что это неправильный термин и неправильное мышление. Я не вижу, чтобы кто-то говорил об этом в Интернете, поэтому я не понимаю. Я знаю, что я чертовски умный (j/k), но мне это кажется немного странным, быть единственным с мыслями выше.

2 ответа

Я работаю с разработчиками в Chrome, Firefox, Safari и Edge и могу гарантировать, что люди, работающие над этими аспектами браузера, понимают разницу между async/defer и ни один. Вы можете обнаружить, что другие будут более вежливо реагировать на ваши вопросы, если вы вежливо их зададите.

Вот изображение из спецификации HTML на загрузку и выполнение скрипта:

Схема загрузки скрипта

Это показывает, что блокировка происходит во время выборки, если классический сценарий не имеет async или же defer, Это также показывает, что выполнение всегда будет блокировать синтаксический анализ, или, конечно, наблюдаемые эффекты синтаксического анализа. Это потому, что DOM и JS работают в одном потоке.

Я протестировал его в Firefox и Chrome, и они показывают (рендеринг): "Некоторая строка HTML, и это выше сгиба" через 5 секунд, а не в течение 5 секунд!!!!

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

Похоже, Google думает, что в таком случае Javascript не будет блокировать рендеринг

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

В подобных случаях (а также с асинхронным) результат будет таким же

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

в таком случае вы могли бы даже подумать о том, чтобы поместить "no-cache" / "no-store" в delay.js (или даже дополнительную задержку), чтобы сделать вашу страницу более быстрой. Заставив загрузку (или дополнительную задержку), вы дадите браузеру дополнительное время для завершения рендеринга предыдущего html, прежде чем выполнять Javascript, блокирующий рендеринг.

Почему бы не использовать defer в этом случае? Он достигает того же самого без потери пропускной способности и непредсказуемости.

Мартен Б, я проверял твой код, и ты действительно прав. Независимо от того, используете ли вы async, defer или что-то еще, строки над встроенным JavaScript не отображаются. Поэтому информация в документации Google неверна.

Другие вопросы по тегам