Асинхронная загрузка css в друпал. Грабли, грабли, грабли

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

Обычная загрузка CSS на сегодня …содержание…

CSS блокирует отрисовку, заставляя пользователя смотреть на белый экран до полной загрузки all-of-my-styles.css .

Обычно принято объединять весь CSS сайта в один-два ресурса, что значит, что пользователь скачивает много правил, которые не применяются к текущей странице. Это потому, что сайт включает в себя разные типы страниц со множеством «компонентов», а отдача CSS на уровне отдельных компонентов в HTTP/1 ухудшает быстродействие.

Это не проблема в случае SPDY и HTTP/2, где можно передавать много небольших ресурсов с минимальными издержками, и кешировать их независимо.

…содержание…

Это решает вопрос избыточности, но для этого вам нужно уже при выводе знать, что будет на странице, что может мешать потоковой отдаче. Кроме того, браузеру всё еще приходится загружать весь CSS до того, как он может что-либо отобразить. Медленная загрузка /site-footer.css задержит отрисовку всего .

Современный подход к загрузке CSS // https://github.com/filamentgroup/loadCSS !function(e){"use strict" var n=function(n,t,o){function i(e){return f.body?e():void setTimeout(function(){i(e)})}var d,r,a,l,f=e.document,s=f.createElement("link"),u=o||"all" return t?d=t:(r=(f.body||f.getElementsByTagName("head")).childNodes,d=r),a=f.styleSheets,s.rel="stylesheet",s.href=n,s.media="only x",i(function(){d.parentNode.insertBefore(s,t?d:d.nextSibling)}),l=function(e){for(var n=s.href,t=a.length;t--;)if(a[t].href===n)return e() setTimeout(function(){l(e)})},s.addEventListener&&s.addEventListener("load",function(){this.media=u}),s.onloadcssdefined=l,l(function(){s.media!==u&&(s.media=u)}),s} "undefined"!=typeof exports?exports.loadCSS=n:e.loadCSS=n}("undefined"!=typeof global?global:this) /* Стили для «шапки» страницы, плюс: */ .main-article, .comments, .about-me, footer { display: none; } loadCSS("/the-rest-of-the-styles.css");

В этом коде мы заготовили немножко встроенных стилей, которые дают нам быструю начальную отрисовку и скрывают те элементы, для которых у нас еще нет стилей, а остальной CSS мы потом подгружаем асинхронно с помощью JavaScript. Этот остальной CSS переопределит display: none для.main-article и т.п..

Более приближенный к жизни пример - моя оффлайновая вики , где это сработало на ура:

На 3G первая отрисовка на 0,6 секунды быстрее. Полные результаты до и после .

Но есть и пара недостатков:

Нужна (небольшая) JavaScript-библиотека

К сожалению, это из-за реализации в WebKit. Как только добавляется на страницу, WebKit блокирует отрисовку до загрузки файла стилей, даже если его добавили скриптом.

В Firefox и IE/Edge, файлы стилей, добавленные скриптом, грузятся полностью асинхронно. Стабильная версия Chrome пока еще ведет себя как WebKit, но в Canary мы перешли на поведение Firefox/Edge.

Вы ограничены двумя фазами загрузки

В предыдущем примере встроенный CSS скрывает содержимое, у которого еще нет стилей, с помощью display:none , затем асинхронно загружаемый CSS открывает его. Если развить эту идею до двух и более CSS-файлов, они могут загружаться не по порядку, вызывая «перескоки» содержимого по ходу загрузки:

«Скачущий» контент бесит пользователей почти наравне со всплывающей рекламой . Сжечь бы эту гадость.

Раз вы ограничены двумя фазами загрузки, вам приходится выбирать, что будет по-быстрому рисоваться сразу, а что будет «всем остальным». Конечно, вы захотите сразу отобразить содержимое первого экрана, но размер этого «первого экрана» у всех разный. Да, ёлки-палки, вам придется найти одно решение для всех размеров.

Способ проще и лучше … … … … …

План в том, чтобы для каждого блокировать отрисовку контента, пока стили грузятся, но разрешить отрисовку контента перед ним. Стили грузятся параллельно, но применяются последовательно. Благодаря этому начинает вести себя как .

Допустим, CSS для «шапки» сайта, статьи и «подвала» загрузился, а всё остальное только грузится, вот как тогда будет выглядеть страница:

  • «Шапка»: отобразилась
  • Статья: отобразилась
  • Комментарии: не отобразились, CSS перед ними еще не загрузился (/comment.css)
  • Раздел «обо мне»: не отобразился, CSS перед ним еще не загрузился (/comment.css)
  • «Подвал»: не отобразился, CSS перед ним еще не загрузился (/comment.css), даже несмотря на то, что его собственный CSS уже загружен

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

Нужно быть внимательными при использовании систем раскладки, где она определяется содержимым (напр. таблиц и флексбоксов), чтобы избежать «скачков» контента по ходу загрузки. Это не новая проблема, но с постепенной отрисовкой натыкаться на нее придется чаще. Можно исправить поведение флексбоксов хаками, но CSS-гриды - гораздо лучшая система для раскладки всей страницы (флексбоксы при этом великолепны для небольших компонентов).

Изменения в Chrome

Нынешнее поведение Chrome/Safari обратно совместимо, они лишь блокируют отрисовку дольше, чем нужно. С поведением Firefox всё чуточку сложнее, но есть обходной путь…

Фикс для Фокса

Поскольку Firefox не всегда блокирует отрисовку в случае в , нужно немного повозиться с ним, чтобы избежать мелькания «голого» контента. К счастью, это очень легко, поскольку блокирует парсинг, но также дожидается загрузки стилей:

Чтобы это сработало, элемент должен не быть пустым, пробела в нем вполне достаточно.

Firefox и Edge с IE покажут вам чудесную постепенную отрисовку, тогда как Chrome и Safari будут показывать белый экран до полной загрузки всего CSS. Нынешнее поведение Chrome и Safari не хуже, чем при размещении всех стилей в , так что можно начать применять этот метод уже сейчас. В ближайшие месяцы Chrome перейдет на подход Edge, и быструю отрисовку увидит больше пользователей.

Так что вот вам гораздо более простой способ грузить только нужный CSS и заодно получить более быструю отрисовку. Пользуйтесь на здоровье!

Все мои мысли были направлены на решение основной проблемы:

В общем случае [при использовании data:URL], загрузка страницы не ускорится, а даже может замедлиться, потому что фоновые картинки (включенные через data:URL) будут грузиться в один поток, а не в несколько при обычном использовании спрайтов. Если фоновых картинок достаточно много (несколько десятков Кб), то это окажется существенным.

Данная статья как раз посвящена тому, как можно достаточно успешно справиться с указанной проблемой. Интересно? Тогда, поехали.

Постановка задачи

При использовании data:URL итоговый CSS-файл занимает довольно большой объем (фактически, размер всех картинок*1,2...1,5 + базовый CSS). И это в виде архива. Если файл не заархивирован, то его дополнительный размер увеличивается многократно (в 2,5-3 раза относительно размера всех фоновых изображений), но это не так существенно, ибо пользователей с отключенным сжатием для CSS-файлов сейчас единицы.

Что нам, фактически, нужно? Во-первых, нужно разделить весь массив CSS-правил на относящиеся к фоновым изображениям и не относящиеся. Во-вторых, сообщить браузерам, что они могут отобразить страницу без первого массива правил (ведь если в нем содержатся только фоновые изображения, то они могут и подождать чуть-чуть).

Чего мы таким образом добиваемся? Фактически, используя такой подход, мы создаем другой контейнер для фоновых изображений (не ресурсное изображение, а CSS-файл), который удобнее использовать в большинстве случаев. Мы объединяем все фоновые картинки не через CSS Sprites, а через data:URL, и можем загрузить их все одним файлом (в котором каждая картинка будет храниться совсем отдельно). При этом избегаем любых проблем с позиционированием фона.

Теоретическое решение

Все гениальное просто, поэтому мы можем загружать в начале странице легкий-легкий CSS-файл (безо всяких фоновых изображений, только базовые стили, чтобы только отобразить страницу корректно), потом по комбинированному window.onload грузить в 2-4 потока динамические файлы стилей.

Возможные минусы: после загрузки каждого дополнительного CSS-файла будет перерисовка страницы. Если таких файлов всего 1 или 2, то отображение страницы произойдет значительно быстрее.

Почему мы не распараллелим загрузку файлов стилей в самом начале документа? Потому что два файла будут загружаться медленнее, чем один. К тому же мы ратуем за максимально быстро отображение страницы в браузере пользователя, поэтому исходный объем загружаемого CSS должен быть минимальным (можно также рассмотреть варианты по включению его в сам HTML).

На практике

На практике все оказалось не сильно сложнее. Мы загружаем в head страницы (до вызовов любых внешних файлов) наш «легкий» CSS:

А затем добавляем в комбинированный window.onload (в самое начало) создание нового файла стилей, который дополняет уже загрузившийся фоновыми изображениями:

Function combinedWindowOnload() { load_dynamic_css("background-images.css"); ... }

В результате мы имеем максимально быстрое отображение страницы, а затем стадию пост-загрузки, которая вытянет и с сервера все дополнительные картинки (тут уже сам браузер постарается), стилевые правила и скрипты.

А доступность?

Внимательные читатели уже заготовили вопрос: а что, если у пользователя отключен JS? Ну, тут должно быть все просто: мы добавляем соответствующий noscript для поддержки таких пользователей.

С маленьким нюансом: noscript не может находиться в head , а link не может находиться в body . Если мы соблюдаем стандарты (все же иногда лучше довериться профессионалам и не ставить браузеры в неудобное положение, когда они встретятся с очередным отклонением от спецификации), то стоит искать обходные пути.

После небольших экспериментов с коллекцией styleSheets и другими DOM-объектами, было выделено следующее изящное решение, обеспечивающее работу схемы во всех браузерах (замечание: после многоличсленных экспериментах было решено остановиться на HTML-комментариях: они оказались наилучшим способом запретить загрузку указанного CSS-файла):

/* если мы сможем создать динамический файл стилей */ if (document.getElementsByTagName) { /* то добавляем в загрузку облегченную версию */ document.write("\x3clink href="light-light.css" rel="stylesheet" type="text/css" media="all"/>"); /* после этого начинаем HTML-комментарий */ document.write("\x3c--"); }

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

Почему комментарии являются еще и условными комментариями для IE? Просто потому что на обычные пустые комментарии Firefox отреагировал странно, и я сейчас нахожусь в поисках кроссбраузерного решения.

Грабли, грабли, грабли...

В ходе тестирования в Internet Explorer обнаружилось, что если добавлять файл стилей сразу параллельно со скриптами (в функции, которая для него срабатывает по onreadystatechange), то IE «морозит» первоначальную отрисовку страницы (т.е. показывает белый экран), пока не получит «свеженький» файл стилей. Для него пришлось вставить фиктивную задержку следующим образом:

SetTimeout("load_dynamic_css("background-images.css")",0);

В Safari же логика отображения страницы в зависимости от загружаемых файлов отличается ото всех браузеров. Подробнее можно прочитать эту заметку о FOUC проблеме и возможных решениях . Если в двух словах, то можно жестко определить начальный набор файлов, необходимых для отображения страницы на экране (HTML/CSS/JS), а можно начать загружать все файлы в порядке приоритетности (и выполняя все их зависимости) и проверять время от времени, можно ли уже отобразить страницу (выполняя все вычисления в фоновом режиме без обновления экрана). В общем, у Safari второй подход, поэтому ничего лучше выноса загрузки динамического CSS-файла с фоновыми картинками после срабатывания window.onload (который, на самом деле, срабатывает раньше, чем во всех остальных браузерах) придумать не удалось. Зато первоначальная картинка в браузере появляется быстрее.

Итак, если брать сразу комбинированный window.onload и добавлять в него загрузку стилей, то получится примерно такая конструкция:

/* объявляем функцию по динамической загрузке стилей и скриптов первый параметр - путь к файлу, второй - тип файла К сожалению, функция объявлена глобальна */ function loadDynamic (src,type){ var node=document.createElement(type?"link":"script"); node = document.getElementsByTagName("head").appendChild(node); /* если передаем второй параметр, то это таблица стилей */ if(type){ node.setAttribute("rel","stylesheet"); node.setAttribute("media","all") } node.setAttribute("type","text/"+(type?"css":"javascript")); node.setAttribute(type?"href":"src",src) } (function(){ /* немного модифицированная версия обработчика */ function combinedWindowOnload(){ if(arguments.callee.done){return} arguments.callee.done=true; if(document.getElementsByTagName){ /* если не Safari, то загружаем CSS с фоновыми изображениями динамически */ if(!/WebKit/i.test(navigator.userAgent)){ /* для обхода IE добавляем псевдо-задержку */ setTimeout("loadDynamic("background-images.css",1)",0); } /* ставим на поток загрузку всех наших скриптов */ loadDynamic("some_scripts.js"); } } /* дальше идет стандартный кроссбраузерный код с */ ... /* навешиваем на window обработчик по событию Onload, спасибо lusever за компактный вид */ window(/*@cc_on "on"+@*/"load",function(){ /* если Safari, то загружаем наконец этот CSS */ if(/WebKit/i.test(navigator.userAgent)){ loadDynamic("background-images.css",1); } /* добавочный вызов WindowOnload для "старых" браузеров */ combinedWindowOnload() },false) })()

Выигрыш

При наличии у вас большого количества маленьких декоративных фоновых изображений (например, для на каждой странице используется от 30 до 40 различных картинок, общий объем которых составляем порядка 30Кб), которые к тому же могут повторяться по различных направлениям, может быть очень удобно объединить их все в один файл, который загружать после отображения страницы на экране.

Описанная техника (кроссбраузерный data:URL + динамическая загрузка файлов стилей) позволяет добиться всех преимуществ технологии CSS Sprites, не затягивая загрузку страницы. При этом обладает очевидными плюсами: не нужно лепить все картинки в один файл, можно работать с каждой совершенно отдельно, что позволяет добиться большей семантичности кода и большего удобства использования сайтов. к тому же это несколько сократит CSS-код за счет уничтожения необходимости использовать background-position .

Я пытаюсь исключить 2 файла CSS, которые блокируют рендеринг на моем сайте, - они появляются в Google Page Speed ​​Insights. Я придерживался разных методов, ни один из которых не был успешным. Но недавно я нашел сообщение о Thinking Async и когда я применил этот код: он устранил проблему.

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

4 ответов

Уловкой запуска асинхронной загрузки стилей является использование элемента и установка недопустимого значения для атрибута media (я использую media = "none", но любое значение будет делать). Когда медиа-запрос оценивается как false, браузер все равно будет загружать таблицу стилей, но он не будет ждать, пока контент будет доступен до отображения страницы.

После того, как таблица стилей закончила загрузку, атрибут media должен быть установлен на допустимое значение, поэтому правила стиля будут применены к документу. Событие onload используется для переключения свойства media на все:

Этот метод загрузки CSS будет доставлять полезный контент посетителям намного быстрее, чем стандартный подход. Критический CSS все еще может быть использован с обычным блокирующим подходом (или вы можете встроить его для максимальной производительности), а некритические стили могут быть постепенно загружены и применены позже в процессе синтаксического анализа/рендеринга.

Этот метод использует JavaScript, но вы можете обслуживать не-JavaScript-браузеры, обертывая эквивалентные блокирующие элементы в элементе :

Вы можете увидеть операцию в www.itcha.edu.sv

вы можете попробовать получить его несколькими способами:

1. Использование media="bogus" и a на ноге

2. Включение DOM по-старому

(function(){ var bsa = document.createElement("script"); bsa.type = "text/javascript"; bsa.async = true; bsa.src = "https://s3.buysellads.com/ac/bsa.js"; (document.getElementsByTagName("head")||document.getElementsByTagName("body")).appendChild(bsa); })();

3.если вы можете попробовать плагины, которые вы могли бы попробовать loadCSS

// include loadCSS here... function loadCSS(href, before, media){ ... } // load a file loadCSS("path/to/mystylesheet.css");

Будущее представляется preload keyword для link элементов.

Версия синхронизации

Версия Async

К сожалению...

Известные браузеры, которые еще не поддерживают эту функцию включают Edge и iOS Safari.

Однако...

loadCSS представляется потенциальным решением, которое позволяет вам использовать preload сегодня (с резервными копиями).

С ростом скорости интернет соединения и увеличении мощности не только десктопных, но и мобильных устройств веб страницы стают более "тяжелыми". Количество и размер подключаемых файлов растет: JavaScript файлы, css файлы, изображения, виджеты сторонних сайтов, iframe. На данный момент специфика работы браузеров такая, что при загрузке js файла блокируется отривсовка до того момента, пока скрипт не выполниться. Современные браузеры в фоновом режиме будут парсить документ и скачивать скрипты и стили, но отрисовка будет заблокирована. Сравнение сетевых параметров для различных браузеров можно посмотреть на browserscope.org . Мы не можем устранить блокировку полностью, но можем оптимизировать серверную и клиентскую часть приложения, что бы блокировка отрисовки занимала наименьший промежуток времени.

Решения для серверной части:
- Уменьшить размер передаваемых файлов
- Использовать CDN
- Вынести статические файлы на отдельный домен или под домен, таким образом увеличить количество одновременных соединений браузера.
- Включить сжатие передаваемых файлов(gzip)

Решения для клиентской части:
- Уменьшить количество запросов.
- Кэшировать файлы на стороне клиента с помощью заголовков Expires и Etags.
- Использовать общедоступные CDN(Google CDN, Yandex CDN). Таким образом, существует вероятность, что файл с общедоступного CDN уже будет храниться в кеше браузера.

Одним из способов оптимизации скорости загрузки сайта является асинхронная загрузка файлов, которая не блокирует отрисовку.

Скрипт асинхронной загрузки JavaScript:

(function() { var s = document.createElement("script"); s.type = "text/javascript"; s.async = true; s.src = "URL файла"; document.getElementsByTagName("head").appendChild(script); })();

Если JavaScript нужно выполнить после загрузки всей страницы, включая содержание, изображения, стилевые файлы и внешние скрипты, то к загрузчику нужно добавить отслеживания события onload.

If (window.addEventListener) { window.addEventListener("load", async_load, false); } else if (window.attachEvent) { window.attachEvent("onload", async_load); }

Скрипт асинхронной загрузки JavaScript с учетом события onload (function() { function async_load(){ var s = document.createElement("script"); s.type = "text/javascript"; s.async = true; s.src = "URL файла"; document.getElementsByTagName("head").appendChild(script); } if (window.addEventListener) { window.addEventListener("load", async_load, false); } else if (window.attachEvent) { window.attachEvent("onload", async_load); } })();

Но это единичный случай, когда требуется загрузка одного файла. Часто на практике подключается множество файлов.

Скрипт асинхронной загрузки множества подключаемых JavaScript файлов (function() { function async_load(){ [ "URL_файла_1.js", "URL_файла_2.js", "URL_файла_3.js" ].forEach(function(src) { var s = document.createElement("script"); s.type = "text/javascript"; s.async = true; s.src = src; document.getElementsByTagName("head").appendChild(script); }); } if (window.addEventListener) { window.addEventListener("load", async_load, false); } else if (window.attachEvent) { window.attachEvent("onload", async_load); } })();

Но в такой реализации есть минус - скрипты будут загружаться в произвольном порядке и соответсвенно выполнятся они будут произвольно во времени. Данный скрипт асинхронной загрузки идеально подходит, если выполнение JavaScript файлов не зависят один от другого и не зависит от DOM. В обратном случае его использование может привести к ошибкам на странице или непредвиденному результату выполнения. Для последовательного выполнения, но асинхронной загрузки, нужно указать async=false, тогда файлы будут скачиваться в произвольном порядке, но выполняться по очереди.

HTML 5. Асинхронная загрузка JavaScript

Стандарт HTML 5 поддерживает асинхронную загрузку JavaScript. Это можно сделать путем добавления ключевого слова async или defer. Например:

Скрипт, который подключен с атрибутом defer выполнится не нарушая порядок выполнения по отношению к остальным скриптам и его выполнение произойдет после полной загрузки и парсинга страницы, но перед тем, как вызовется DOMContentLoaded.

Скрипт, который подключен с атрибутом async выполнится при первой возможности после полной загрузки, но при этом не ожидает окончания парсинга документа и до загрузки объекта window. Браузеры не гарантируют выполнение скриптов в том же порядке в котором они подключены.

Библиотеки для асинхронной загрузки JavaScript

RequireJS - модуль загрузки JavaScript. Оптимизирован под браузеры, но он может использоваться в других средах, таких как Node, Rhino.

Require(["script"], function(script) { console.log("start after load script.js"); });

extsrc.js - библиотека, которая запускает скрипты на выполнение после того, как страница загрузится и отобразится пользователю. Работает корректно с document.write.

yepnope.js - позволяет совершать асинхронную загрузку JavaScript и CSS файлов.

Yepnope([ "script.js", "style.css" ]);

Простой способ загрузки JavaScript скриптов

Оказывается, что на практике добиться оптимальной кросс браузерной загрузки JavaScript скриптов, которые не блокируют отображение сложно, а порой невозможно. Наиболее оптимальный способом является добавление в конец документа перед закрывающимся тегом body. Из за ограничения разных браузеров и самого HTML такой вариант загрузки, который не блокирует отображение, можно считать наиболее простой.

В одном из недавних постов я рассказал об асинхронной загрузке JavaScript. Сегодня речь пойдет снова об асинхронной загрузке, но асинхронно грузить будем CSS. Потребность в таком методе загрузки стилевых файлов диктуется развитием Интернета.

В последнее время владельцы сайтов жестко усвоили, что CSS подключается в начале кода html в теге head, а весь JavaScript код по возможности подключается как можно ниже (идеально перед закрытием тега body). Целью такого поведения является показ сайта по мере загрузки html. Т.е. браузер сначала загружает все содержимое CSS, и, зная описания всех классов, отрисовывает страницу по мере загрузки html. При этом пользователь, как бы сразу, видит появляющийся контент в красивом виде. А JavaScript добавляется в самом конце, когда пользователь уже знакомиться с содержанием страницы.

Долгое время такой подход отлично работал. Но… Новый тренд - мобильность. Чаще всего мобильные приложения имеют сравнительно небольшую скорость, а CSS имеет тенденцию к росту. Поэтому время загрузки CSS для мобильных пользователей может оказаться критичным. Кому хочется смотреть 20-30 секунд на пустой экран?

Поэтому возникает соблазн: А как бы подгружать CSS код асинхронно? Сразу оговоримся, какой-то минимальный CSS код все равно нужно подгрузить в теге head. Вы спросите почему? Очень просто, без задания этого минимума пользователь увидит html без стилей, в котором ему будет достаточно тяжело разобраться.

К «минимальному набору» я бы отнес общий layout (формирующий форму) и минимальные стили для заголовков и текста. А вот все дополнительные украшательства и излишества - после загрузки основного контент. В этом случае пользователь получает возможность ознакомиться с текстом документа уже до полной загрузки JavaScript и CSS, которые могут занимать довольно большой объем.

Я покажу, как реализовать такую асинхронную загрузку при помощи jQuery.

Чтобы наш CSS начал загружаться асинхронно - нужный файл требуется подключать с использованием jQuery. Например, таким образом:

JQuery("head").append("");

Естественно ожидать, что данный код будет выполнен после основного тела документа, а в идеале после загрузки всего html. Поэтому загружать будем по событию ready в jQuery примерно так:

JQuery (document).ready(function() { jQuery("head").append(""); });

При таком подключении CSS для быстрой загрузки html никаких преград не будет. В целом же структуру html страницы можно представить примерно так:

… ; … … Основное содержание страницы... jQuery (document).ready(function() { jQuery("head").append(""); });

Такой подход благотворно скажется на ваших посетителях. На мой взгляд, единственным недостатком такого подхода является - подключение стилей через JavaScript. Нет JavaScript - нет стилей. Пусть доля браузеров с отключенным JavaScript мала, но пользователям все равно будет не очень приятно. Поэтому перед применение данного метода, стоит взвесить все аргументы за и против.

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