36

我想使用一个单独的域作为 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

4 回答 4

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>

将 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/中,一旦加载了 require framework.js,它将设置 http://framework.jpillora.com/ 的路径lib/...设置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.

于 2012-09-09T14:52:07.393 回答
10

问题

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

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 配置解析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',
  // ...
});

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

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

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

解决方案

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

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

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

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

baseUrl就我而言,这实际上与我可以拥有多个s几乎相同。

于 2014-08-05T10:09:20.267 回答
0

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

例如,UI 组件的所有路径都添加到 URL 控制器对象中。

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

于 2012-09-07T03:55:19.870 回答
0

requirejs 多版本

尝试这个

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

于 2019-06-18T22:27:37.163 回答