Статьи

блок ссылок блокирует анализ DOM

Сегодня мы довольно хорошо разбираемся в том, как работает JavaScript. Мы знаем, что элементы скрипта блокируют рендеринг (ну, фактически блокирует синтаксический анализ, что задерживает рендеринг), и мы знаем почему8. Конечно, поэтому мы помещаем элементы скрипта в конец документа. Но знаете ли вы, что блок ссылок тоже блокируется?

* документ . запись может повлиять на дерево DOM, поэтому синтаксический анализ гарантирует, что они происходят синхронно

Конечно, я сделал, и что?

В прошлом было маловероятно, что вы включили бы внешний ресурс CSS, но сегодня это изменилось. Сегодня у нас есть сервисы, предоставляющие шрифты, и в этот момент вы связываетесь с внешним сервисом из элемента head (потому что мы помещаем CSS в заголовок и скрипт в конце тела).

Если этот сервис по какой-либо причине зависнет, он также повесит вашу страницу. Что-то, что мы провели в сообществе JavaScript долгое время, пытаясь избежать этого, и теперь мы рискуем повториться.

Почему это происходит?

Немного огорчает то, что я могу полностью понять, почему элемент скрипта блокирует синтаксический анализ DOM (и, следовательно, блокирует рендеринг), но я не могу понять, почему внешняя таблица стилей будет.

Возможно, это потому, что мы могли бы включать динамический контент через CSS — но я сомневаюсь в этом. Динамическое содержимое на самом деле не отображается в дереве DOM, поэтому я предполагаю, что оно не блокирует процесс анализа. Так что еще это может быть? Предложения в комментариях, пожалуйста!

Возможно, это ошибка? Safari, Chrome и Firefox страдают от этой проблемы. Opera этого не делает (но зато блокирует ли он и JavaScript — у меня такое чувство, что нет). Я не тестировал IE (отчасти потому, что был уверен, отчасти потому, что не хотел запускать виртуальную машину — если кто-то мог подтвердить, это было бы супер).

Прямо сейчас я не уверен, в чем причина, но я знаю, что это подвергает риску некоторые веб-сайты.

пример

Этот URL будет отображать зависание: http://jsbin.com/agumu4/3/ — убедитесь, что у вас открыта веб-консоль, и обновите ее, чтобы наблюдать за изменением состояния.

<!DOCTYPE html>
<html>
<head>
<meta charset=utf-8 />
<title>Hang test</title>
<script>
// script in head to debug state change
console.log('doc state: ' + document.readyState);

document.onreadystatechange = function () {
console.log('doc state change: ' + document.readyState);
};
</script>
<link href="http://hang.nodester.com/hang.css?5000" rel="stylesheet" />
</head>
<body>
<p>Hello World</p>
</body>
</html>

тестирование

Я создал простой сервис подвешивания, который вы можете использовать самостоятельно. Он работает на Node, поэтому не стоит беспокоиться о сбое в работе машины из-за зависания (в отличие от использования PHP для тестирования с использованием режима сна — который мог бы уничтожить общедоступную машину).

Для тестирования включите следующий URL: http://hang.nodester.com/file.type?ms

т.е. http://hang.nodester.com/foo.css?2000 вернет файл с типом mime CSS и зависнет на 2000 миллисекунд.

The best way to determine when the DOM is loaded (or loading) when you can’t see the output is to listen for the readystatechange event (ht). So in my test, I’ve included some script that tells me where the DOM is up to, and I can visually confirm whether the link element is hanging.

What about font includes?

I also tested including hanging fonts via CSS, i.e. if you copied the @font-face declarations, but the font service was down: this does not hang the page. However, you do suffer from the FOUC, but that’s a whole different issue.

The fix

As per anything that hangs: do it asynchronously to the DOM rendering — or rather after the DOM has done most, if not all of the parsing. That is, to use JavaScript to insert the link element once the DOM — or rather content is ready. Here’s a simple example: http://jsbin.com/agumu4/4 — note that the readystate says it’s still loading, that’s because my DOM doesn’t fully load when the JavaScript appends the link element (i.e. it doesn’t wait for an event, it’s just at the bottom of the document).

 

From http://remysharp.com/2011/06/08/link-elements-block-dom-parsing-too/