Сайт о телевидении

Сайт о телевидении

» » Загрузка JavaScript(без блокировки отрисовки документа, асинхронная загрузка)

Загрузка JavaScript(без блокировки отрисовки документа, асинхронная загрузка)

В одном из недавних постов я рассказал об асинхронной загрузке 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, т.к. в этом случае пользователь очень быстро получает часть документа для ознакомления.

Что будет заметно, если эта конструкция окажется внутри . Из описания в почтовой рассылке разработчиков 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 и заодно получить более быструю отрисовку. Пользуйтесь на здоровье!

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

Таблицы связанных стилей

Самый мощный и удобный способ определения стилей и правил для сайта. Стили хранятся в отдельном файле, который может быть использован для любых веб-страниц. Для подключения таблицы связанных стилей используется тег в заголовке страницы (пример 1).

Пример 1. Подключение таблицы связанных стилей

Стили Hello, world!

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

Достоинства данного способа
  • Используется один файл со стилем для любого количества веб-страниц, также возможно его применять на других сайтах.
  • Можно изменять таблицу стилей без модификации веб-страниц.
  • При изменении стиля в одном единственном файле, стиль автоматически применяется ко всем страницам, где есть на него ссылка. Несомненно, удобно. Указываем размер шрифта в одном только месте, и он изменяется на всех сто или больше веб-страницах нашего сайта.
  • Файл со стилем при первой загрузке помещается в кэш на локальном компьютере, отдельно от веб-страниц, поэтому загрузка сайта происходит быстрее.
  • Таблицы глобальных стилей

    Стиль определяется в самом документе и обычно располагается в заголовке веб-страницы. По своей гибкости и возможностям этот способ использования стиля уступает предыдущему, но также позволяет размещать все стили в одном месте. В данном случае, прямо в теле документа. Определение стиля задается тегом (пример 2).

    Пример 2. Использование таблицы глобальных стилей

    Стили H1 { font-size: 120%; /* Размер шрифта */ font-family: Verdana, Arial, Helvetica, sans-serif; /* Семейство шрифта */ color: #336; /* Цвет текста */ } Hello, world!

    В данном примере показано изменение стиля заголовка . На веб-странице теперь достаточно указать только этот тег и стили будут добавлены к нему автоматически.

    Внутренние стили

    Внутренний стиль являются по существу расширением для одиночного тега используемого на веб-странице. Для определения стиля используется атрибут style , а его значения указываются с помощью языка таблицы стилей (пример 3)..

    Пример 3. Использование внутренних стилей

    Стили Hello, world!

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

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

    Пример 4. Сочетание разных методов подключения стилей

    Стили H1 { font-size: 120%; font-family: Arial, Helvetica, sans-serif; color: green; } Hello, world! Hello, world!

    В приведенном примере первый заголовок задается красным цветом размером 36 пикселов, а следующий — зеленым цветом и другим шрифтом.

    Несмотря на всё большее распространение широкополосного доступа к Интернету, проблемы скорости загрузки HTML-страниц всё ещё не безразличны многим пользователям Сети, особенно на просторах бывшего Союза. CSS (Cascading Style Sheets) может помочь в этом деле, сэкономив нам время и трафик.

    1. Избегайте использования таблиц для разметки страницы

    Вот шесть причин, по которым лучше использовать CSS, а не таблицы, для разметки страниц:

    • Браузеры анализируют таблицы дважды: первый раз для того, чтобы оценить структуру таблицы, и второй - для определения их содержимого.
    • Таблицы отображаются сразу полностью, а не по мере загрузки.
    • Таблицы заставляют использовать прозрачные картинки для определения ширины колонок и т.п.
    • CSS требует гораздо меньше кода, чем перегруженные таблицы.
    • Весь CSS-код может быть вынесен во внешний файл, который будет грузиться всего один раз и храниться в кэше браузера.
    • При помощи CSS можно контролировать очерёдность загрузки элементов страницы.
    2. Не используйте картинки для отображения текста

    Большинство кнопок и надписей можно отобразить при помощи CSS. Взгляните на пример:

    a:link.example, a:visited.example, a:active.example { color:#fff; background:#f90; font-size:1.2em; font-weight:bold; text-decoration:none; padding:0.2em; border:4px #00f outset } a:hover.example { color:#fff; background:#fa1; font-size:1.2em; font-weight:bold; text-decoration:none; padding:0.2em; border:4px #00f inset

    Этот CSS определяет простую кнопку, которая меняет свой вид при наведении курсора. Таким образом можно создавать и более сложные объекты.

    3. Загрузка картинок через CSS

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

    И соответствующий CSS:

    Pretty-image { background: url(filename.gif); width: 200px; height: 100px }

    Сначала это может показаться бессмысленным, но на самом деле такой способ может намного ускорить загрузку страницы. В этом случае браузер начнёт загружать картинку только после того, как будет выведен весь текст, а не одновременно. Таким образом пользователи могут работать со страницей, в кто время как изображение ещё будет подгружаться.

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

    4. Использование контекстных стилей

    Данный код неэффективен:

    This is a sentence

    This is another sentence

    This is yet another sentence

    This is one more sentence

    .text { color: #03c; font-size:2em }

    Вместо того, чтобы присваивать класс каждому параграфу, их можно сгруппировать в одном элементе DIV с тем же классом:

    This is a sentence

    This is another sentence

    This is yet another sentence

    This is one more sentence

    .text p { color: #03c; font-size:2em }

    Этот код указывает браузеру, что каждый параграф внутри элемента с классом text будет иметь цвет #03c и размер шрифта в 2em.

    Вы могли заметить, что цвет здесь указан всего тремя символами, а не шестью. В данном случае #03c является сокращённым написанием значения цвета #0033cc.

    5. Использование сокращений

    Шрифт

    Лучше написать:

    font: 1em/1.5em bold italic serif

    font-size: 1em; line-height: 1.5em; font-weight: bold; font-style: italic; font-family: serif

    Границы

    border: 1px black solid

    border-width: 1px; border-color: black; border-style: solid

    Фон

    background: #fff url(image.gif) no-repeat top left

    background-color: #fff; background-image: url(image.gif); background-repeat: no-repeat; background-position: top left;

    Отступы и границы

    Используйте:

    margin: 2px 1px 3px 4px; (верх, вправо, низ, влево)

    Аналогично:

    margin: 5em 1em 3em; (верх, влево и вправо, низ)

    margin: 5% 1%; (верх и низ, влево и вправо)

    Эти правила применяются к атрибутам margin, border и padding.

    6. Минимизирование пробелов, переводов строк и комментариев

    Каждый символ - буква или пробел - занимают один байт. Каждый лишний символ только увеличивает размер страниц. Поэтому старайтесь поменьше нажимать Enter и Tab в процессе вёрстки. Кроме того, не забывайте объединять CSS-стили.

    7. Используйте относительные ссылки

    Абсолютные ссылки занимают намного больше места, чем относительные. А кроме того, создаёт дополнительную нагрузку на браузер, что более важно. Пример абсолютной ссылки: . Гораздо правильней будет написать < a href=»filename.htm»> . Но что если нужный файл находится в другом каталоге? Вот несколько примеров, которые помогут вам разобраться в этом вопросе:

    8. Не увлекайтесь применением тегов META

    Большинство тегов META соврешенно ненужные. Если интересно, можно взглянуть на все существующие варианты . Самые важные теги (keywords и description) используются для оптимизации поисковых машин. При использовании атрибута content в теге META старайтесь не превышать размера в 200 символов. Большие описания и множество ключевых слов могут быть восприняты поисковыми машинами как спам.

    9. Выносите CSS и JavaScript в отдельные файлы

    Все это знают, но не всегда пользуются. Вот так выглядит вызов CSS из внешнего файла:

    И соответственно JavaScript:

    Любой внешний файл грузится всего один раз и затем сохраняется в локальном кэше. Ограничений на количество «подключаемых» внешних файлов не существует.

    10. Ставьте / (слэш) в конце ссылок на каталоги

    Необходимо писать так.

    Выход есть: поместить явавские строки в конец html документа (следовательно их загрузка будет происходить после прорисовки всей страницы) и только после этого содержимое блоков будет отображено в нужных местах. Это называется . Все серьезные проекты сегодня стараются как можно быстрее перейти на новую технологию загрузки. Тем более, что это абсолютно легко.

    Есть несколько подходов. Начну по порядку.

    script src= type= "text/javascript" >

    Асинхронная загрузка скрипта HTML5

    Стандарт HTML5 поддерживает возможность асинхронной загрузки скриптов, что может значительно ускорить общее время получения страницы. Просто добавьте async или defer .

    < script async src= "http://www.site.ru/script.js" type= "text/javascript" >

    < script defer src= "http://www.site.ru/script.js" type= "text/javascript" >

    Чем же отличаются атрибуты async и defer

    В обоих случаях мы получаем асинхронную загрузку скриптов. Разница заключается только в моменте, когда скрипт начинает выполнятся. Скрипт с атрибутом async выполнится при первой же возможности после его полной загрузки, но до загрузки объекта window. В случае использования атрибута defer – скрипт не нарушит порядок своего выполнения по отношению к остальным скриптам и его выполнение произойдет после полной загрузки и парсинга страницы, но до события DOMContentLoaded объекта document.

    К сожалению, этот механизм на сегодняшний день не работает во всех браузерах (особенно это касается IE). Также не будет работать, если в файле script.js есть строки document.write .

    Асинхронная загрузка javascript скриптом от Google

    Как известно всем мастерам, Google уделяет особое внимание скорости загрузки сайтов, и понижает медленные в поисковой выдаче. Что бы помочь, Гугл разработал специальный скрипт, при помощи которого можно сделать асинхронную загрузку javascript.

    Чтобы использовать, просто заменяем

    на

    И подключаем файл скрипта extsrc.js

    Получится так:

    < script src= "http://extsrcjs.googlecode.com/svn/trunk/extsrc.js" > < script extsrc= "...." >

    К сожалению, этот способ тоже не подойдет к файлам с document.write

    Лучшая рабочая асинхронная загрузка javascript

    Универсальный способ для всех браузеров. Работает даже с document.write

    В том месте страницы, где нужно реально отобразить наш элемент создаем пустой div блок:

    < div id= "script_block" class = "script_block" >

    В самом конце страницы перед вставляем скрипт для асинхронной загрузки файлов:

    < div id= "script_ad" class = "script_ad" style= "display:none;" > Здесь любой файл или скрипт, который нужно загрузить. < script type= "text/javascript" > // переместить его в реальную позицию отображения document. getElementById("script_block" ) . appendChild(document. getElementById("script_ad" ) ) ; // показать document. getElementById("script_ad" ) . style. display = "block" ;

    В самых старых версиях IE (6 и ниже) асинхронная загрузка к сожалению не работает, но таких пользователей уже практически нет. Все остальные браузеры и сервисы успешно пользуются современной ускоренной загрузкой web-страниц.