2012-02-15 15 views
26

Sono abbastanza nuovo su RequireJS e ho avuto un po 'di problemi. Ho scritto un piccolo framework basato su Backbone usando RequireJS e voglio che sia riutilizzabile in diversi progetti. Così, con alcune ricerche ho imparato che richiedono pacchetti. Questo sembrava quello che stavo cercando. Ho un file main.js per lanciare la mia app che appare essenzialmente come questo:Percorsi relativi con moduli/pacchetti RequireJS

require.config({ 
    packages: ['framework'] 
}); 

require(['framework'], function(framework) { 
    framework.createDash(); 
}); 

Poi nella stessa directory come i miei main.js ho un altro directory chiamata "quadro", che contiene un altro che guarda main.js in questo modo:

define(function(require, exports, module) { 
    exports.createDash = function(dash, element) { 
    require(['dash/dash.model', 'dash/dash.view'], function(DashModel, DashView) { 
     return new DashView({ 
     model: new DashModel(dash), 
     el: element ? element : window 
     }); 
    }); 
    }; 
}); 

Nella ricerca ho trovato this page che indica che l'argomento 'require' ambito dovrebbe essere al modulo. Tuttavia, quando provo a richiedere le cose sono ancora relative al mio main.js.originale Ho provato una serie di cose e cercato per ore senza successo. C'è un modo in cui posso avere il mio richiedere/definire le chiamate all'interno del mio pacchetto incluso rispetto al main.js nella sua radice?

risposta

50

è necessario definire il vostro modulo come pacchetto nella configurazione richiede:

require.config({ 
    packages: [ 
    { name: 'packagename', 
     location: 'path/to/your/package/root', // default 'packagename' 
     main: 'scriptfileToLoad'    // default 'main' 
    }] 
    ... some other stuff ... 
}); 

per caricare il modulo è sufficiente utilizzare il 'packagename' ai requisiti:

define(['jquery', 'packagename'], function($, MyPackage) { 
    MyPackage.useIt() 
}); 

Nella tua pacchetto è necessario utilizzare il prefisso ./ per caricare i file relativi al sottomodulo:

define(['globalDependency', './myLocalFile'], function(Asdf, LocalFile) { 
    LocalFile.finallyLoaded(); 
}); 

V'è una utile scorciatoia: se il nome del pacchetto è uguale alla tua posizione e il file principale si chiama 'main.js', allora si può sostituire questo

packages: [ 
    { name: 'packagename', 
     location: 'packagename', 
     main: 'main' 
    }] 

a questo:

packages: ['packagename'] 

Per quanto posso vedere, hai già provato a definire un pacchetto ma hai usato anche il prefisso ./? Senza questo prefisso require tenterà di trovare i file nel suo percorso root globale. E senza un pacchetto, ./ sarà inutile perché il percorso relativo è uguale al percorso radice globale.


Acclamazioni

+3

Permette comunque al pacchetto di rendere la propria chiamata separata a require.config() e definire il proprio elenco di alias del percorso, a patto che i file alias dei riferimenti inizino con "./"? Non voglio dover utilizzare il percorso relativo completo a tutti i file, ogni volta che li riferimento con un define(). Da allora ho ristrutturato l'intero progetto, ma sono ancora curioso. –

+0

So che questa risposta è un po 'datata, ma ultimamente, puoi tranquillamente usare percorsi relativi per richiedere moduli anche senza pacchetti. – hayavuk

+0

Per riferimento: http://requirejs.org/docs/api.html#packages – Skarllot

2

questo ha funzionato per me, l'aggiunta di un prefisso "./" ai nomi di modulo:

define(function (require, exports, module) { 
    exports.createDash = function (dash, element) { 
     require([ './dash/dash.model', './dash/dash.view' ], function (DashModel, DashView) { 
      return new DashView({ 
       model : new DashModel(dash), 
       el : element ? element : window 
      }); 
     }); 
    }; 
}); 
+0

Grazie per la risposta. Il "./" ha funzionato per caricare quei due componenti, ma suppongo di non aver fatto un ottimo lavoro spiegando la domanda (principalmente perché non penso di aver compreso appieno la domanda nel momento in cui ho postato) . Davvero il mio problema è venuto a, come posso definire i percorsi con require.config() che può essere utilizzato da entrambi all'interno del contesto quadro e senza, ma include ancora lo stesso file? Potrebbe esserci una soluzione migliore là fuori per quello che sto cercando di fare, ma almeno ho qualcosa che funziona ora. Grazie ancora! –

5

ho capito la risposta alla mia domanda, e la soluzione (non erano la stessa apparentemente). Immagino che lo posterò qui nel caso in cui possa aiutare qualcun altro in futuro.

Essenzialmente quello che volevo era caricare il mio framework nel suo contesto. Ho trovato l'opzione di contesto sotto lo configuration section sul sito Web di require e uno example of how to use it. Inizialmente ho provato questo facendo qualcosa come:

var req = require.config({ 
    baseUrl: 'framework', 
    context: 'framework', 

    paths: { 
     jQuery: 'lib/jquery/jquery-1.7.min.js', 
     Underscore: 'lib/underscore/underscore.min.js', 
     Backbone: 'lib/backbone/backbone.min.js', 
     etc... 
    } 
}); 

req(['main'], function() {}); 

Ci sono stati due problemi con questo. Primo, la mia variabile 'req' veniva definita al di fuori del framework, ma volevo che il framework definisse i propri percorsi. E secondo, ogni volta che un file al di fuori del framework richiederebbe un file all'interno del framework, che a sua volta richiederebbe 'jQuery', per esempio, quindi jQuery (o qualsiasi altra cosa) non sarebbe richiesto all'interno del contesto dell'istanza del framework di richiedere e quindi non è stato in grado di trovare il file.

Quello che ho finito per fare stava definendo main.js del mio quadro di simile a questa:

var paths = { 
    jQuery: 'lib/jquery/jquery-1.7.min.js', 
    Underscore: 'lib/underscore/underscore.min.js', 
    Backbone: 'lib/backbone/backbone.min.js', 
    etc... 
}; 

define(function() { 
    var exports = {}; 

    exports.initialize = function(baseUrl, overridePaths, callback) { 
     if(!overridePaths) { 
     overridePaths = {}; 
     } 
     if(baseUrl && baseUrl[baseUrl.length - 1] != '/') { 
      baseUrl = baseUrl + '/'; 
     } 

     var fullpaths = {}; 
     for(var path in paths) { 
      // Don't add baseUrl to anything that looks like a full URL like 'http://...' or anything that begins with a forward slash 
      if(paths[path].match(/^(?:.*:\/\/|\/)/)) { 
       fullpaths[path] = paths[path]; 
      } 
      else { 
       fullpaths[path] = baseUrl + paths[path]; 
      } 
     } 

     var config = {paths: fullpaths}; 
     for(var pathName in overridePaths) { 
      config.paths[pathName] = overridePaths[pathName]; 
     } 
     require.config(config); 

     // Do anything else you need to do such as defining more functions for exports 

     if(callback) { 
      callback(); 
     } 
    } 

    return exports; 
}); 

E poi nel main.js del mio file di progetto ho solo fare questo:

require(['framework/main'], function(framework) { 
    // NOTE: This setTimeout() call is used because, for whatever reason, if you make 
    //  a 'require' call in here or in the framework without it, it will just hang 
    //  and never actually go fetch the files in the browser. There's probably a 
    //  better way to handle this, but I don't know what it is. 
    setTimeout(function() { 
     framework.initialize('framework', null, function() { 
      // Do stuff here 
     } 
    }, 0); 
}); 

Questo prende tutto ciò che viene passato al metodo initialize() del framework per 'baseURL' e lo antepone a qualsiasi percorso definito dal framework che non inizia con una barra o 'nulla: //', a meno che non siano percorsi di override. Ciò consente al pacchetto di utilizzare il framework per sovrascrivere cose come 'jQuery'.

1

Un processo che funzionava bene per me per consentire ad un pacchetto con sottomoduli essere utilizzata direttamente da dati principale o da una struttura esterna, supponendo che un main.js (o altro pacchetto principale) è chiamato con un nome particolare, doveva usare var baseUrl = require.toUrl('packageName') + '/../' come prefisso per un file di configurazione require.config({ paths: { ... } }). Per esempio:

var music21Base = require.toUrl('music21') + '/../'; 

require.config({ paths: { 
          'jquery': music21Base + 'ext/jquery/jquery.2.1.10.min'; 
          'subModuleLoader': music21Base + 'src/subModuleLoader'; 
         } }); 

L'impostazione di context: "xxx" ha funzionato bene per i moduli di chiamata normali con ./modName, ma non ha funzionato per l'argomento paths per me.

+1

Questo non è molto accurato, ma ha risolto il problema del caricamento dell'applet locale. Grazie! – Madwyn