RequireJS:有没有办法实现多个基本URL?

时间:2012-09-06 14:33:18

标签: javascript requirejs

我想使用一个单独的域作为JavaScript框架,它将创建一个基本需求配置,我可以从应用程序中增加。

foo.example.com
    main.js
    lib/foo-specific.js
framework.example.com
    framework.js <-- entry point
    lib/jquery.js
    lib/etc...

最理想的是,我希望能够要求'lib / foo-specific'和/或'lib / jquery'并且让路径很好地解决,但是从我发现的,没有办法做这个,除非我为框架中的每个js文件使用特定的路径键/值。目前,我有一个自定义插件,可以使用不同的基本URL(例如fw!lib/jquery)加载给定路径,但如果我想使用text!插件,它将无法正常工作插件链不受支持。

请参阅https://github.com/jpillora/js-framework了解我目前的情况,并https://github.com/jpillora/prettyprinter了解用例。

有没有一个干净的方法来解决这个问题?或者实现多个基本URL?

注意:我也查看了多个require实例,但我认为这不会起作用,因为我希望应用程序能够访问框架的配置。

4 个答案:

答案 0 :(得分:35)

James Burke在RequireJS Github问题的页面上回答:Issue #447: Multiple Base URLs · jrburke/requirejs

如果 data-main是脚本的唯一入口点(更多信息的评论),结果很简单,我用以下方法解决了我的特殊问题:

我的应用index.html

<script src="http://framework.jpillora.com/js/lib/require.js" 
  data-main="http://framework.jpillora.com/js/framework" > </script>

将requirejs入口点设置为framework.js

var framework = ... //set using script elements src attribute

require.config({

    baseUrl: 'js/',

    //Framework paths
    paths: {
      'framework': framework,
      'lib'      : framework + 'js/lib',
      'ext'      : framework + 'js/ext',
      'util'     : framework + 'js/util'
    },

    //Shortcuts
    map: {
      '*': {
        ...
      }
    },

    //Non-modularised libraries with deps
    shim: {
      ...
    }
});

require(['main']);

因此,我们不是通常执行index.html->main.js,而是添加一个额外的步骤index.html->framework.js->main.js,它为应用程序代码提供了框架代码路径的知识。

例如,在应用http://prettyprint.jpillora.com/中,一旦需要加载framework.js,它就会设置lib/...http://framework.jpillora.com/的路径并设置baseUrl作为./js/,因此只需要main,就会将基本网址设置为自己的域名,并将lib指向另一个域名。

哪个会产生require(['lib/foo', 'view/bar']); 解决:

http://framework.jpillora.com/js/lib/foo.jshttp://prettyprint.jpillora.com/js/view/bar.js

如此处所示,该应用仅为main.js其他所有内容均来自framework

chrome devtools loaded app

最后,每当我使用上面的main.js加载应用程序的framework.js时,我就可以访问所有常用的库和实用程序类。请参阅应用来源。

另请注意,使用r.js优化器和一个不错的本地文件结构,还可以将应用程序优化为单个js文件,仅提取framework所需的内容。

答案 1 :(得分:9)

问题

我在尝试设置测试环境时遇到了类似的问题。我有一个像这样的文件结构:

myApp/
    src/
        js/
            app.js
            data.js
            lib/underscore.js
    test/
        karma.conf.js
        test-main.js
        matchers.js
        spec/
            data.js

这里有些棘手:我的应用脚本(app.jsdata.js)假设一个RequireJS配置将data解析为src/js/data.js,{{1到lib/underscore等,所以我也需要在我的测试环境中进行配置:

src/js/lib/underscore.js

现在我可以写我的测试了:

test/test-main.js
-----------------
require.config({
  // Karma serves files under /base, which is the basePath from your config file
  baseUrl: '/base/src/js',
  // ...
});

使用一些自定义匹配器:

test/spec/data.js
-----------------
define(['data', '../../test/matchers'], function(dataModule) {
    describe('The data module', function() {
        it('should satisfy my custom matcher', function() {
            expect(dataModule).toSatisfyMyCustomMatcher();
        });
    });
});

然而,test/matchers.js ---------------- define([], function() { beforeEach(function() { this.addMatchers({ toSatisfyMyCustomMatcher: function() { return this.actual.isGood; }, }); }); }); 部分非常丑陋。通过了解其他模块的文件路径 - 这就是RequireJS的工作,不应该打扰测试规范。相反,我们想要使用符号名称。

解决方案

RequireJS paths config也可以映射目录。

  

用于模块名称的路径不应包含扩展名,因为路径映射可以用于目录。

所以,解决方案是一个简单的路径配置:

'../../test/matchers'

现在我可以将test/test-main.js ----------------- require.config({ baseUrl: '/base/src/js', paths: { test: '../../test', }, // ... }); 目录称为test的孩子:

baseUrl

在我的案例中,有效的方式与我可以有多个test/spec/data.js ----------------- define(['data', 'test/matchers'], function(dataModule) { // ... }); 几乎相同。

答案 2 :(得分:0)

了解我们如何处理BoilerplateJS中的路由和上下文,这是大规模产品开发的参考架构。我们使用库crossroads.js来路由模块和UI组件。所有要做的就是将路径/哈希添加到路由集中,它将通过框架进行路由。

作为example,UI组件的所有路径都会添加到URL控制器对象中。

对于在整个应用程序中访问框架配置信息,可以将配置/设置附加到可在应用程序内访问的全局上下文对象。

答案 3 :(得分:0)

requirejs multiversion

尝试一下

context:赋予加载上下文的名称。只要每个顶级require调用都指定一个唯一的上下文字符串,这便允许require.js在页面中加载模块的多个版本。要正确使用它,请参阅“ Multiversion支持”部分。