使用 RequireJS 加载 Backbone 和 Underscore

发布于 2024-12-15 20:58:22 字数 2173 浏览 3 评论 0原文

我正在尝试使用 RequireJS 加载 Backbone 和 Underscore (以及 jQuery)。对于最新版本的 Backbone 和 Underscore,这似乎有点棘手。其一,Underscore 自动将自身注册为模块,但 Backbone 假定 Underscore 是全局可用的。我还应该注意到,Backbone 似乎没有将自己注册为模块,这使得它与其他库不一致。这是我能想到的最好的 main.js,它可以工作:

require(
{
    paths: {
        'backbone': 'libs/backbone/backbone-require',
        'templates': '../templates'
    }
},
[
    // jQuery registers itself as a module.
    'http://cdnjs.cloudflare.com/ajax/libs/jquery/1.7/jquery.min.js',

    // Underscore registers itself as a module.
    'http://cdnjs.cloudflare.com/ajax/libs/underscore.js/1.2.1/underscore-min.js'
], function() {

    // These nested require() calls are just due to how Backbone is built.  Underscore basically says if require()
    // is available then it will automatically register an "underscore" module, but it won't register underscore
    // as a global "_".  However, Backbone expects Underscore to be a global variable.  To make this work, we require
    // the Underscore module after it's been defined from within Underscore and set it as a global variable for
    // Backbone's sake.  Hopefully Backbone will soon be able to use the Underscore module directly instead of
    // assuming it's global.
    require(['underscore'], function(_) {
        window._ = _;
    });

    require([
        'order!http://cdnjs.cloudflare.com/ajax/libs/backbone.js/0.5.3/backbone-min.js',
        'order!app'
    ], function(a, app) {
        app.initialize();
    })
});

我应该提到的是,虽然它工作,但优化器会卡住。我收到以下信息:

Tracing dependencies for: main
js: "/home/httpd/aahardy/requirejs/r.js", line 7619: exception from uncaught JavaScript throw: Error: Error: Error evaluating module "undefined" at location "/home/httpd/aahardy/phoenix/trunk/ui/js/../../ui-build/js/underscore.js":
JavaException: java.io.FileNotFoundException: /home/httpd/aahardy/phoenix/trunk/ui/js/../../ui-build/js/underscore.js (No such file or directory)
fileName:/home/httpd/aahardy/phoenix/trunk/ui/js/../../ui-build/js/underscore.js
lineNumber: undefined
http://requirejs.org/docs/errors.html#defineerror
In module tree:
    main

有更好的方法来处理这个问题吗?谢谢!

I'm trying to load Backbone and Underscore (as well as jQuery) with RequireJS. With the latest versions of Backbone and Underscore, it seems kind of tricky. For one, Underscore automatically registers itself as a module, but Backbone assumes Underscore is available globally. I should also note that Backbone doesn't seem to register itself as a module which makes it kind of inconsistent with the other libs. This is the best main.js I could come up with that works:

require(
{
    paths: {
        'backbone': 'libs/backbone/backbone-require',
        'templates': '../templates'
    }
},
[
    // jQuery registers itself as a module.
    'http://cdnjs.cloudflare.com/ajax/libs/jquery/1.7/jquery.min.js',

    // Underscore registers itself as a module.
    'http://cdnjs.cloudflare.com/ajax/libs/underscore.js/1.2.1/underscore-min.js'
], function() {

    // These nested require() calls are just due to how Backbone is built.  Underscore basically says if require()
    // is available then it will automatically register an "underscore" module, but it won't register underscore
    // as a global "_".  However, Backbone expects Underscore to be a global variable.  To make this work, we require
    // the Underscore module after it's been defined from within Underscore and set it as a global variable for
    // Backbone's sake.  Hopefully Backbone will soon be able to use the Underscore module directly instead of
    // assuming it's global.
    require(['underscore'], function(_) {
        window._ = _;
    });

    require([
        'order!http://cdnjs.cloudflare.com/ajax/libs/backbone.js/0.5.3/backbone-min.js',
        'order!app'
    ], function(a, app) {
        app.initialize();
    })
});

I should mention that, while it works, the optimizer chokes on it. I receive the following:

Tracing dependencies for: main
js: "/home/httpd/aahardy/requirejs/r.js", line 7619: exception from uncaught JavaScript throw: Error: Error: Error evaluating module "undefined" at location "/home/httpd/aahardy/phoenix/trunk/ui/js/../../ui-build/js/underscore.js":
JavaException: java.io.FileNotFoundException: /home/httpd/aahardy/phoenix/trunk/ui/js/../../ui-build/js/underscore.js (No such file or directory)
fileName:/home/httpd/aahardy/phoenix/trunk/ui/js/../../ui-build/js/underscore.js
lineNumber: undefined
http://requirejs.org/docs/errors.html#defineerror
In module tree:
    main

Is there a better way of handling this? Thanks!

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

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

发布评论

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

评论(6

寻找一个思念的角度 2024-12-22 20:58:23

RequireJS 2.X 现在有机地解决非 AMD 模块,例如骨干网使用新的 shim 配置可以更好地强调。

shim 配置使用起来很简单:(1) 声明依赖项 (deps),如果有的话,(可能来自 path配置,或者本身可能是有效路径)。 (2)(可选)从您正在填充的文件中指定全局变量名称,该名称应导出到需要它的模块函数中。 (如果您没有指定导出,那么您只需要使用全局,因为没有任何内容将被传递到您的 require/define 函数中。)

这是一个使用 shim 的简单示例加载骨干网。它还添加了下划线的导出,即使它没有任何依赖项。

require.config({
  shim: {
    underscore: {
      exports: '_'
    },
    backbone: {
      deps: ["underscore", "jquery"],
      exports: "Backbone"
    }
  }
});

//the "main" function to bootstrap your code
require(['jquery', 'underscore', 'backbone'], function ($, _, Backbone) {   // or, you could use these deps in a separate module using define

});

注意:此简化代码假设 jquery、backbone 和 underscore 位于与此“相同的目录中名为“jquery.js”、“backbone.js”和“underscore.js”的文件中main”代码(成为 require 的 baseURL)。如果不是这种情况,您需要使用路径配置 .

我个人认为,通过内置的 shim 功能,不使用 Backbone & 分叉版本的优点是:下划线胜过使用其他流行答案中推荐的 AMD 分支的好处,但无论哪种方式都有效。

RequireJS 2.X now organically addresses non-AMD modules such as Backbone & Underscore much better, using the new shim configuration.

The shim configuration is simple to use: (1) one states the dependencies (deps), if any, (which may be from the paths configuration, or may be valid paths themselves). (2) (optionally) specify the global variable name from the file you're shimming, which should be exported to your module functions that require it. (If you don't specify the exports, then you'll need to just use the global, as nothing will get passed into your require/define functions.)

Here is a simple example usage of shim to load Backbone. It also adds an export for underscore, even though it doesn't have any dependencies.

require.config({
  shim: {
    underscore: {
      exports: '_'
    },
    backbone: {
      deps: ["underscore", "jquery"],
      exports: "Backbone"
    }
  }
});

//the "main" function to bootstrap your code
require(['jquery', 'underscore', 'backbone'], function ($, _, Backbone) {   // or, you could use these deps in a separate module using define

});

Note: this simplified code assumes that jquery, backbone and underscore are in files named "jquery.js", "backbone.js" and "underscore.js" in the same directory as this "main" code (which becomes the baseURL for require). If this isn't the case, you'll need to use a paths config.

I personally think with the built-in shim functionality, the advantages of not using a forked version of Backbone & Underscore outweigh the benefits of using the AMD fork recommended in the other popular answer, but either way works.

盛装女皇 2024-12-22 20:58:23

更新:从版本 1.3.0 开始 Underscore 删除了 AMD (RequireJS) 支持。

您可以使用 amdjs/Backbone 0.9.1amdjs/Underscore 1.3.1 分叉,由 James Burke(RequireJS 的维护者)提供 AMD 支持。

有关 AMD 对 Underscore 和 Backbone 的支持的更多信息。

// main.js using RequireJS 1.0.7
require.config({
    paths: {
        'jquery': 'libs/jquery/1.7.1/jquery',
        'underscore': 'libs/underscore/1.3.1-amdjs/underscore', // AMD support
        'backbone': 'libs/backbone/0.9.1-amdjs/backbone', // AMD support
        'templates': '../templates'
    }
});

require([
    'domReady', // optional, using RequireJS domReady plugin
    'app'
], function(domReady, app){
    domReady(function () {
        app.initialize();
    });
});

模块已正确注册,并且不需要订单插件:

// app.js
define([
    'jquery', 
    'underscore',
    'backbone'
], function($, _, Backbone){
    return {
        initialize: function(){
            // you can use $, _ or Backbone here
        }
    };
});

下划线实际上是可选的,因为 Backbone 现在自行获取其依赖项:

// app.js
define(['jquery', 'backbone'], function($, Backbone){
    return {
        initialize: function(){
            // you can use $ and Backbone here with
            // dependencies loaded i.e. Underscore
        }
    };
});

使用一些 AMD 糖 你也可以这样写:

define(function(require) {
    var Backbone = require('backbone'),
        $ = require('jquery');

    return {
        initialize: function(){
            // you can use $ and Backbone here with
            // dependencies loaded i.e. Underscore
        }
    };
});

关于优化器错误:仔细检查你的构建配置。我假设您的路径配置已关闭。如果您有一个类似于 RequireJS 文档的目录设置,您可以使用:

// app.build.js
({
    appDir: "../",
    baseUrl: "js",
    dir: "../../ui-build",
    paths: {
        'jquery': 'libs/jquery/1.7.1/jquery',
        'underscore': 'libs/underscore/1.3.1-amdjs/underscore',
        'backbone': 'libs/backbone/0.9.1-amdjs/backbone',
        'templates': '../templates'
    }, 
    modules: [
        {
            name: "main"
        }
    ]
})

Update: As of version 1.3.0 Underscore removed AMD (RequireJS) support.

You can use the amdjs/Backbone 0.9.1 and the amdjs/Underscore 1.3.1 fork with AMD support from James Burke (the maintainer of RequireJS).

More info about AMD support for Underscore and Backbone.

// main.js using RequireJS 1.0.7
require.config({
    paths: {
        'jquery': 'libs/jquery/1.7.1/jquery',
        'underscore': 'libs/underscore/1.3.1-amdjs/underscore', // AMD support
        'backbone': 'libs/backbone/0.9.1-amdjs/backbone', // AMD support
        'templates': '../templates'
    }
});

require([
    'domReady', // optional, using RequireJS domReady plugin
    'app'
], function(domReady, app){
    domReady(function () {
        app.initialize();
    });
});

The modules are properly registered and there is no need for the order plugin:

// app.js
define([
    'jquery', 
    'underscore',
    'backbone'
], function($, _, Backbone){
    return {
        initialize: function(){
            // you can use $, _ or Backbone here
        }
    };
});

Underscore is actually optional, because Backbone now gets its dependencies on its own:

// app.js
define(['jquery', 'backbone'], function($, Backbone){
    return {
        initialize: function(){
            // you can use $ and Backbone here with
            // dependencies loaded i.e. Underscore
        }
    };
});

With some AMD sugar you could also write it like this:

define(function(require) {
    var Backbone = require('backbone'),
        $ = require('jquery');

    return {
        initialize: function(){
            // you can use $ and Backbone here with
            // dependencies loaded i.e. Underscore
        }
    };
});

Regarding the optimizer error: doublecheck your build configuration. I assume your path configuration is off. If you have a directory setup similar to the RequireJS Docs you can use:

// app.build.js
({
    appDir: "../",
    baseUrl: "js",
    dir: "../../ui-build",
    paths: {
        'jquery': 'libs/jquery/1.7.1/jquery',
        'underscore': 'libs/underscore/1.3.1-amdjs/underscore',
        'backbone': 'libs/backbone/0.9.1-amdjs/backbone',
        'templates': '../templates'
    }, 
    modules: [
        {
            name: "main"
        }
    ]
})
苹果你个爱泡泡 2024-12-22 20:58:23

作为参考,从版本 1.1.1(~2013 年 2 月)开始,Backbone 还将自身注册为 AMD 模块 。它将与 requirejs 一起使用,而无需使用其 shim 配置。 (James Burke 的 amdjs 分支自 1.1.0 以来也没有更新过)

For reference, as of version 1.1.1 (~Feb '13), Backbone also registers itself as an AMD module. It will work with requirejs without the need to use its shim config. (James Burke's amdjs fork also hasn't been updated since 1.1.0)

飘逸的'云 2024-12-22 20:58:23

好消息,Underscore 1.6.0 现在支持 requirejs Define !!!

低于此的版本需要垫片,或者需要 underscore.js 然后盲目地希望“_”全局变量没有被破坏(公平地说这是一个公平的赌注)

只需将其加载

  requirejs.config({
    paths: {
        "underscore": "PATH/underscore-1.6.0.min",
    }
  });

Good news, Underscore 1.6.0 now supports requirejs define !!!

versions below this require shims, or requiring underscore.js then blindly hoping that the "_" global variable hasn;t been smashed (which to be fair is a fair bet)

simply load it in by

  requirejs.config({
    paths: {
        "underscore": "PATH/underscore-1.6.0.min",
    }
  });
西瑶 2024-12-22 20:58:23

我就直接写下来,你可以看一下requirejs.org上的解释,你可以将下面的代码作为你日常使用的片段; (附注:我使用 yeoman)(由于许多内容已更新,我于 2014 年 2 月发布此内容。)

确保您在 index.html 中包含脚本

<!-- build:js({app,.tmp}) scripts/main.js -->
<script data-main="scripts/main" src="bower_components/requirejs/require.js"></script>
<!-- endbuild -->

然后,在 main.js

require.config({
    shim: {
        'backbone': {
            deps: ['../bower_components/underscore/underscore.js', 'jquery'],
            exports: 'Backbone'
        }
    },

    paths: {
        jquery: '../bower_components/jquery/jquery',
        backbone: '../bower_components/backbone/backbone'
    }
});

require(['views/app'], function(AppView){
    new AppView();
});

app.js

/**
 * App View
 */
define(['backbone', 'router'], function(Backbone, MainRouter) {
    var AppView = Backbone.View.extend({
        el: 'body',

        initialize: function() {
            App.Router = new MainRouter();
            Backbone.history.start();
        }
    });

    return AppView;
});

中,我希望我有用。!

I will write down directly, you can read the explaination on requirejs.org, you could use below code as a snippet for your everyday use; (p.s. i use yeoman) (since many things updated, im posting this as of Feb 2014.)

Make sure you included script in your index.html

<!-- build:js({app,.tmp}) scripts/main.js -->
<script data-main="scripts/main" src="bower_components/requirejs/require.js"></script>
<!-- endbuild -->

Then, in main.js

require.config({
    shim: {
        'backbone': {
            deps: ['../bower_components/underscore/underscore.js', 'jquery'],
            exports: 'Backbone'
        }
    },

    paths: {
        jquery: '../bower_components/jquery/jquery',
        backbone: '../bower_components/backbone/backbone'
    }
});

require(['views/app'], function(AppView){
    new AppView();
});

app.js

/**
 * App View
 */
define(['backbone', 'router'], function(Backbone, MainRouter) {
    var AppView = Backbone.View.extend({
        el: 'body',

        initialize: function() {
            App.Router = new MainRouter();
            Backbone.history.start();
        }
    });

    return AppView;
});

I hope I was useful.!

递刀给你 2024-12-22 20:58:23
require.config({
  waitSeconds: 500,
  paths: {
    jquery: "libs/jquery/jquery",
    jqueryCookie: "libs/jquery/jquery.cookie",
    .....
  },

  shim: {
    jqxcore: {
      export: "$",
      deps: ["jquery"]
    },
    jqxbuttons: {
      export: "$",
      deps: ["jquery", "jqxcore"]
    }
    ............
  }
});

require([
 <i> // Load our app module and pass it to our definition function</i>
  "app"
], function(App) {
  // The "app" dependency is passed in as "App"
  // Again, the other dependencies passed in are not "AMD" therefore don't pass a parameter to this function
  App.initialize();
});
require.config({
  waitSeconds: 500,
  paths: {
    jquery: "libs/jquery/jquery",
    jqueryCookie: "libs/jquery/jquery.cookie",
    .....
  },

  shim: {
    jqxcore: {
      export: "$",
      deps: ["jquery"]
    },
    jqxbuttons: {
      export: "$",
      deps: ["jquery", "jqxcore"]
    }
    ............
  }
});

require([
 <i> // Load our app module and pass it to our definition function</i>
  "app"
], function(App) {
  // The "app" dependency is passed in as "App"
  // Again, the other dependencies passed in are not "AMD" therefore don't pass a parameter to this function
  App.initialize();
});
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文