Как сделать плагин jQuery загружаемым с помощью requirejs

88

Я работаю с requirejs + jquery, и мне было интересно, есть ли разумный способ заставить плагин jQuery хорошо работать с require.

Например, я использую jQuery-cookie. Если я правильно понял, я могу создать файл с именем jquery-cookie.js и внутри сделать

define(["jquery"], // Require jquery
       function($){
// Put here the plugin code. 
// No need to return anything as we are augmenting the jQuery object
});
requirejs.config( {
    "shim": {
        "jquery-cookie"  : ["jquery"]
    }
} );

Мне было интересно, могу ли я делать такие вещи, как jQuery, а это примерно так:

if ( typeof define === "function" && define.amd && define.amd.jQuery ) {
    define( "jquery", [], function () { return jQuery; } );
}

или если это единственный способ сделать плагины jQuery совместимыми с requirejs или любыми amd

Никола Пелучетти
источник

Ответы:

67

Вам нужно только сделать ЛИБО

define(["jquery"], // Require jquery
       function($){
// Put here the plugin code. 
// No need to return anything as we are augmenting the jQuery object
});

в конце jquery-cookie.js ИЛИ

requirejs.config( {
    "shim": {
        "jquery-cookie"  : ["jquery"]
    }
} );

в любом месте, прежде чем вы включите jquery-cookie (например, туда, куда указывает основные данные).

Последний опубликованный вами блок кода хорош для таких вещей, как jQuery, которые распространяются и могут находиться или не находиться в среде AMD. В идеале каждый плагин jQuery уже должен иметь такую ​​настройку.

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

Ганс
источник
1
Если я не выполняю и определение, и прокладку, все не работает, я получаю сообщение об ошибке $ .cookie не является функцией,
Никола Пелучетти,
По моему опыту, недостаточно ничего не вернуть из определяющей функции, requirejs не распознает, что модуль загружен. Это можно разбудить с помощью shim: {plugins: {sizes: ['jquery'], exports: 'plugins'}
honzajde
Обратите внимание, что скрипт плагина jQuery действительно должен запускаться. Я не эксперт, но я нашел простое решение, при котором у вас есть один require(['plugin1', 'plugin2']);и т. Д. Обратный вызов не передается, поэтому ничего не будет выполняться, кроме самих сценариев плагина. Это означает, что затем они будут добавлены, jQuery.fnпоэтому везде, где вы можете просто указать jquery в качестве зависимости, они будут включены. Как я уже сказал, я новичок в этом, и может быть лучший подход (например, просто использование scriptтега), но это действительно работает.
Джошуа Бамбрик
3
Джош: Вы делаете ставку на то, что все загрузится в правильном порядке. Некоторые пользователи на вашем сайте, вероятно, видят неисправный материал. Проблема не столько в том, что плагин загружается, а в том, когда плагин загружается и что еще выполняется в это время. Основная причина использования require - обеспечить разумный порядок операций, основанный на зависимостях, а не на предположениях.
Hans
104

Есть некоторые предостережения при использовании конфигурации прокладки в RequireJS, указанные на http://requirejs.org/docs/api.html#config-shim. . А именно: «Не смешивайте загрузку CDN с конфигурацией прокладки в сборке», когда вы используете оптимизатор.

Я искал способ использовать один и тот же код плагина jQuery на сайтах как с RequireJS, так и без него. Я нашел этот фрагмент для плагинов jQuery по адресу https://github.com/umdjs/umd/blob/master/jqueryPlugin.js . Вы оборачиваете свой плагин этим кодом, и он в любом случае будет работать правильно.

(function (factory) {
if (typeof define === 'function' && define.amd) {
    // AMD. Register as an anonymous module depending on jQuery.
    define(['jquery'], factory);
} else {
    // No AMD. Register plugin with global jQuery object.
    factory(jQuery);
}
}(function ($) {

    $.fn.yourjQueryPlugin = function () {
        // Put your plugin code here
    };  

}));

Кредит идет на jrburke; как и многие другие javascript, он функционирует внутри функций, воздействуя на другие функции. Но я думаю, что распаковал то, что он делает.

Аргумент функции factoryв первой строке сам по себе является функцией, которая вызывается для определения плагина для $аргумента. Когда AMD-совместимый загрузчик отсутствует, он вызывается непосредственно для определения подключаемого модуля в глобальном jQueryобъекте. Это похоже на распространенную идиому определения плагинов:

function($)
{
  $.fn.yourjQueryPlugin = function() {
    // Plugin code here
  };
}(jQuery);

Если есть загрузчик модуля, то factoryон регистрируется как обратный вызов для загрузчика, вызываемого после загрузки jQuery. Загруженная копия jQuery является аргументом. Это эквивалентно

define(['jquery'], function($) {
  $.fn.yourjQueryPlugin = function() {
     // Plugin code here
  };
})
Карл Раймонд
источник
3
Мне нравится этот ответ, потому что, хотя вопрос был о плагине jQuery, он работает для любого модуля или библиотеки, а не только для jQuery. Мне потребовалась минута, чтобы осмыслить ваш код, но как только я это сделал, это стало совершенно логичным.
Адам Таттл
1
Это определенно непонятный javascript. Я добавил несколько пояснений о том, как это работает.
Карл Рэймонд
Есть какие-нибудь советы, как это сделать и создать плагин, работающий с jQuery или Zepto? Вы можете легко заменить код, не относящийся к AMD, наfactory(jQuery || Zepto); , , но я не знаю, как бы вы сделали часть AMD. Я думаю, вам нужно установить jQuery "путь" к zepto ?? paths: { jquery: 'vendor/zepto/zepto.min' }
Райан Уил
вау, я давно хотел понять этот фрагмент кода. Большое спасибо, разве shimэто не так? Думаю, нет ... потому что вы сказали, что вручную кодируете, как указано выше.
Евгений
Совет для идиотов вроде меня: где написано $.fn.jqueryPlugin измените jqueryPluginназвание плагина во фрагменте !!
Мэтт Лейси
2

Так же, как к сведению, некоторые плагины jquery уже используют amd / require, поэтому вам не нужно ничего объявлять в прокладке. На самом деле в некоторых случаях это может вызвать у вас проблемы.

Если вы посмотрите в jquery cookie JS, вы увидите определение вызовов и require (["jquery"]).

и в jquery.js вы увидите вызов для определения ("jquery", [], function () ...

TPEACHES
источник