2012-02-15 22 views
26

Soy bastante nuevo en RequireJS y me he encontrado con un pequeño problema. He escrito un pequeño framework basado en Backbone usando RequireJS y quiero que sea reutilizable en diferentes proyectos. Entonces, con algunas búsquedas, aprendí que requerir permite paquetes. Esto parecía lo que estaba buscando. Tengo un archivo main.js para poner en marcha mi aplicación que básicamente es el siguiente:Rutas relativas con módulos/paquetes RequireJS

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

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

Luego, en el mismo directorio que mis main.js tengo otro directorio llamado "marco", que contiene otro main.js que se ve de esta manera:

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

En la búsqueda encontré this page lo que indica que el argumento 'require' debe estar al alcance al submódulo. Sin embargo, cuando trato de exigir cosas, siguen siendo relativos a mi main.js. Intenté varias cosas y busqué durante horas en vano. ¿Hay alguna forma en que pueda tener mis llamadas requerir/definir dentro de mi paquete incluido en relación con main.js en su raíz?

Respuesta

50

es necesario definir el submódulo como un paquete en la configuración requiere:

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

para cargar el módulo sólo tiene que utilizar su 'nombrepaquete' en los requisitos:

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

En su paquete debe utilizar el prefijo ./ para cargar sus archivos relativos a su submódulo:

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

Hay un atajo útil: Si el nombre del paquete es igual a su ubicación y su archivo principal se llama '' main.js, entonces se puede sustituir este

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

a esto:

packages: ['packagename'] 

Por lo que puedo ver, usted ya intentó definir un paquete, pero ¿también utilizó el prefijo ./? Sin este prefijo, se intentará encontrar los archivos en su ruta de acceso raíz global. Y sin un paquete, ./ será inútil porque la ruta relativa es la misma que la ruta raíz global.


Saludos

+3

¿Esto todavía permite que el paquete realice su propia llamada a require.config() y defina su propia lista de alias de ruta, siempre y cuando los archivos de referencia de los alias comiencen con './'? No quiero tener que usar la ruta relativa completa a todos los archivos, cada vez que los referencia con un define(). Desde entonces he reestructurado todo el proyecto, pero aún tengo curiosidad. –

+0

Sé que esta respuesta está un poco anticuada, pero últimamente, puede usar rutas de acceso relativas para requerir módulos incluso sin paquetes. – hayavuk

+0

Para referencia: http://requirejs.org/docs/api.html#packages – Skarllot

2

Esto funcionó para mí, la adición de un prefijo "./" a los nombres de los módulos:

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

Gracias por la respuesta. El './' funcionó para cargar esos dos componentes, pero supongo que no hice un gran trabajo explicando la pregunta (sobre todo porque no creo haber entendido completamente la pregunta en el momento en que publiqué) . Realmente mi problema se redujo a, ¿cómo puedo definir las rutas con require.config() que se pueden usar tanto desde el contexto del framework como sin él, pero que aún incluyen el mismo archivo? Puede que haya una solución mejor para lo que intento hacer, pero al menos tengo algo que funciona ahora. ¡Gracias de nuevo! –

5

me di cuenta de la respuesta a mi pregunta, y la solución (que no eran los mismos aparentemente). Supongo que lo publicaré aquí en caso de que pueda ayudar a alguien más en el futuro.

Esencialmente, lo que quería era cargar mi marco dentro de su propio contexto. Encontré la opción de contexto bajo el configuration section en el sitio web de require y un example of how to use it. Originalmente probé esto haciendo algo como:

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

Hubo dos problemas con esto. Primero, mi variable 'req' se definía fuera del marco, pero quería que el marco definiera sus propias rutas. Y segundo, cada vez que un archivo fuera del marco requeriría un archivo dentro del marco, que a su vez requeriría 'jQuery', por ejemplo, entonces jQuery (o lo que sea) no sería necesario desde el contexto de la instancia del marco de require y por lo tanto no pudo encontrar el archivo.

Lo que terminé haciendo fue definiendo main.js de mi marco a ser algo como esto:

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

Y luego, en main.js de mi archivo de proyecto que acabo de hacer esto:

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

Esto toma todo lo que se transfiere al método initialize() de framework para 'baseURL' y lo antepone a cualquier ruta definida por el framework que no comience con una barra inclinada o 'anything: //', a menos que sean rutas de anulación. Esto permite que el paquete que utiliza el marco anule cosas como 'jQuery'.

1

Un proceso que funcionó bien para mí para permitir que un paquete con submódulos para utilizarse directamente a partir de datos-principal o desde un marco exterior, suponiendo que un main.js (u otro paquete principal) es llamado por un nombre particular, era usar var baseUrl = require.toUrl('packageName') + '/../' como un prefijo a un archivo de configuración require.config({ paths: { ... } }). Por ejemplo:

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

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

El ajuste de context: "xxx" funcionó bien para llamar módulos normales con ./modName pero no funcionó para el argumento paths para mí.

+1

Esto no es muy claro, pero resolvió mi problema de carga de applet local. ¡Gracias! – Madwyn

Cuestiones relacionadas