Официально выпущенный Алексом Секстоном и Ральфом Хольцманном в конце февраля 2011 года, загрузчик ресурсов yepnope.js поддерживает асинхронную, условную загрузку и предварительную загрузку ресурсов JavaScript и CSS. Это делает управление зависимым условным кодом быстрым.
Каждые несколько недель мы пересматриваем некоторые из любимых постов нашего читателя на протяжении всей истории сайта. Этот учебник был впервые опубликован в марте 2011 года.
Этот изящный загрузчик ресурсов, размер которого составляет всего 1,6 КБ, упакован с помощью Modernizer и отлично подходит для загрузки полизаполнений, предварительной загрузки или «заполнения» кэша пользователей или в качестве простого асинхронного загрузчика / фильтра ресурсов!
Для тех из вас, кто не знаком с полифиллами, они, по сути, являются плагинами или оболочками, которые позволяют использовать новые или будущие технологии в старых браузерах, например, базы данных Web SQL, преобразования CSS3 и т. Д.
Yepnope теперь также поддерживает ряд префиксов и фильтров, которые при добавлении к URL-адресу ресурса добавляют еще один уровень тонкой настройки или настройки к его основной функциональности. Как будто это не было уже хорошо, yepnope также предоставляет вам механизм для определения ваших собственных префиксов и фильтров. Давайте посмотрим, что может сделать yepnope.js!
Фон — асинхронная загрузка скриптов
Прежде чем мы углубимся в yepnope и его возможности, важно немного понять, как работает асинхронная загрузка скриптов, почему это полезно и как это отличается от загрузки скриптов vanilla.
Асинхронные загрузчики удаляют присущий скрипту характер блокировки.
Как правило, файлы JavaScript, загруженные с <script>
, блокируют загрузку ресурсов, а также отображение элементов на веб-странице. Таким образом, несмотря на то, что большинство современных браузеров, как правило, поддерживают параллельную загрузку файлов JavaScript, загрузка изображений и рендеринг страниц все еще должны ждать завершения загрузки сценариев. В свою очередь, количество времени, которое пользователь должен ждать для отображения страницы, увеличивается.
Вот тут и начинают играть асинхронные загрузчики. Используя один из нескольких различных методов загрузки, они удаляют присущий скрипту характер блокировки, который позволяет параллельно загружать как скрипты Java, так и ресурсы, не мешая при этом отображению страниц. Во многих случаях это может сократить — иногда радикально — время загрузки страницы.
Большинство загрузчиков сохраняют порядок, в котором выполняются сценарии, обеспечивая обратный вызов, когда сценарий загружен и готов.
Асинхронная загрузка не обходится без предостережений. Когда сценарии загружаются традиционным способом, встроенный код не анализируется и не выполняется до тех пор, пока внешние сценарии не будут полностью загружены последовательно. Это не относится к асинхронной загрузке. Фактически, встроенные сценарии обычно анализируются / выполняются, пока сценарии все еще загружаются. Аналогичным образом браузер также загружает ресурсы и отображает страницу во время загрузки сценариев. Таким образом, мы можем прийти к ситуациям, когда встроенный код, который, возможно, зависит от загружаемого скрипта / библиотеки, выполняется до того, как его зависимость готова или до / после того, как сам DOM готов. Таким образом, большинство загрузчиков сохраняют порядок, в котором выполняются сценарии, обеспечивая обратный вызов, когда сценарий загружен и готов. Это позволяет нам запускать любой зависимый встроенный код в качестве обратного вызова, возможно, в оболочке, готовой к DOM, где это применимо.
Кроме того, при работе с небольшой или хорошо оптимизированной страницей DOM может быть на самом деле готов или даже загружен до завершения загрузки самих скриптов! Таким образом, если рассматриваемая страница не улучшается постепенно, так как она в значительной степени опирается на JavaScript для стилизации, возможно, имеется FOUC или флеш из не стилизованного контента. Точно так же пользователи могут даже испытать краткий FUBC или вспышку несоответствующего содержания. Важно помнить об этом всякий раз, когда вы используете загрузчик скриптов / ресурсов.
Шаг 1 — Тестовый объект yepnope
Тестовый объект yepnope
имеет семь основных свойств, любое из которых является необязательным. Этот объект включает реальный тест, ресурсы, которые будут загружены в результате теста, ресурсы, которые будут загружены независимо от теста, а также обратные вызовы. Вот взгляд на реквизиты тестового объекта yepnope:
-
тестовое задание:
Логическое значение, представляющее условие, которое мы хотим проверить.
-
Ага:
Строка или массив / объект строк, представляющих URL ресурсов для загрузки, если тест верен .
-
нет:
Строка или массив / объект строк, представляющих URL ресурсов для загрузки, если тест ложный .
-
загрузки:
Строка или массив / объект строк, представляющих URL ресурсов для загрузки независимо от результата теста.
-
и то и другое:
Строка или массив / объект строк, представляющих URL ресурсов для загрузки независимо от результата теста. Это, в основном, синтаксический сахар, так как его функция, как правило, такая же, как функция
load
. -
Перезвони:
Функция, которая будет вызываться для каждого ресурса при его последовательной загрузке.
-
завершения:
Функция, которая будет вызвана один раз, когда все ресурсы будут загружены.
Теперь, чтобы получить представление о синтаксисе, давайте рассмотрим простейшее использование yepnope: загрузка одного ресурса.
1
|
yepnope(‘resources/someScript.js’);
|
… или, возможно, загрузка массива ресурсов.
1
2
3
4
|
yepnope([
‘resources/someScript.js’,
‘resources/someStyleSheet.css’
]);
|
Как насчет литерала объекта, чтобы мы могли использовать именованные обратные вызовы позже?
1
2
3
4
|
yepnope({
‘someScript’ : ‘resources/someScript.js’,
‘someStyleSheet’ : ‘resources/someStyleSheet.css’
});
|
Помните, что эти ресурсы будут загружаться асинхронно по мере загрузки и рендеринга страницы.
Шаг 2 — Условия — Тестирование на черты будущего!
Итак, мы можем загружать ресурсы асинхронно! Это здорово, но что, если некоторым страницам не требуется определенный ресурс? Или что делать, если ресурс нужен только в конкретном браузере, который не поддерживает новейшие технологии?
Нет проблем! Это где основная цель Yepnope становится в центре внимания. Используя свойство test, мы можем условно загружать ресурсы в зависимости от необходимости. Например, предположим, что библиотека Modernizer загружена.
Для тех из вас, кто не знаком с Modernizer, это отличный набор тестов, используемый для обнаружения поддержки функций HTML5 и CSS3 в браузерах.
Modernizer добавляет соответствующие js flexbox no-canvas
элемент html
страниц, представляющий поддерживаемые и не поддерживаемые функции, например, « js flexbox no-canvas
» и т. Д. Кроме того, вы можете получить доступ к каждому из тестов Modernizer, которые возвращают логические значения по отдельности в вашем коде.
Итак, используя Modernizer, давайте hashchange
поддержку событий hashchange
а также поддержку истории сеансов!
Вот посмотрите на наш тест:
1
2
3
|
yepnope({
test : Modernizr.hashchange && Modernizr.history
});
|
Этот тест, конечно, вернет true
только если браузер поддерживает обе эти функции.
Шаг 3 — Загрузка ресурсов условно
С нашим набором условий теста мы теперь определим, какие ресурсы загружать, основываясь на результатах этого теста. Другими словами, если вам нужно загрузить определенный ресурс только в том случае, если в браузере отсутствует функция или если тест не пройден, вы можете просто определить этот ресурс в предложении nope
. И наоборот, вы можете загружать ресурсы при прохождении теста внутри предложения yep
.
Итак, предполагая, что браузер не поддерживает одну из этих двух функций, мы загрузим плагин jQuery Бена Алмана , который обеспечивает поддержку hashchange
и истории в старых браузерах, которые не поддерживают ни одну из этих функций.
Давайте загрузим плагин hashchange:
1
2
3
4
|
yepnope({
test : Modernizr.hashchange && Modernizr.history,
nope : ‘resources/jquery.ba-hashchange.js’
});
|
В приведенном выше примере мы не будем использовать свойство yep
как мы предоставляем шим только в случае необходимости.
Чтобы проиллюстрировать предложение yep, давайте проверим поддержку преобразования CSS3, а затем загрузим таблицу стилей для браузеров, которые поддерживают преобразования, и простую таблицу стилей для браузеров, которые этого не делают. Кроме того, мы загрузим плагин jQuery, который также имитирует преобразования CSS3.
Используя и да, и нет:
1
2
3
4
5
|
yepnope({
test : Modernizr.csstransforms,
yep : ‘resources/cssTransform.css’
nope : [‘resources/noTransform.css’, ‘jQuery.pseudoTransforms.js’]
});
|
Обратите внимание, что оба этих примера будут загружать все ресурсы асинхронно, так как остальная часть страницы загружается и отображается!
Шаг 4 — Загрузка ресурсов независимо от условий теста
Yepnope также предоставляет способ загрузки ресурсов независимо от результатов теста с помощью свойства load
. Функция load
всегда будет загружать любой ресурс, на который она подается, независимо от результата test
. Точно так же both
пропеллера, которые, по сути, являются просто синтаксическим сахаром, также загружают ресурсы независимо от результата теста или, более точно, на любом из результатов.
Загрузка по умолчанию:
1
2
3
4
5
|
yepnope({
test : Modernizr.hashchange && Modernizr.history,
nope : ‘resources/jquery.ba-hashchange.js’,
load : ‘resources/somethingWhichIsAlwaysLoaded.css’,
});
|
Загрузка при обоих условиях, синтаксический сахар:
1
2
3
4
5
|
yepnope({
test : Modernizr.hashchange && Modernizr.history,
nope : ‘resources/jquery.ba-hashchange.js’,
both : ‘resources/somethingWhichIsAlwaysLoaded.css’,
});
|
В обоих приведенных выше примерах ресурсы будут загружаться асинхронно, несмотря ни на что.
Шаг 5 — Обратные вызовы — Зависимый код после загрузки
Как упоминалось ранее, мы не можем писать встроенный код обычным способом, если этот код зависит от одного из загружаемых скриптов. Таким образом, мы будем использовать функцию обратного вызова yepnope, которая запускается один раз для каждого ресурса после завершения загрузки. Функция обратного вызова принимает три параметра, которым назначаются следующие:
-
URL
Эта строка представляет URL ресурса, который был загружен
-
результат
Логическое значение, представляющее статус загрузки.
-
ключ
Если используется массив или объект ресурсов, это будет представлять индекс или имя свойства файла, который был загружен
Давайте рассмотрим простой обратный вызов на примере плагина hashchange из предыдущего. Мы будем использовать метод привязки jQuery для привязки обработчика к событию hashchange window
:
Простой обратный вызов:
01
02
03
04
05
06
07
08
09
10
11
12
13
|
yepnope({
test : Modernizr.hashchange && Modernizr.history,
nope : ‘resources/jquery.ba-hashchange.js’,
callback : function(url, result, key){
$(function(){
$(window).bind(‘hashchange’, function(){
console.info(location.hash);
});
});
},
});
|
Независимо от того, в каком состоянии находится DOM, этот обратный вызов, который в данном конкретном случае находится в оболочке с готовым документом, сработает, как только будет загружен ресурс.
Допустим, однако, что мы загружаем более одного скрипта и что нам нужно запустить обратный вызов для каждого скрипта во время его загрузки. Указание кода, который нам нужно выполнить описанным выше способом, создаст избыточность, поскольку обратный вызов запускается при каждой загрузке ресурса. Однако Yepnope предоставляет отличный способ обработки обратных вызовов для каждого ресурса независимо от любых других обратных вызовов.
Используя литерал объекта для определения загружаемых нами ресурсов, мы можем ссылаться на каждый ключ ресурса в отдельности в рамках обратного вызова.
Давайте рассмотрим пример, в котором мы загружаем jQuery, а также плагин jQuery hashchange, который зависит от того, загружается ли сначала jQuery. Однако на этот раз мы будем использовать объектные литералы!
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
|
yepnope({
test : Modernizr.hashchange && Modernizr.history,
nope : {
‘jquery’ : ‘resources/jquery-1.5.1.min.js’,
‘hashch’ : ‘resources/jquery.ba-hashchange.js’
},
callback : {
‘jquery’ : function(url, result, key){
console.info(‘I will fire only when the jquery script is loaded’);
},
‘hashch’ : function(url, result, key){
console.info(‘I will fire only when the hashchange script is loaded’);
// This code will be added to jQuerys DOM ready call stack
$(function(){
$(window).bind(‘hashchange’, function(){
console.info(location.hash);
});
});
}
}
});
|
Используя приведенный выше пример в качестве справочного материала, вы можете упорядоченно реализовать собственные обратные вызовы для каждой загрузки ресурса.
Шаг 6 — Завершить — Когда все сказано и сделано!
Наконец, у нас есть complete
обратный вызов, который вызывается только один раз, после того как все ресурсы закончили загрузку. Так, например, если вы «загружаете» веб-приложение, и код, который вам нужно запустить, зависит от всех загружаемых файлов, а не указывает callback
для каждого ресурса, вы должны написать свой код в complete
обратный вызов, так что он запускается только один раз, после загрузки всех его зависимостей. В отличие от функции callback
, complete
не принимает никаких параметров и не имеет доступа к url
, result
или key
.
complete
обратный звонок:
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
|
yepnope({
test : Modernizr.hashchange && Modernizr.history,
nope : [
‘resources/jquery-1.5.1.min.js’,
‘resources/jquery.ba-hashchange.js’
],
complete : function(){
console.info(‘I will fire only once when both jquery and the hashchange script are loaded’);
// This code will be added to jQuerys DOM ready call stack
$(function(){
$(window).bind(‘hashchange’, function(){
console.info(location.hash);
});
});
}
});
|
Поэтому, по сути, complete
обратный вызов полезен для всего, что необходимо сделать после загрузки всех ресурсов.
Шаг 7 — Плагины Yepnope, префиксы и многое другое!
Yepnope также предоставляет нам еще одну изящную маленькую особенность: префиксы и фильтры! Префиксы по умолчанию, предоставляемые yepnope, которые всегда добавляются к началу URL ресурса, используются для определения файла как CSS, предварительной загрузки ресурса или ориентации на Internet Explorer или одну из его версий соответственно. Давайте посмотрим:
-
CSS!
Этот префикс используется для того, чтобы заставить yepnope рассматривать ресурс как таблицу стилей. По умолчанию yepnope рассматривает файлы .css как таблицы стилей, а все остальное — как файл JavaScript. Так что, если вы обслуживаете CSS динамически, этот префикс заставит yepnope рассматривать этот ресурс как таблицу стилей.
1yepnope(‘css!styles.php?colorscheme=blue’); -
преднагрузки!
Этот префикс позволяет загружать / кэшировать ресурс, не выполняя его.
1yepnope(‘preload!userInterface.js’); -
то есть!
Могут возникнуть ситуации, когда вам нужно загружать определенные ресурсы, только если вы работаете с Internet Explorer или определенной версией Internet Explorer. Таким образом, префиксы
ie
помогают вам ориентировать загрузку ресурсов наie
или конкретные его версии. Вот список поддерживаемых префиксовie
гдеgt
обозначает «версии больше чем», аlt
обозначает «версии меньше чем».- Internet Explorer:
ie!
- Internet Explorer по номеру версии:
ie5!
,ie6!
,ie7!
,ie8!
,ie9!
- Версии Internet Explorer больше чем:
iegt5!
,iegt6!
,iegt7!
,iegt8!
- Версии Internet Explorer меньше чем:
ielt7!
,ielt8!
,ielt9!
Все эти фильтры являются цепочечными и служат своего рода оператором
OR
в том случае, если один из них оценивается какtrue
ресурс будет загружен. Итак, если нам нужно настроить таргетинг на ie7 и ie8, мы просто добавим соответствующие фильтры к URL-адресу ресурса следующим образом:1yepnope(‘ie7!ie8!userInterface.js’); - Internet Explorer:
Создание собственных фильтров!
Если вам когда-либо понадобится, yepnope
также предоставляет средства для создания ваших собственных фильтров и префиксов с помощью методов addFilter
и addPrefix
. Любому созданному вами фильтру или префиксу передается resourceObject
содержащий ряд полезных реквизитов. Помните, однако, чтобы вернуть resourceObject
поскольку yepnope требует, чтобы вы это сделали. Вот посмотрите на resourceObject
:
-
URL:
URL загружаемого ресурса.
-
префиксы
Массив примененных префиксов.
-
autoCallback
Обратный вызов, который запускается после загрузки каждого скрипта, отдельно от других.
-
поехес
Логическое значение, которое вызывает предварительную загрузку без выполнения.
-
вместо
Расширенная функция, которая принимает те же параметры, что и загрузчик.
-
forceJS
Логическое значение, которое заставляет ресурс обрабатываться как javascript.
-
forceCSS
Логическое значение, которое заставляет ресурс обрабатываться как таблица стилей.
-
байпас
Логическое значение, определяющее, загружать или нет текущий ресурс.
Допустим, например, что вам нужна возможность переключать загрузку ресурсов между вашим CDN и веб-сервером на лету. Можем ли мы сделать это, хотя !? Ага! Давайте создадим два префикса, один для загрузки с CDN, а другой для загрузки с вашего веб-сервера.
01
02
03
04
05
06
07
08
09
10
11
12
13
|
yepnope.addPrefix(‘local’, function(resourceObj) {
resourceObj.url = ‘http://mySite/resources/’ + resourceObj.url;
return resourceObj;
});
yepnope.addPrefix(‘amazon’, function(resourceObj) {
resourceObj.url = ‘http://pseudoRepository.s3.amazonaws.com/’ + resourceObj.url;
return resourceObj;
});
|
Используя эти префиксы, мы теперь можем легко переключаться между нашим CDN и веб-сервером!
1
2
3
4
|
yepnope([
‘local!css/typography.css’,
‘amazon!defaultStyle.css’
]);
|
Шаг 8 — Несколько предостережений
Таким образом, сохраняя очень малую площадь, условный загрузчик yepnope обладает множеством полезных функций! Есть, однако, несколько вещей, которые вы должны знать, прежде чем использовать его.
-
Нет
document.write
Как и в случае любого асинхронного загрузчика, вы не можете использовать
document.write
. -
Internet Explorer менее 9 и выполнение обратного вызова
Версии Internet Explorer менее девяти не гарантируют, что обратные вызовы запускаются сразу после запуска соответствующего сценария.
-
Будьте осторожны с DOM
Ваш скрипт может быть загружен и выполнен до того, как DOM будет готов. Итак, если вы манипулируете DOM, желательно использовать готовую оболочку DOM.
-
Вы все еще должны объединить, где вы можете
То, что вы используете асинхронный загрузчик, не означает, что вам не следует объединять свои ресурсы там, где это возможно.
-
Ограничения асинхронной загрузки Internet Explorer
Более старые версии Internet Explorer могут загружать только два ресурса из одного домена одновременно, тогда как другие версии могут загружать до шести. Итак, если вы загружаете несколько файлов, рассмотрите возможность использования поддоменов или CDN.
Вывод — мысли на yepnope.js
В общем, я нашел yepnope отличной утилитой! Он не только поддерживает асинхронную загрузку как скриптов, так и таблиц стилей, но также предоставляет хороший, чистый способ условной загрузки полифайлов HTML5 и CSS3. Механизм обратного вызова хорошо продуман, а возможность добавлять свои собственные префиксы и фильтры просто великолепна! С точки зрения производительности я обнаружил, что yepnope несколько схожи с другими загрузчиками, такими как LABjs Getify Solutions и require.js Джеймса Бёрка . Очевидно, что каждый загрузчик индивидуален и подходит для разных нужд, но если вы еще этого не сделали, я призываю вас попробовать yepnope.js !