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

jpi*_*ora 36 javascript requirejs

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

foo.example.com
    main.js
    lib/foo-specific.js
framework.example.com
    framework.js <-- entry point
    lib/jquery.js
    lib/etc...
Run Code Online (Sandbox Code Playgroud)

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

有关我目前的内容,请参阅https://github.com/jpillora/js-framework,以及https://github.com/jpillora/prettyprinter了解用例.

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

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

jpi*_*ora 35

James Burke在RequireJS Github问题的页面上回答:问题#447:多个基本URL·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>
Run Code Online (Sandbox Code Playgroud)

将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']);
Run Code Online (Sandbox Code Playgroud)

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

例如,在应用程序http://prettyprint.jpillora.com/中,一旦需要加载framework.js,它将设置路径lib/...http://framework.jpillora.com/并设置baseUrl./js/如此main需要,它将将基本URL设置为它自己的域并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加载应用程序

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

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


Emi*_*erg 10

问题

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

myApp/
    src/
        js/
            app.js
            data.js
            lib/underscore.js
    test/
        karma.conf.js
        test-main.js
        matchers.js
        spec/
            data.js
Run Code Online (Sandbox Code Playgroud)

这里的地方变得棘手:我的应用程序的脚本(app.jsdata.js)认为解决了一个RequireJS配置datasrc/js/data.js,lib/underscoresrc/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',
  // ...
});
Run Code Online (Sandbox Code Playgroud)

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

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();
        });
    });
});
Run Code Online (Sandbox Code Playgroud)

使用一些自定义匹配器:

test/matchers.js
----------------
define([], function() {
    beforeEach(function() {
        this.addMatchers({
            toSatisfyMyCustomMatcher: function() {
                return this.actual.isGood;
            },
        });
    });
});
Run Code Online (Sandbox Code Playgroud)

然而,那'../../test/matchers'部分是非常丑陋的.知道其他模块的文件路径不应该打扰测试规范 - 这就是RequireJS的工作.相反,我们想要使用符号名称.

解决方案

RequireJS 路径配置也可以映射目录.

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

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

test/test-main.js
-----------------
require.config({
  baseUrl: '/base/src/js',
  paths: {
      test: '../../test',
  },
  // ...
});
Run Code Online (Sandbox Code Playgroud)

现在我可以将test目录称为它的子节点baseUrl:

test/spec/data.js
-----------------
define(['data', 'test/matchers'], function(dataModule) {
    // ...
});
Run Code Online (Sandbox Code Playgroud)

在我的情况下有效地出来几乎就像我可以有多个baseUrls一样.