Wrapper, позволяющий модулю работать с тегами AMD/CommonJs или script? - программирование
Подтвердить что ты не робот

Wrapper, позволяющий модулю работать с тегами AMD/CommonJs или script?

Я только что сделал попытку обернуть один из наших модулей, который должен быть включен через тег <script> в некотором шаблоне, чтобы позволить дополнительную загрузку AMD с requirejs.

Это было довольно болезненно, и лучшее, что я мог придумать, было:

(function(){
var exports, jQuery;
if (typeof window.define === 'function' && typeof window.requirejs === 'function') {
    exports     = {};
    define(['jquery'], function (jq) {
        jQuery = jq;
        return thisModule();
    });
} else {
    exports     = window;
    jQuery      = window.jQuery;
    thisModule();
}


function thisModule() {
}

})();

Обратите внимание, что это

  • МНОГО шаблона
  • Требуется, чтобы объявить зависимости в переменных (только jQuery в этом случае к счастью) AND amd
  • Требуется еще больше кода, если я хочу иметь поддержку CommonJs.

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

У кого-нибудь есть подсказки?

4b9b3361

Ответ 1

Что вы пытаетесь воссоздать тем, что уже существует, я сделал то же самое, придумав немного другое решение в fooobar.com/questions/327603/....

Чтобы сократить длинную историю, вам нужно знать имя "Универсальное определение модуля", а там находится GitHub, расположенная в https://github.com/umdjs/umd с множеством различных реализаций.

Ответ 2

Вы пытаетесь сделать это для внутреннего модуля или внешнего модуля?

Если вы не нуждаетесь в дополнительных модулях, возможно ли построить ваши модули, предполагающие AMD, а затем просто отстроить функцию define() где-нибудь еще в вашем коде, если это не так? Конечно, вам придется использовать именованные модули, но вам все равно придется это делать в любом случае...

Если ваши модули возвращают свой экспорт из функции define(), это было бы относительно просто, и ваша функция определения проксирования могла бы выглядеть примерно так:

//Whatever additional guards you want could be added, of course...
if (typeof(window.define) === undefined){
  window.define = function(name, deps, callback){
    window.myNamespace[name] = callback();
  };
}

По крайней мере, вам не нужно будет добавлять шаблон к каждому модулю...

Если у вас есть большая библиотека с большим количеством взаимозависимых подмодулей, вам, вероятно, просто придется совершить попытку использовать "Требовать весь путь" или нет, а затем использовать свой код обертки вокруг всей вашей библиотеки поддерживайте поддержку AMD, как JQuery и Knockout JS делают это.

Ответ 3

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

Несколько заметок и недостатков.

  • Вы должны заменить любые явные настройки объекта window объектом экспорта
  • Предполагается, что любая зависимость существует как свойство с аналогичным именем в объекте window (хотя оно также позволяет разместить это свойство там). В общем случае это достаточно безопасно, но вы можете легко взломать что-то вроде конфигурации путей requirejs.
  • На самом деле я не уверен, что вся концепция экспорта особенно необходима или, по крайней мере, не нужна во всех случаях.
(function () {
    var define, exports = {};
    if (window.define && window.define.amd) {
        define = window.define;
    } else {
        exports = window;
        define = function (name, dependencies, fn) {
            var deps = [];
            for (var i = 0; i < dependencies.length; i++)
                deps.push(window[dependencies[i]]);
            var module = fn.apply(undefined, deps);
            if (!window[name]) window[name] = module;
        };
    }

    define('mylib.interaction', ['jQuery', 'mylib.core', 'jQuery.UI'], function($, mylib) {
        return /*....blah...*/;
    })
})()