@segfaultBut, но я не знаю, ошибаетесь ли вы, но чтобы получить ответ на этот вопрос, вы говорите: «но кажется, что для выполнения кода JavaScript необязательно, чтобы он выполнялся полностью» (пример синхронная среда) Что вы имеете в виду именно под "разбором". Какой парсер? Анализатор HTML?

с о следующем коде:

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

Я протестировал его в Firefox и Chrome, и они показывают (рендеринг): «Одна строка HTML-кода» через 5 секунд, а не в течение 5 секунд. Почему браузер делает это?

Я понимаю, почему браузер должен останавливать рендеринг при выполнении JavaScript, потому что вы можете изменить стиль элементов с помощью JavaScript (в качестве примера). Это создаст проблемы, если браузер будет показывать и изменять контент в одно и то же время. Вот почему браузер блокирует рендеринг при выполнении JavaScript.

В приведенном выше примере при запуске с JavaScript «одна строка HTML-кода» уже анализируется «HTML-парсером». Это необходимо, потому что JavaScript может содержать, например, document.write, поэтому добавленная строка должна идти после предыдущего HTML. Очевидно, между «разбором HTML» и отображением / рендерингом того же HTML существует некоторое время, потому что в противном случае браузер в этом примере уже показал бы что-то в течение 5 секунд, но это не так.

Когда вы заменяете «Одну строку HTML-кода» большим количеством HTML-кода, браузер уже будет показывать некоторый контент в течение 5 секунд, поэтому в принципе возможно показывать уже некоторый контент.

Если бы я был браузером, я бы сделал:

Разбор "Одна строка HTML-кода"Видя какой-то блок JavaScriptЗакончите рендеринг HTML, предшествующего «блоку JavaScript», чтобы браузер отобразил на этом этапе: «Одна строка HTML-кода»Теперь приостановите рендеринг и выполните код JavaScript.После выполнения кода JavaScript снова начните рендеринг.

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

Может быть, это то, что браузеры могут улучшить, но, возможно, есть другая причина. Может быть, кто-то знает об этом больше и может мне это объяснить.

 msoft31 окт. 2017 г., 22:59
Браузер анализирует HTML, и он доступен в скрипте. Есть разница между разбором и рендерингом. Можно также сказать, что есть большое изменение в том, что скрипт может изменять содержимое, что потребует повторного рендеринга страницы. Таким образом, при рендеринге происходит увеличение скорости, как это делает браузер. Очевидно, ваш пример далек от реальной жизни, где можно было бы работать асинхронно, где это возможно. У меня нет доказательств или ссылок на спецификации, поэтому я оставлю это как комментарий.
 Maarten Bruins31 окт. 2017 г., 23:50
@msoft Браузер без проблем перерисовывает страницу из-за некоторых строк JavaScript. Это не повлияет на скорость. Причина, по которой браузер не выполняет рендеринг и «выполнение javascript» одновременно (по крайней мере, в Chrome и Firefox), заключается в том, что javascript может изменять стиль элементов. Вы не можете показать и изменить что-то в один и тот же момент. Это причина, а не увеличение скорости, потому что нет.
 George25 окт. 2017 г., 13:26
Как ни странно, если вы установите точку останова в JS, вы увидите, чтоОдна строка HTML-кода отображается до 5 секунд.
 Maarten Bruins31 окт. 2017 г., 23:50
@msoft Asynchronous даст тот же результат, если браузер получит скрипт из кеша. И если html предшествовал Javascript, например, это не «Одна строка HTML-кода», а «Тысячи строк HTML-кода», то возможно, что часть уже визуализирована до «выполнения javascript», а другая - нет. Браузер не всегда блокирует рендеринг первой части, поэтому не из-за увеличения скорости, как вы предлагаете. В противном случае браузер никогда не будет показывать html перед «выполнением javascript», и это не так.
 Maarten Bruins26 окт. 2017 г., 15:23
@ Джордж Это не так «странно», потому что определение отладчика таково: «Когда вызывается отладчик, выполнение приостанавливается в операторе отладчика». Они говорят о выполнении JavaScript. Рендеринг не может иметь место во время выполнения JavaScript, но я могу иметь место, когда нет выполнения. Таким образом, при приостановке выполнения HTML, предшествующий javascript, может быть воспроизведен снова.

Ответы на вопрос(2)

который вы используете в примере выше.

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

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

Надеюсь это поможет!

С уважением, Эби

 Maarten Bruins06 апр. 2018 г., 18:23
Также с асинхронностью это не так. Многие люди неправильно понимают Async, поэтому меня не удивляет, что вы так думаете. Javascript всегда блокирует рендеринг. Если предыдущий html еще не завершен с рендерингом, он будет заблокирован во время выполнения javascript. Async не имеет никакого влияния на это.
 Eby Jacob06 апр. 2018 г., 16:49
Если вы хотите, чтобы рендеринг происходил до выполнения javascript, попробуйте ленивую загрузку javascript, которая вызывается только после срабатывания события onload DOM. например, вы можете добавить асинхронный сценарий во внешний скрипт. <script async src = "script.js"> </ script>
 Maarten Bruins06 апр. 2018 г., 16:28
Спасибо, но это не так. Также внешние скрипты могут блокировать рендеринг. Особенно, когда контент поступает из кеша, а время загрузки отсутствует.

которые могут независимо выполняться браузером, но обе они могут работать с небольшими фрагментами кода HTML / CSS / и т. Д. И не требуют полной загрузки всех ресурсов, чтобы начать выполнять свою соответствующую работу. Конечно, все, что визуализируется, должно быть сначала проанализировано, но кажется, что для выполнения кода JavaScript не обязательно должен быть полностью завершен синтаксический анализ, и для того, чтобы начать отображать пользовательский контент как можно быстрее, это также имеет смысл для браузеры, чтобы начать рендеринг страницы до завершения анализа.

Рассмотрим эту модификацию вашего примера кода (я проверял это в Google Chrome версии 62.0.3202.75 на macOS):

<!DOCTYPE html>
<html>
    <head>
        <meta charset="utf-8" />
        <title>Test</title>
    </head>
    <body>
        One line of html code
        <script>
            // Synchronous delay of 5 seconds
            var timeWhile = new Date().getTime();
            for (var current = new Date().getTime(); current - timeWhile < 5000; current = new Date().getTime()) {
                if (current - timeWhile === 2500) {
                    alert(document.body.childNodes[0].nodeValue);
                    alert(document.body.childNodes[2].nodeValue);
                }
            };
        </script>
        Another line of HTML code
    </body>

я добавилalert()с вашим кодом вместоconsole.log()s потому что сброс / запись в консоль JavaScript также, кажется, блокируется синхронной задержкой.

Первыйalert() показывает строку «Одна строка HTML-кода» перед тем, как текст появляется на странице, доказывая, что эта часть страницы была проанализирована до ее рендеринга.

Тем не менее, второйalert() не бывает Поскольку строка «Другая строка HTML-кода» еще не проанализирована, она не определена как дочерний узелdocument.bodyпоэтому попытка доступа к нему приводит к ошибке, которая не позволяет отображать предупреждение, а вместо этого отображается в консоли JavaScript:Uncaught TypeError: Cannot read property 'nodeValue' of undefined.

Если вы перезапустите вручнуюalert(document.body.childNodes[2].nodeValue); в консоли после загрузки страницы вы увидите предупреждение «Другая строка HTML-кода», как и ожидалось.

Я не уверен, почему строка «Одна строка HTML-кода» не отображается на странице до того, как произойдет синхронная задержка, но я предполагаю, что поведение зависит от реализации браузера.

 Maarten Bruins02 нояб. 2017 г., 16:41
@segfaultBut, но я не знаю, ошибаетесь ли вы, но чтобы получить ответ на этот вопрос, вы говорите: «но кажется, что для выполнения кода JavaScript необязательно, чтобы он выполнялся полностью» (пример синхронная среда) Что вы имеете в виду именно под "разбором". Какой парсер? Анализатор HTML?
 segfault02 нояб. 2017 г., 16:24
@MaartenBruins Я не уверен, как ваш оригинальный пример показывает, что «Одна строка HTML-кода» находится в DOM, но не на экране, это то, что делает мой пример. Ничто в исходном примере не имеет доступа к DOM через JavaScript. Я не верю, что перепутал рендеринг и синтаксический анализ, я пытался сказать, что отдельные фрагменты страницы можно анализировать и впоследствии отображать независимо для каждого фрагмента.
 Maarten Bruins02 нояб. 2017 г., 01:39
Часть 1: Я читаю вашу статью сейчас, и я также делал тесты, как вы в прошлом, но ваш тест на самом деле ничего лишнего. Было бы достаточно знать, что «Одна строка HTML-кода» находится в DOM, но еще не на экране. Мой пример показывает то же самое. Остальное не нужно для этого обсуждения. Так что на самом деле нет ответа на вопрос;).
 Maarten Bruins02 нояб. 2017 г., 01:40
Часть 2. Также одно исправление относительно того, что вы говорили: «но кажется, что для выполнения кода JavaScript необязательно, чтобы он выполнялся полностью». HTML перед выполнением javascript (синхронизация) всегда должен быть первым в DOM, перед началом выполнения (поэтому анализ html должен быть завершен). Рендеринг предыдущего html не обязательно должен быть полностью завершен для запуска кода JavaScript. Но вы не должны путать «рендеринг» и «разбор HTML».
 Maarten Bruins02 нояб. 2017 г., 16:40
Вы правы, что я не получил доступ к DOM в этом моем примере, потому что вопрос был не об этой части. Я не доказал это своим тестом, но из теории (и более ранних тестов) я знаю, что в синхронной среде html должен быть в DOM, прежде чем начинать выполнение кода. Мой тест был больше о том, можно ли сделать «рендеринг» еще при запуске выполнения.

Ваш ответ на вопрос