Chargement de la colonne vertébrale et du trait de soulignement à l'aide de RequireJS


172

J'essaye de charger Backbone et Underscore (ainsi que jQuery) avec RequireJS. Avec les dernières versions de Backbone et Underscore, cela semble assez délicat. D'une part, Underscore s'enregistre automatiquement en tant que module, mais Backbone suppose que Underscore est disponible dans le monde entier. Je dois également noter que Backbone ne semble pas s'enregistrer en tant que module, ce qui le rend un peu incompatible avec les autres bibliothèques. C'est le meilleur main.js que j'ai pu trouver qui fonctionne:

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

Je dois mentionner que, pendant que cela fonctionne, l'optimiseur s'étouffe dessus. Je reçois ce qui suit:

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

Y a-t-il une meilleure façon de gérer cela? Merci!


L'avez-vous fait à l'aide d'un tutoriel?
kaha

1
J'ai parcouru divers tutoriels comme backbonetutorials.com/organizing-backbone-using-modules, mais ils semblent maintenant obsolètes avec les dernières versions de soulignement et de backbone.
Aaronius

J'ai également trouvé requirejs difficile à utiliser avec d'autres bibliothèques et vice-versa. C'est pourquoi j'ai créé une bibliothèque qui est beaucoup plus facile à utiliser et qui est testée avec angular. Il y a une application de démonstration en bas: gngeorgiev.github.io/Modulerr.js Vous pouvez également combiner tous les scripts en un seul sans la dépendance à Modulerr.js
Georgi-it

btw La définition du module asynchrone synchrone est un peu oxymore :)
Strajk

Ha! Bon point. Édité.
Aaronius

Réponses:


294

RequireJS 2.X s'adresse désormais de manière organique aux modules non AMD tels que Backbone et Underscore, en utilisant la nouvelle shimconfiguration.

La shimconfiguration est simple à utiliser: (1) on énonce les dépendances ( deps), s'il y en a, (qui peuvent provenir de la pathsconfiguration, ou peuvent être des chemins valides eux-mêmes). (2) (facultativement) spécifiez le nom de la variable globale du fichier que vous copiez, qui doit être exporté vers les fonctions de votre module qui en ont besoin. (Si vous ne spécifiez pas les exportations, vous devrez simplement utiliser le global, car rien ne sera passé dans vos fonctions require / define.)

Voici un exemple simple d'utilisation de shimpour charger Backbone. Il ajoute également une exportation pour le trait de soulignement, même s'il n'a aucune dépendance.

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

});

Remarque: ce code simplifié suppose que jquery, backbone et underscore sont dans des fichiers nommés "jquery.js", "backbone.js" et "underscore.js" dans le même répertoire que ce code "main" (qui devient l'URL de base pour require ). Si ce n'est pas le cas, vous devrez utiliser une configuration de chemins .

Personnellement, je pense qu'avec la shimfonctionnalité intégrée, les avantages de ne pas utiliser une version fourchue de Backbone & Underscore l'emportent sur les avantages d'utiliser le fork AMD recommandé dans l'autre réponse populaire, mais dans les deux cas, cela fonctionne.


Ce code doit-il être utilisé avec Sample RequireJS 2.0.1 + jQuery 1.7.2 project requirejs.org/docs/download.html#samplejquery ?
Henry

Si je vous comprends bien, Henry, vous demandez si le shim est nécessaire pour les plugins $. Ce n'est pas le cas, SI vous utilisez le fichier combiné require-jquery.js de cet exemple de projet. En effet, avec le fichier combiné, jquery est chargé de manière synchrone avec require, donc jquery est garanti d'être chargé au moment où vous essayez d'utiliser des plugins $ dans n'importe quel module. Dans ce cas, lorsque vous souhaitez utiliser des plugins $, vous pouvez simplement les inclure dans votre liste de dépendances comme s'ils étaient AMD, même s'ils ne le sont pas. C'est définitivement une exception à la règle, et généralement vous aurez besoin de shim pour tous les modules non AMD.
Ben Roberts

Notez que la cofiguration shim est compatible avec cet exemple de projet et peut être utilisée pour ajouter d'autres bibliothèques non AMD.
Ben Roberts

11
Je pensais juste que je mentionnerais que c'est vraiment la voie à suivre, j'aimerais pouvoir donner +50 votes positifs pour que ce soit la réponse n ° 1.
koblas

La méthode de cette réponse semblait prometteuse, mais n'a pas fonctionné pour moi. J'ai utilisé gist.github.com/2517531 à la place, ce qui a bien fonctionné.
Rob W

171

Mise à jour : à partir de la version 1.3.0, Underscore a supprimé le support AMD (RequireJS) .

Vous pouvez utiliser amdjs / Backbone 0.9.1 et le fork amdjs / Underscore 1.3.1 avec le support AMD de James Burke (le mainteneur de RequireJS).

Plus d'informations sur la prise en charge d'AMD pour Underscore et 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();
    });
});

Les modules sont correctement enregistrés et il n'y a pas besoin du plugin de commande:

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

Le soulignement est en fait facultatif, car Backbone obtient désormais ses propres dépendances:

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

Avec du sucre AMD, vous pouvez également l'écrire comme ceci:

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

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

Concernant l'erreur de l'optimiseur: revérifiez votre configuration de construction. Je suppose que la configuration de votre chemin est désactivée. Si vous avez une configuration de répertoire similaire à RequireJS Docs, vous pouvez utiliser:

// 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
C'est exactement ce que je cherchais. Je vous remercie! Excellente réponse détaillée également. Il fonctionne maintenant comme vous l'avez décrit.
Aaronius

2
+1 réponse précise, fonctionnelle et mise à jour + exemples. excellent travail Riebel, vous m'aidez, et je suis sûr que d'autres, beaucoup.
Ken

22
Super-bonus pour garder cela mis à jour longtemps après la publication originale.
Aaronius

Bonne réponse @Riebel! Cela m'a été très utile. Btw, je recommanderais également de jeter un oeil à volo . C'est une bibliothèque créée par jrburke (le créateur de requirejs) pour récupérer les dépendances de github. Par exemple, la récupération de la version amd du trait de soulignement se fait simplement en tapant: volo add underscore
txominpelu


4

Bonne nouvelle, Underscore 1.6.0 prend désormais en charge requirejs define !!!

les versions inférieures à cela nécessitent des shims, ou nécessitent un underscore.js puis espèrent aveuglément que la variable globale "_" n'a pas été écrasée (ce qui pour être juste est un pari juste)

chargez-le simplement en

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

4

Je vais écrire directement, vous pouvez lire l'explication sur requirejs.org, vous pouvez utiliser le code ci-dessous comme un extrait pour votre usage quotidien; (ps j'utilise yeoman) (depuis beaucoup de choses mises à jour, je publie ceci à partir de février 2014.)

Assurez-vous d'avoir inclus le script dans votre index.html

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

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

J'espère que j'ai été utile.!


1
Plus utile que vous ne le pensez. C'est exactement ce que j'ai essayé de construire sur un de mes projets, bower_components et tout. Merci @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();
});
En utilisant notre site, vous reconnaissez avoir lu et compris notre politique liée aux cookies et notre politique de confidentialité.
Licensed under cc by-sa 3.0 with attribution required.