Загрузка Highcharts через прокладку с использованием RequireJS и поддержание зависимости jQuery

Я пытаюсь загрузить библиотеку Highcharts, используя прокладку в RequireJS. Однако при загрузке Highcharts генерируется исключение, потому что он не может получить доступ к методам jQuery, от которых зависит.

Требуемый конфиг выглядит так:

require.config({
    baseUrl: "js",

    shim: {

        'libs/highcharts/highcharts.src.js': {
            deps: ['jquery'],
            exports: function(jQuery)
            {
                this.HighchartsAdapter = jQuery;

                return this.Highcharts;
            }
        }
    }
});

Выбрасывается следующее исключение:

Uncaught TypeError: undefined is not a function

и относится к этой строке:

dataLabels: merge(defaultLabelOptions, {

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

Я точно не знаю, как убедиться, что Highcharts получает доступ к jQuery с помощью RequireJS и shim.

Кто-нибудь раньше использовал вместе RequireJS и Highcharts? Я предполагаю, что проблема связана не с highcharts, а с любой библиотекой, которая имеет другие виды зависимостей.

Заранее спасибо за любые советы или указания в правильном направлении!

Чтобы добавить дополнительный контекст, в надежде, что кто-то, кто знаком с require.js или shims, сможет помочь, не будучи слишком близко знакомым с highcharts, вот какой-то источник, который настраивает этот merge метод в Highcharts

var globalAdapter = win.HighchartsAdapter,
adapter = globalAdapter || {},

// Utility functions. If the HighchartsAdapter is not defined, 
// adapter is an empty object
// and all the utility functions will be null. In that case they are 
// populated by the
// default adapters below.

// {snipped code}

merge = adapter.merge

// {snipped code}

if (!globalAdapter && win.jQuery) {
    var jQ = win.jQuery;

    // {snipped code}

    merge = function () {
        var args = arguments;
        return jQ.extend(true, null, args[0], args[1], args[2], args[3]);
    };

    // {snipped code}
}

Объект win — это ссылка, установленная на window в начале скрипта. Итак, я подумал, что добавление window.jQuery = jQuery; к методу экспорта на прокладке приведет к тому, что highcharts подберет ссылку jQuery; но это не так.

Опять же, на этом этапе будут оценены любые идеи, информация, советы или реплики - я в полной растерянности и начинаю сомневаться, стоит ли вообще пытаться внедрить систему пакетов AMD в javascript браузера.


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

RequireJS использует «пути» для поиска библиотек, которые не поддерживаются «AMD», и загружает их на вашу страницу. объект «прокладка» позволяет вам определять зависимости для библиотек, определенных в путях. Зависимости должны быть загружены до того, как requirejs попытается загрузить зависимый скрипт.

Свойство exports предоставляет механизм, сообщающий requirejs, как определить, загружена ли библиотека. Для основных библиотек, таких как jquery, backbone, socketio и т. д., все они экспортируют некоторую переменную уровня окна (Backbone, io, jQuery и $ и т. д.). Вы просто указываете это имя переменной как свойство exports, и requirejs сможет определить, когда загружается библиотека.

Как только ваши определения сделаны, вы можете использовать функцию requirejs' define, как и ожидалось.

Вот мой пример объекта require.config:

require.config({
    baseUrl: "/js/",

    paths: {
        jquery: 'jquery',
        socketio: 'http://localhost:8000/socket.io/socket.io', //for loading the socket.io client library
        highcharts: 'libs/highcharts/highcharts.src',
        underscore: 'libs/underscore',
        backbone: 'libs/backbone'
    },

    shim: {
        jquery: {
            exports: 'jQuery'
        },

        socketio: {
            exports: 'io'
        },

        underscore: {
            exports: '_'
        },

        backbone: {
            deps: ['jquery', 'underscore'],
            exports: 'Backbone'
        },

        highcharts: {
            deps: ['jquery'],
            exports: 'Highcharts'
        }
    }
});

Как упоминалось ранее pabera, это для Require.JS версии 2.0.1.

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


person Jim Rubenstein    schedule 06.06.2012    source источник


Ответы (2)


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

requirejs.config({
    baseUrl:'/js/',
    paths:{
      jquery:'vendor/jquery',
      handlebars: 'vendor/handlebars',
      text: 'vendor/require-text',
      chaplin:'vendor/chaplin',
      underscore:'vendor/underscore',
      backbone:'vendor/backbone',
      highcharts: 'vendor/highcharts'
    },

    shim: {
      backbone: {
        deps: ['underscore', 'jquery'],
        exports: 'Backbone'
      },
      underscore: {
        exports: '_'
      },    
      highcharts: {
        exports: 'Highcharts'
      }    
    },
});

Поскольку я использую Chaplin поверх Backbone, я включаю еще несколько файлов в свой атрибут paths. Highcharts имеет схожую структуру с Backbone, поэтому я подумал, что смогу загрузить его таким же образом. Теперь это работает для меня. Как видите, я уже добавляю highcharts в атрибут paths, чтобы экспортировать его как прокладку послесловия.

Возможно, это поможет, в противном случае давайте попробуем внести еще больший вклад в решение вашей проблемы.

person pabera    schedule 12.06.2012
comment
Я попробую и посмотрю, что у меня получится; Спасибо за ответ! - person Jim Rubenstein; 12.06.2012
comment
Я использую require.js 2.0.1, если это важно. Удачи - person pabera; 13.06.2012
comment
Я изменился, чтобы использовать обычный require.js (вместо w/jquery) и использовал прокладку jquery с вашим объяснением/примером путей/прокладок. после прочтения документации еще немного, теперь я понимаю, что происходит - большое спасибо! - person Jim Rubenstein; 13.06.2012
comment
Почему бы не сделать ваш baseUrl '/js/vendor/'? - person Adam Grant; 24.10.2013

Хотя jQuery можно использовать как модуль AMD, он все равно будет экспортировать себя в окно, поэтому любые скрипты, зависящие от глобального jQuery или $, будут работать до тех пор, пока jQuery загружается первым.

Вы пробовали задать путь? jQuery интересен тем, что, хотя документация RequireJS не рекомендует вам называть свои модули, jQuery на самом деле это делает.

Из исходного кода jQuery

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

Это означает, что вам нужно будет указать RequireJS, где найти «jquery». Так:

require.config({
    paths: {
        'jquery': 'path/to/jquery'
    }
});

Если вам интересно, почему jQuery регистрируется таким образом, то есть довольно большой комментарий в источнике, в котором содержится более подробная информация

person Simon Smith    schedule 06.06.2012
comment
На самом деле я скачал код require.js с кодом jquery здесь, думая, что он по крайней мере, это рекомендуемый способ загрузки jquery с помощью require.js, поэтому я использую именно его. Насколько я понимаю, jQuery в значительной степени обрабатывается источником require.js с использованием этой загрузки, которая должна (я предполагаю) свести на нет необходимость использования «путей» для установки пути для jquery или подстановки jquery. - person Jim Rubenstein; 06.06.2012