Laden von Backbone und Unterstrich mit RequireJS


172

Ich versuche, Backbone und Underscore (sowie jQuery) mit RequireJS zu laden. Mit den neuesten Versionen von Backbone und Underscore scheint es etwas schwierig zu sein. Zum einen registriert sich Underscore automatisch als Modul, Backbone geht jedoch davon aus, dass Underscore global verfügbar ist. Ich sollte auch beachten, dass Backbone sich nicht als Modul zu registrieren scheint, was es irgendwie inkonsistent mit den anderen Bibliotheken macht. Dies ist die beste main.js, die ich mir vorstellen kann:

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

Ich sollte erwähnen, dass der Optimierer daran erstickt, während es funktioniert. Ich erhalte folgendes:

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

Gibt es eine bessere Möglichkeit, damit umzugehen? Vielen Dank!


Hast du es mit einem Tutorial gemacht?
Kaha

1
Ich habe verschiedene Tutorials wie backbonetutorials.com/organizing-backbone-using-modules durchgesehen, aber sie scheinen jetzt mit den neuesten Versionen von Unterstrich und Backbone veraltet zu sein.
Aaronius

Ich fand es auch schwierig, Anforderungen mit anderen Bibliotheken zu verwenden und umgekehrt. Deshalb habe ich eine Bibliothek erstellt, die viel einfacher zu bedienen ist und mit Winkel getestet wird. Unten befindet sich eine Demo-Anwendung: gngeorgiev.github.io/Modulerr.js Sie können auch alle Skripte zu einem kombinieren, ohne von Modulerr.js abhängig zu sein
Georgi-it

Übrigens Synchronous Asynchronous Module Definition ist ein bisschen Oxymoron :)
Strajk

Ha! Guter Punkt. Bearbeitet.
Aaronius

Antworten:


294

RequireJS 2.X adressiert jetzt mithilfe der neuen shimKonfiguration organisch Nicht-AMD-Module wie Backbone & Underscore viel besser .

Die shimKonfiguration ist einfach zu verwenden: (1) Man gibt die Abhängigkeiten ( deps) an, falls vorhanden (die aus der pathsKonfiguration stammen oder selbst gültige Pfade sein können). (2) Geben Sie (optional) den globalen Variablennamen aus der Datei an, die Sie shimmen, die in Ihre Modulfunktionen exportiert werden soll, die dies erfordern. (Wenn Sie die Exporte nicht angeben, müssen Sie nur die globale Funktion verwenden, da nichts an Ihre Funktionen zum Anfordern / Definieren übergeben wird.)

Hier ist ein einfaches Beispiel für shimdas Laden von Backbone. Es wird auch ein Export für den Unterstrich hinzugefügt, obwohl keine Abhängigkeiten vorhanden sind.

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

});

Hinweis: Bei diesem vereinfachten Code wird davon ausgegangen, dass sich jquery, backbone und underscore in Dateien mit den Namen "jquery.js", "backbone.js" und "underscore.js" im selben Verzeichnis wie dieser "main" -Code befinden (der zur Basis-URL für require wird ). Ist dies nicht der Fall, müssen Sie eine Pfadkonfiguration verwenden .

Ich persönlich denke, dass mit der integrierten shimFunktionalität die Vorteile, keine gegabelte Version von Backbone & Underscore zu verwenden, die Vorteile der Verwendung der AMD-Gabel überwiegen, die in der anderen gängigen Antwort empfohlen wird, aber in beiden Fällen funktioniert.


Sollte dieser Code mit Sample RequireJS 2.0.1 + jQuery 1.7.2 project requirejs.org/docs/download.html#samplejquery verwendet werden ?
Henry

Wenn ich dich richtig verstehe, Henry, fragst du, ob Shim für $ Plugins notwendig ist. Dies ist nicht der Fall, wenn Sie die kombinierte Datei require-jquery.js aus diesem Beispielprojekt verwenden. Dies liegt daran, dass mit der kombinierten Datei jquery synchron mit require geladen wird, sodass jquery garantiert geladen wird, wenn Sie versuchen, $ plugins in einem beliebigen Modul zu verwenden. In diesem Fall können Sie, wenn Sie $ plugins verwenden möchten, diese einfach in Ihre Abhängigkeitsliste aufnehmen, als wären sie AMD, auch wenn dies nicht der Fall ist. Dies ist definitiv eine Ausnahme von der Regel, und im Allgemeinen benötigen Sie Shim für alle Nicht-AMD-Module.
Ben Roberts

Beachten Sie, dass die Shim-Cofiguration mit diesem Beispielprojekt kompatibel ist und zum Hinzufügen anderer Nicht-AMD-Bibliotheken verwendet werden kann.
Ben Roberts

11
Ich dachte nur, ich würde erwähnen, dass dies wirklich der richtige Weg ist. Ich wünschte, ich könnte +50 Upvotes geben, damit es die Antwort Nr. 1 wird.
Koblas

Die Methode in dieser Antwort sah vielversprechend aus, funktionierte aber bei mir nicht. Ich habe stattdessen gist.github.com/2517531 verwendet, was gut funktioniert hat.
Rob W

171

Update : Ab Version 1.3.0 hat Underscore die AMD-Unterstützung (RequireJS) entfernt .

Sie können die Gabel amdjs / Backbone 0.9.1 und amkjs / Underscore 1.3.1 mit AMD-Unterstützung von James Burke (dem Betreuer von RequireJS) verwenden.

Weitere Informationen zur AMD-Unterstützung für Underscore und 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();
    });
});

Die Module sind ordnungsgemäß registriert und das Bestell-Plugin ist nicht erforderlich:

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

Unterstrich ist eigentlich optional, da Backbone seine Abhängigkeiten jetzt selbstständig erhält:

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

Mit etwas AMD-Zucker könnte man es auch so schreiben:

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

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

Bezüglich des Optimierungsfehlers: Überprüfen Sie Ihre Build-Konfiguration. Ich gehe davon aus, dass Ihre Pfadkonfiguration deaktiviert ist. Wenn Sie ein Verzeichnis eingerichtet haben, das den RequireJS-Dokumenten ähnelt, können Sie Folgendes verwenden:

// 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
Genau das habe ich gesucht. Danke dir! Tolle detaillierte Antwort. Es läuft jetzt so, wie Sie es beschrieben haben.
Aaronius

2
+1 genaue, funktionierende und aktualisierte Antwort + Beispiele. exzellente Arbeit Riebel, du hast mir geholfen, und ich bin sicher, andere sehr.
Ken

22
Super-Bonus für die Aktualisierung lange nach dem ursprünglichen Beitrag.
Aaronius

Tolle Antwort @Riebel! Es war wirklich nützlich für mich. Übrigens würde ich auch empfehlen, sich volo anzuschauen . Es ist eine Bibliothek, die von jrburke (dem Ersteller von requirejs) erstellt wurde, um Abhängigkeiten von github abzurufen. Zum Beispiel wird die AMD-Version des Unterstrichs
abgerufen,


4

Gute Nachrichten, Underscore 1.6.0 unterstützt jetzt requirejs define !!!

Versionen darunter erfordern Shims oder Underscore.js und hoffen dann blind, dass die globale Variable "_" nicht zerschlagen wurde (was fair ist, ist eine faire Wette).

Laden Sie es einfach von

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

4

Ich werde direkt aufschreiben, Sie können die Erklärung auf requirejs.org lesen, Sie könnten den folgenden Code als Ausschnitt für Ihren täglichen Gebrauch verwenden; (ps ich benutze yeoman) (da viele Dinge aktualisiert wurden, poste ich dies ab Februar 2014.)

Stellen Sie sicher, dass Sie ein Skript in Ihre index.html aufgenommen haben

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

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

Ich hoffe ich war nützlich.!


1
Nützlicher als Sie wissen würden. Genau das habe ich versucht, auf einem meiner Projekte, bower_components und allem, aufzubauen. Danke @STEEL
Dwight Spencer

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();
});
Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.