2011-11-15 21 views
171

Sto provando a caricare Backbone e Underscore (oltre a jQuery) con RequireJS. Con le ultime versioni di Backbone e Underscore, sembra un po 'complicato. Per uno, Underscore si registra automaticamente come un modulo, ma Backbone presuppone che Underscore sia disponibile globalmente. Dovrei anche notare che Backbone non sembra registrarsi come un modulo che lo rende un po 'incoerente con le altre librerie. Questo è il miglior main.js ho potuto venire con che funziona:Caricamento Backbone e Underscore utilizzando RequireJS

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 si lavora, l'ottimizzatore soffoca su di esso. 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!

+0

Lo hai fatto utilizzando un tutorial? – kaha

+1

Ho esaminato varie esercitazioni come http://backbonetutorials.com/organizing-backbone-using-modules/ ma sembrano ormai obsolete con le ultime versioni di underscore e backbone. – Aaronius

+0

Ho trovato anche requirejs difficile da usare con altre librerie e viceversa. Questo è il motivo per cui ho creato una libreria che è molto più facile da usare ed è testata con angolari. C'è una demo application in basso: http://gngeorgiev.github.io/Modulerr.js/ Puoi anche combinare tutti gli script in uno senza la dipendenza da Modulerr.js –

risposta

292

RequireJS 2.X ora affronta organicamente i moduli non-AMD, come Backbone & sottolineatura molto meglio, utilizzando la nuova configurazione shim.

La configurazione shim è semplice da usare: (1) si afferma dipendenze (deps), se presente, (che può essere dalla configurazione paths, o possono essere percorsi validi stessi). (2) (facoltativamente) specifica il nome della variabile globale dal file che stai shimming, che deve essere esportato nelle funzioni del modulo che lo richiedono. (Se non si specificano le esportazioni, sarà necessario utilizzare semplicemente il globale, poiché nulla verrà passato nelle funzioni di richiesta/definizione.)

Ecco un semplice esempio di utilizzo di shim per caricare Backbone. Aggiunge anche un'esportazione per il carattere di sottolineatura, anche se non ha alcuna dipendenza.

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, spina dorsale e Underscore sono in file denominati "jquery.js", "backbone.js" e "underscore.js" nella stessa directory come questo " codice "principale (che diventa baseURL per richiedere).Se questo non è il tuo caso, dovrai usare uno paths config.

Personalmente penso che con il built-in shim funzionalità, i vantaggi di non utilizzando una versione biforcuta di Backbone & sottolineatura superano i vantaggi di utilizzare la forcella AMD raccomandato nel altra risposta popolare, ma in entrambi i casi funziona.

+0

Questo codice dovrebbe essere usato con 'Sample RequireJS 2.0.1 + jQuery 1.7.2 project' http://requirejs.org/docs/download.html#samplejquery? – Henry

+0

Se ti capisco bene, Henry, stai chiedendo se lo shim è necessario per $ plugin. Non lo è, SE si utilizza il file require-jquery.js combinato da quel progetto di esempio.Questo perché con il file combinato, jquery viene caricato in modo sincrono con require, quindi jquery è garantito per essere caricato dal momento in cui si tenta di utilizzare qualsiasi $ plugin in qualsiasi modulo. In questo caso, quando si desidera utilizzare $ plugins, è possibile includerli nell'elenco delle dipendenze come se fossero AMD, anche se non lo sono. Questa è sicuramente un'eccezione alla regola, e in generale avrete bisogno di shim per qualsiasi modulo non AMD. –

+0

Si noti che la cofigurazione dello spessore è compatibile con quel progetto di esempio e potrebbe essere utilizzata per aggiungere altre librerie non AMD. –

171

Aggiornamento: A partire dalla versione 1.3.0 Underscore removed AMD (RequireJS) support.

È possibile utilizzare il amdjs/Backbone 0.9.1 e la forcella amdjs/Underscore 1.3.1 con supporto AMD da James Burke (il manutentore di RequireJS).

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

I moduli sono correttamente registrati e non v'è alcuna necessità per il plugin ordine:

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

sottolineatura è in realtà facoltativa, perché Backbone ora prende le sue dipendenze sul proprio:

// 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 AMD sugar si potrebbe anche scrivere 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 
     } 
    }; 
}); 

Riguardo all'errore dell'ottimizzatore: doublecontrollare la configurazione della build. Presumo che la configurazione del tuo percorso sia disattivata. Se si dispone di un directory setup similar to the RequireJS Docs è 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 dettagliata pure. Ora funziona come hai descritto. – Aaronius

+2

+1 risposta, lavoro e risposta aggiornati + esempi. ottimo lavoro Riebel, mi hai aiutato, e sono sicuro che gli altri, molto. – Ken

+22

Super-bonus per mantenere questo aggiornamento molto tempo dopo il post originale. – Aaronius

3

Buone notizie, Underscore 1.6.0 ora supporta requirejs define !!!

versioni inferiori a questo richiedono spessori, o che richiedono underscore.js poi alla cieca sperando che il "_" variabile globale hasn t stato frantumato (che ad essere sinceri è una scommessa equa)

semplicemente caricarla in da

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

Scriverò direttamente, puoi leggere la spiegazione su requirejs.org, potresti usare sotto il codice come frammento per il tuo uso quotidiano; (Ps io uso Yeoman) (dal momento che molte cose aggiornati, im postando questo come di febbraio 2014.)

Assicurati incluso script nella vostra index.html

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

Poi, 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 essere stato utile.!

+1

Più utile di quanto si possa sapere. Questo è esattamente quello che ho cercato di costruire su un mio progetto, bower_components e tutti. Grazie a @STEEL –

+0

contento di sapere :) – 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(); 
}); 
Problemi correlati