Относительные пути с модулями / пакетами RequireJS - PullRequest
28 голосов
/ 16 февраля 2012

Я довольно новичок в RequireJS и столкнулся с небольшой проблемой.Я написал небольшой фреймворк, построенный на Backbone с использованием RequireJS, и хочу, чтобы его можно было повторно использовать в различных проектах.Итак, с некоторыми поисками я узнал, что требуют позволяет пакеты.Это похоже на то, что я искал.У меня есть файл main.js для запуска моего приложения, который по сути выглядит следующим образом:

require.config({
  packages: ['framework']
});

require(['framework'], function(framework) {
  framework.createDash();
});

Затем в том же каталоге, что и мой main.js, у меня есть еще один каталог с именем "framework", который содержит еще один main.jsчто выглядит следующим образом:

define(function(require, exports, module) {
  exports.createDash = function(dash, element) {
    require(['dash/dash.model', 'dash/dash.view'], function(DashModel, DashView) {
      return new DashView({
        model: new DashModel(dash),
        el: element ? element : window
      });
    });
  };
});

При поиске я нашел эту страницу , которая указывает, что аргумент 'require' должен быть ограничен подмодулем.Тем не менее, когда я пытаюсь потребовать вещи, они по-прежнему относительно моего оригинального main.js.Я перепробовал несколько вещей и искал часы безрезультатно.Можно ли каким-то образом включить вызовы require / define в мой пакет относительно main.js в его корне?

Ответы [ 4 ]

51 голосов
/ 27 мая 2012

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

require.config({
  packages: [
    { name: 'packagename',
      location: 'path/to/your/package/root',  // default 'packagename'
      main: 'scriptfileToLoad'                // default 'main' 
    }]
  ... some other stuff ...
});

Для загрузки вашего модуля вам просто нужно использовать ваше «имя_пакета» в соответствии с требованиями:

define(['jquery', 'packagename'], function($, MyPackage) {
  MyPackage.useIt()
});

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

define(['globalDependency', './myLocalFile'], function(Asdf, LocalFile) {
  LocalFile.finallyLoaded();
});

Есть полезный ярлык: если имя вашего пакета совпадает с вашим местоположением, а ваш основной файл называется 'main.js', то вы можете заменить это

  packages: [
    { name: 'packagename',
      location: 'packagename',
      main: 'main'
    }]

к этому:

  packages: ['packagename']

Насколько я вижу, вы уже пытались определить пакет, но вы также использовали префикс ./? Без этого префикса require попытается найти файлы в своем глобальном корневом пути. А без пакета ./ будет бесполезен, поскольку относительный путь совпадает с глобальным корневым путем.


Приветствия

5 голосов
/ 22 февраля 2012

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

По существу, я хотел загрузить мою структуру в ее собственном контексте.Я нашел контекстную опцию в разделе конфигурации на веб-сайте require и пример того, как его использовать .Первоначально я попытался сделать это, сделав что-то вроде:

var req = require.config({
    baseUrl: 'framework',
    context: 'framework',

    paths: {
        jQuery: 'lib/jquery/jquery-1.7.min.js',
        Underscore: 'lib/underscore/underscore.min.js',
        Backbone: 'lib/backbone/backbone.min.js',
        etc...
    }
});

req(['main'], function() {});

Было две проблемы с этим.Во-первых, моя переменная 'req' определялась вне фреймворка, но я хотел, чтобы фреймворк определял ее собственные пути.И, во-вторых, всякий раз, когда файлу за пределами фреймворка потребуется файл внутри фреймворка, что, в свою очередь, потребует, например, 'jQuery', тогда jQuery (или что-то еще) не потребуется в контексте экземпляра фреймворкаof require и поэтому он не может найти файл.

В итоге я определил main.js своего фреймворка, чтобы он выглядел примерно так:

var paths = {
    jQuery: 'lib/jquery/jquery-1.7.min.js',
    Underscore: 'lib/underscore/underscore.min.js',
    Backbone: 'lib/backbone/backbone.min.js',
    etc...
};

define(function() {
    var exports = {};

    exports.initialize = function(baseUrl, overridePaths, callback) {
        if(!overridePaths) {
        overridePaths = {};
        }
        if(baseUrl && baseUrl[baseUrl.length - 1] != '/') {
            baseUrl = baseUrl + '/';
        }

        var fullpaths = {};
        for(var path in paths) {
            // Don't add baseUrl to anything that looks like a full URL like 'http://...' or anything that begins with a forward slash
            if(paths[path].match(/^(?:.*:\/\/|\/)/)) {
                fullpaths[path] = paths[path];
            }
            else {
                fullpaths[path] = baseUrl + paths[path];
            }
        }

        var config = {paths: fullpaths};
        for(var pathName in overridePaths) {
            config.paths[pathName] = overridePaths[pathName];
        }
        require.config(config);

        // Do anything else you need to do such as defining more functions for exports

        if(callback) {
            callback();
        }
    }

    return exports;
});

А потом в моем проектеФайл main.js Я просто делаю это:

require(['framework/main'], function(framework) {
    // NOTE: This setTimeout() call is used because, for whatever reason, if you make
    //       a 'require' call in here or in the framework without it, it will just hang
    //       and never actually go fetch the files in the browser. There's probably a
    //       better way to handle this, but I don't know what it is.
    setTimeout(function() {
        framework.initialize('framework', null, function() {
            // Do stuff here
        }
    }, 0);
});

Это берет все, что передано в метод initialize () фреймворка для baseURL, и добавляет это к любым путям, которые определяет фреймворк и которые не начинаются скосая черта или что-нибудь: //, если они не являются путями переопределения.Это позволяет пакету, использующему фреймворк, переопределять такие вещи, как «jQuery».

2 голосов
/ 20 февраля 2012

Это сработало для меня, добавив префикс "./" к именам модулей:

define(function (require, exports, module) {
    exports.createDash = function (dash, element) {
        require([ './dash/dash.model', './dash/dash.view' ], function (DashModel, DashView) {
            return new DashView({
                model : new DashModel(dash),
                el : element ? element : window
            });
        });
    };
});
1 голос
/ 29 сентября 2014

Процесс, который мне помог, позволил использовать пакет с подмодулями непосредственно из data-main или из внешней среды, предполагая, что main.js (или другой main пакета) вызывается с определенным именем, был использовать var baseUrl = require.toUrl('packageName') + '/../' в качестве префикса к require.config({ paths: { ... } }) файлу конфигурации. Например:

var music21Base = require.toUrl('music21') + '/../';

require.config({ paths: {
                          'jquery': music21Base + 'ext/jquery/jquery.2.1.10.min';
                          'subModuleLoader': music21Base + 'src/subModuleLoader';
                         }  });

Настройка context: "xxx" отлично работала для вызова обычных модулей с ./modName, но не работала для аргумента paths для меня.

...