Относительные пути с модулями/пакетами RequireJS
Я новичок в RequireJS, и у меня возникла проблема. Я написал небольшую структуру, построенную на Backbone, используя RequireJS, и я хочу, чтобы она была повторно использована в разных проектах. Поэтому, с некоторыми поисками, я узнал, что требуется разрешить пакеты. Это казалось тем, что я искал. У меня есть файл main.js для запуска моего приложения, которое выглядит примерно так:
require.config({
packages: ['framework']
});
require(['framework'], function(framework) {
framework.createDash();
});
Тогда в том же каталоге, что и my 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
});
});
};
});
В поиске я нашел this page, который указывает, что аргумент 'require' должен быть привязан к подмодулю. Однако, когда я пытаюсь потребовать вещи, они по-прежнему относительно моего оригинального main.js. Я пробовал много вещей и искал часы безрезультатно. Есть ли способ, которым мои вызовы require/define внутри моего пакета включаются относительно main.js в нем root?
Ответы
Ответ 1
Вам необходимо определить ваш подмодуль как пакет в требуемой конфигурации:
require.config({
packages: [
{ name: 'packagename',
location: 'path/to/your/package/root', // default 'packagename'
main: 'scriptfileToLoad' // default 'main'
}]
... some other stuff ...
});
Чтобы загрузить ваш модуль, вам просто нужно использовать свой 'packagename' в соответствии с требованиями:
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 попытается найти файлы в нем глобальный корневой путь. И без пакета ./
будет бесполезным, поскольку относительный путь совпадает с глобальным корневым путем.
Приветствия
Ответ 2
Я выяснил ответ на мой вопрос и решение (они были явно не такими). Думаю, я отправлю его здесь, если он может помочь кому-то еще в будущем.
По сути, я хотел, чтобы загрузить мою фреймворк в своем собственном контексте. Я нашел контекстную опцию в разделе на веб-сайте 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 (или что-то еще) не потребуется из контекста экземпляра фрейма и поэтому он не смог найти файл.
То, что я закончил, - это определение моей рамки 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 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);
});
Это принимает все, что передается в метод initial initialize() для "baseURL", и добавляет, что к любым путям, которые определяет инфраструктура, которые не начинаются с косой черты или "ничего://", если они не переопределены пути. Это позволяет пакету с использованием фреймворка переопределять такие вещи, как "jQuery".
Ответ 3
Это сработало для меня, добавив префикс "./"
к именам модулей:
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
});
});
};
});
Ответ 4
Процесс, который хорошо работал у меня для того, чтобы позволить пакет с субмодулями использоваться непосредственно из основной базы данных или из внешней структуры, предполагая, что main.js(или другой основной пакет) вызывается конкретным именем, был использовать 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
для меня.