简体   繁体   English

RequireJS模块/包的相对路径

[英]Relative paths with RequireJS modules/packages

I'm fairly new to RequireJS and I've run into a bit of a problem. 我是RequireJS的新手,我遇到了一些问题。 I've written a little framework built on Backbone using RequireJS and I want it to be re-usable in different projects. 我使用RequireJS编写了一个基于Backbone构建的小框架,我希望它可以在不同的项目中重用。 So, with some searching I learned that require allows packages. 所以,通过一些搜索,我了解到需要允许包。 This seemed like what I was looking for. 这看起来像我在寻找。 I have a main.js file to launch my app that essentially looks like this: 我有一个main.js文件来启动我的应用程序,基本上是这样的:

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

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

Then in the same directory as my main.js I have another directory called "framework" which contains another main.js which looks like this: 然后在与我的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
      });
    });
  };
});

In searching I found this page which indicates that the 'require' argument should be scoped to the submodule. 在搜索中我发现这个页面表明'require'参数应该作用于子模块。 However, when I try to require things they are still relative to my original main.js. 但是,当我尝试要求它们仍然相对于我原来的main.js. I've tried a number of things and searched for hours to no avail. 我已经尝试了很多东西,并且搜索了几个小时无济于事。 Is there any way I can have my require/define calls within my package included relative to the main.js in it's root? 有没有什么方法可以让我的包中的require / define调用相对于它的根目录中的main.js包含?

You need to define your submodule as package in the require configuration: 您需要在require配置中将子模块定义为包:

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

To load your module you just need to use your 'packagename' at the requirements: 要加载模块,您只需要在要求中使用'packagename':

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

In your package you must use the ./ prefix to load your files relative to your submodule: 在您的包中,您必须使用./前缀来加载相对于子模块的文件:

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

There is a useful shortcut: If your package name equals to your location and your main file is called 'main.js', then you can replace this 有一个有用的快捷方式:如果您的包名称等于您的位置,而您的主文件名为'main.js',那么您可以替换它

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

to this: 对此:

  packages: ['packagename']

As far as I can see, you already tried to define a package but did you also use the ./ prefix? 据我所知,你已经尝试定义一个包,但你是否也使用./前缀? Without this prefix require will try to find the files in it's global root-path. 如果没有此前缀,require将尝试在其全局根路径中查找文件。 And without a package, ./ will be useless because the relative path is the same as the global root-path. 如果没有包,。 ./将无用,因为相对路径与全局根路径相同。


Cheers 干杯

I figured out the answer to my question, and the solution (they were not the same apparently). 我想出了我的问题的答案和解决方案(显然它们不一样)。 I guess I'll post it here in case it can help someone else in the future. 我想我会在这里发布,以防将来可以帮助其他人。

Essentially what I was wanting was to load my framework within its own context. 基本上我想要的是在自己的上下文中加载我的框架。 I found the context option under the configuration section on require's website and an example of how to use it . 我在require的网站上的配置部分下找到了context选项,以及如何使用它示例 Originally I tried this by doing something like: 最初我通过做类似的事情来尝试这个:

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() {});

There were two problems with this. 这有两个问题。 First, my 'req' variable was being defined outside of the framework, but I wanted the framework to define it's own paths. 首先,我的'req'变量是在框架之外定义的,但我希望框架定义它自己的路径。 And second, whenever a file outside of the framework would require a file within the framework, which would in turn require 'jQuery', for example, then jQuery (or whatever else) wouldn't be required from within the context of the framework instance of require and so it couldn't find the file. 第二,每当框架外的文件需要框架内的文件时,例如需要'jQuery',那么在框架实例的上下文中就不需要jQuery(或其他任何东西)需要,所以它找不到文件。

What I ended up doing was defining my framework's main.js to look something like this: 我最终做的是定义我的框架的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;
});

And then in my project's main.js file I just do this: 然后在我的项目的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);
});

This takes whatever is passed in to the framework's initialize() method for 'baseURL' and prepends that to any paths that the framework defines that do not start with a forward slash or 'anything://', unless they are override paths. 这将传递给框架的'baseURL'的initialize()方法,并将其预先添加到框架定义的不以正斜杠或'anything://'开头的任何路径,除非它们是覆盖路径。 This allows the package using the framework to override things like 'jQuery'. 这允许使用框架的包覆盖诸如'jQuery'之类的东西。

This worked for me, adding a "./" prefix to the module names: 这对我"./" ,在模块名称中添加了"./"前缀:

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
            });
        });
    };
});

A process that worked well for me for allowing a package with submodules to be used directly from data-main or from an outside framework, assuming that a main.js (or other package main) is called by a particular name, was to use var baseUrl = require.toUrl('packageName') + '/../' as a prefix to a require.config({ paths: { ... } }) configuration file. 一个适合我的进程,允许直接从data-main或外部框架使用包含子模块的包,假设main.js(或其他包main)由特定名称调用,是使用var baseUrl = require.toUrl('packageName') + '/../'作为require.config({ paths: { ... } })配置文件的前缀。 For instance: 例如:

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

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

The setting of context: "xxx" worked fine for calling normal modules with ./modName but did not work for the paths argument for me. context: "xxx"的设置context: "xxx"适用于使用./modName调用普通模块,但对于我的paths参数不起作用。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM