使用RequireJS加载主干和下划线


172

我正在尝试使用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

有没有更好的方法来解决这个问题?谢谢!


您是否使用任何教程来完成?
卡哈2011年

1
我翻阅了各种教程,如beltonetutorials.com/organizing-backbone-using-modules,但现在它们的最新版本的下划线和主干似乎已经过时了。
亚罗尼乌斯(Aaronius)2011年

我还发现requirejs很难与其他库一起使用,反之亦然。这就是为什么我创建了一个易于使用且经过角度测试的库的原因。底部有一个演示应用程序:gngeorgiev.github.io/Modulerr.js您还可以将所有脚本合并为一个脚本,而无需依赖Modulerr.js
Georgi-it

btw同步异步模块定义有点矛盾:)
Strajk 2014年

哈!好点子。编辑。
亚罗尼厄斯(Aaronius)2014年

Answers:


294

现在,RequireJS 2.X使用新shim配置可以更好地有机解决非AMD模块,例如Backbone&Underscore 。

shim配置易于使用:(1)声明依赖项(deps)(如果有)(可能来自paths配置,也可能是有效路径本身)。(2)(可选)从要填充的文件中指定全局变量名称,该名称应导出到需要它的模块函数中。(如果不指定导出,则只需使用全局变量,因为任何内容都不会传递到require / define函数中。)

这是shim加载Backbone的一个简单示例用法。即使没有任何依赖性,它也会为下划线添加导出。

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,bone和underscore位于与此“ main”代码相同的目录下的名为“ jquery.js”,“ backbone.js”和“ underscore.js”的文件中(这成为require的baseURL )。如果不是这种情况,则需要使用path config

我个人认为,使用内置shim功能,不使用分叉版本的Backbone&Underscore的优势要胜过使用另一个流行答案中推荐的AMD叉型的优势,但是无论哪种方式都可以。


该代码是否应与Sample RequireJS 2.0.1 + jQuery 1.7.2 project requirejs.org/docs/download.html#samplejquery一起使用?
亨利

亨利,如果我对您的理解正确,您是在问$插件是否需要填充垫片。如果您使用了该示例项目中的组合require-jquery.js文件,则不是。这是因为在合并的文件中,jquery与require同步加载,因此可以保证在尝试在任何模块中使用$插件时都将加载jquery。在这种情况下,当您要使用$插件时,即使它们不是AMD,也可以将它们包括在依赖项列表中,就好像它们是AMD一样。这绝对是该规则的一个例外,通常,对于任何非AMD模块,都需要填充垫片。
Ben Roberts 2012年

请注意,匀场配置与该示例项目兼容,可以用于添加其他非AMD库。
本·罗伯茨

11
只是以为我会提到这确实是要走的路,希望我能给+50投票,使它成为第一答案。
koblas 2012年

这个答案中的方法看起来很有希望,但对我不起作用。我改用gist.github.com/2517531,效果很好。
罗布W

171

更新:从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 Docs类似目录设置,则可以使用:

// 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"
        }
    ]
})

4
那正是我想要的。谢谢!很好的详细答案。正如您所描述的,它现在正在运行。
亚罗尼乌斯(Aaronius)2011年

2
+1准确,有效和更新的答案+示例。里贝尔(Riebel)的出色工作,您为我提供了帮助,而且我敢肯定,其他人也会很多。

22
超级奖励,用于在原始帖子发布很长时间后保持此更新。
亚罗尼厄斯

好答案@Riebel!对我来说真的很有用。顺便说一句,我也建议看看volo。这是由jrburke(requirejs的创建者)创建的库,用于从github检索依赖项。例如,只需输入以下内容即可获取下划线的amd版本:volo add underscore
txominpelu 2012年


4

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

低于此版本的版本需要填充,或者需要underscore.js,然后盲目地希望“ _”全局变量未被粉碎(公平地说是合理的选择)

只需通过加载它

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

4

我将直接写下来,您可以阅读requirejs.org上的说明,可以将以下代码用作日常使用的代码段;(PS我使用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;
});

我希望我有用。


1
比您知道的有用。这正是我试图在我的项目,bower_components和所有项目上构建的。感谢@STEEL
德怀特·斯潘塞

0
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();
});
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.