RequireJS 模块/包的相对路径

发布于 2025-01-06 04:12:47 字数 1000 浏览 2 评论 0原文

我对 RequireJS 还很陌生,并且遇到了一些问题。我使用 RequireJS 编写了一个基于 Backbone 构建的小框架,我希望它可以在不同的项目中重复使用。因此,通过一些搜索,我了解到 require 允许包。这似乎就是我正在寻找的。我有一个 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 包含在内?

I'm fairly new to RequireJS and I've run into a bit of a problem. I've written a little framework built on Backbone using RequireJS and I want it to be re-usable in different projects. 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:

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:

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. However, when I try to require things they are still relative to my original 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?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(4

手心的海 2025-01-13 04:12:47

您需要在 require 配置中将您的子模块定义为包:

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 将尝试在其全局根路径中查找文件。如果没有包, ./ 将毫无用处,因为相对路径与全局根路径相同。

干杯

You need to define your submodule as package in the require configuration:

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:

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

  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. And without a package, ./ will be useless because the relative path is the same as the global root-path.

Cheers

芯好空 2025-01-13 04:12:47

我找到了问题的答案和解决方案(它们显然不一样)。我想我会将其发布在这里,以防将来对其他人有所帮助。

本质上我想要的是在它自己的上下文中加载我的框架。我在 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(或其他任何内容) 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);
});

:将其添加到框架定义的任何不以正斜杠或“anything://”开头的路径之前,除非它们是覆盖路径。这允许使用框架的包覆盖“jQuery”之类的东西。

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. 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. 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.

What I ended up doing was defining my framework's main.js to look something like this:

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:

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. This allows the package using the framework to override things like 'jQuery'.

偏爱自由 2025-01-13 04:12:47

这对我有用,在模块名称中添加 "./" 前缀:

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 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
            });
        });
    };
});
行雁书 2025-01-13 04:12:47

一个对我来说效果很好的过程,允许直接从 data-main 或外部框架使用带有子模块的包,假设 main.js (或其他包 main)由特定名称调用,是使用 < code>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 参数不起作用为我。

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. 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.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文