Caricamento di Backbone e Underscore mediante RequireJS


172

Sto cercando di caricare Backbone e Underscore (così come jQuery) con RequireJS. Con le ultime versioni di Backbone e Underscore, sembra un po 'complicato. Per uno, Underscore si registra automaticamente come modulo, ma Backbone presuppone che Underscore sia disponibile a livello globale. Dovrei anche notare che Backbone non sembra registrarsi come un modulo che lo rende in qualche modo incompatibile con le altre librerie. Questo è il miglior main.js che ho potuto inventare che funziona:

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

Devo dire che, mentre funziona, l'ottimizzatore lo soffoca. Ricevo quanto segue:

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

C'è un modo migliore di gestirlo? Grazie!


L'hai fatto usando qualche tutorial?
Kaha,

1
Ho esaminato vari tutorial come backbonetutorials.com/organizing-backbone-using-modules ma ora sembrano obsoleti con le ultime versioni di underscore e backbone.
Aaronio il

Ho anche trovato i requisiti difficili da usare con altre librerie e viceversa. Ecco perché ho creato una libreria che è molto più facile da usare ed è testata con angolare. C'è un'applicazione demo in fondo: gngeorgiev.github.io/Modulerr.js Puoi anche combinare tutti gli script in uno senza la dipendenza da Modulerr.js
Georgi-it

tra Synchronous Asynchronous Module Definition is kinda oxymoron :)
Strajk,

Ha! Buon punto. Modificato.
Aaronius,

Risposte:


294

RequireJS 2.X ora risolve molto meglio i moduli non AMD come Backbone e Underscore, usando il nuovoshim configurazione.

La shimconfigurazione è semplice da usare: (1) uno indica le dipendenze ( deps), se presenti, (che possono provenire dapaths configurazione o possono essere percorsi validi stessi). (2) (facoltativamente) specifica il nome della variabile globale dal file che stai scagliando, che dovrebbe essere esportato nelle funzioni del tuo modulo che lo richiedono. (Se non specifichi le esportazioni, dovrai semplicemente utilizzare il globale, poiché nulla verrà passato nelle tue funzioni di richiesta / definizione.)

Ecco un semplice esempio di utilizzo shimper caricare Backbone. Aggiunge inoltre un'esportazione per il carattere di sottolineatura, anche se non ha dipendenze.

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

});

Nota: questo codice semplificato presuppone che jquery, backbone e underscore siano nei file denominati "jquery.js", "backbone.js" e "underscore.js" nella stessa directory di questo codice "main" (che diventa il baseURL per richiedere ). In caso contrario, dovrai utilizzare una configurazione dei percorsi .

Personalmente penso con la shimfunzionalità integrata, i vantaggi di non utilizzare una versione biforcuta di Backbone e Underscore superano i vantaggi dell'utilizzo del fork AMD raccomandato nell'altra risposta popolare, ma in entrambi i casi funziona.


Questo codice deve essere utilizzato con Sample RequireJS 2.0.1 + jQuery 1.7.2 project requirejs.org/docs/download.html#samplejquery ?
Henry,

Se ti capisco correttamente, Henry, mi stai chiedendo se lo shim è necessario per $ plugin. Non lo è, SE si utilizza il file requisito-jquery.js combinato da quel progetto di esempio. Questo perché con il file combinato, jquery viene caricato in modo sincrono con request, quindi si garantisce che jquery venga caricato quando si tenta di utilizzare $ plugin in qualsiasi modulo. In questo caso, quando si desidera utilizzare $ plugin, è possibile includerli nell'elenco delle dipendenze come se fossero AMD, anche se non lo sono. Questa è sicuramente un'eccezione alla regola e generalmente avrai bisogno di shim per qualsiasi modulo non AMD.
Ben Roberts,

Notare che la cofigurazione shim è compatibile con quel progetto di esempio e potrebbe essere utilizzata per aggiungere altre librerie non AMD.
Ben Roberts,

11
Ho pensato di menzionare che questa è davvero la strada da percorrere, vorrei poter dare +50 voti per ottenere la risposta numero 1.
koblas,

Il metodo in questa risposta sembrava promettente, ma non ha funzionato per me. Ho usato invece gist.github.com/2517531 , che ha funzionato bene.
Rob W

171

Aggiornamento : dalla versione 1.3.0 Underscore ha rimosso il supporto AMD (RequireJS) .

Puoi usare amdjs / Backbone 0.9.1 e il fork amdjs / Underscore 1.3.1 con il supporto AMD di James Burke (il manutentore di RequireJS).

Ulteriori informazioni sul supporto AMD per Underscore e 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();
    });
});

I moduli sono registrati correttamente e non è necessario il plug-in dell'ordine:

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

Underscore è in realtà facoltativo, perché Backbone ora ottiene le sue dipendenze da solo:

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

Con un po 'di zucchero AMD potresti anche scriverlo in questo modo:

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

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

Per quanto riguarda l'errore di ottimizzazione: ricontrollare la configurazione della build. Presumo che la configurazione del tuo percorso sia disattivata. Se si dispone di un'impostazione di directory simile a Documenti RequireJS, è possibile utilizzare:

// 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
Questo è esattamente quello che stavo cercando. Grazie! Ottima risposta anche dettagliata. Ora funziona esattamente come hai descritto.
Aaronius,

2
+1 risposta accurata, funzionante e aggiornata + esempi. ottimo lavoro Riebel, mi hai aiutato, e ne sono certo altri, molto.
Ken,

22
Super-bonus per mantenere questo aggiornamento a lungo dopo il post originale.
Aaronio il

Ottima risposta @Riebel! Mi è stato davvero utile. A proposito, consiglierei anche di dare un'occhiata a volo . È una libreria creata da jrburke (il creatore di requirejs) per recuperare le dipendenze da Github. Ad esempio, il recupero della versione amd del carattere di sottolineatura avviene semplicemente digitando: volo aggiungi underscore
txominpelu


4

Buone notizie, Underscore 1.6.0 ora supporta Requisito Definisci !!!

le versioni sottostanti richiedono spessori o richiedono underscore.js sperando poi ciecamente che la variabile globale "_" non sia stata distrutta (che per essere onesti è una scommessa giusta)

caricalo semplicemente da

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

4

Scriverò direttamente, puoi leggere la spiegazione su requestjs.org, potresti usare il codice qui sotto come frammento per il tuo uso quotidiano; (ps io uso yeoman) (dal momento che molte cose sono state aggiornate, lo sto pubblicando da febbraio 2014.)

Assicurati di aver incluso lo script in index.html

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

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

Spero di esserti stato utile.!


1
Più utile di quanto potresti sapere. Questo è esattamente ciò che ho tentato di sviluppare su un mio progetto, bower_components e tutti. Grazie @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();
});
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.