2012-07-26 10 views
33

Actualmente estoy aprendiendo los fundamentos de RequireJS y tengo algunas preguntas con respecto a un perfil de compilación, archivos principales y el uso de RequireJS con proyectos de varias páginas.Cómo usar RequireJS build profile + r.js en un proyecto de varias páginas

estructura de directorios de mi proyecto es el siguiente:

 
httpdocs_siteroot/ 
    app/ 
     php files... 
    media/ 
     css/ 
      css files... 
     js/ 
      libs/ 
       jquery.js 
       require.js 
       mustache.js 
      mains/ 
       main.page1.js 
       main.page2.js 
       main.page3.js 
      plugins/ 
       jquery.plugin1.js 
       jquery.plugin2.js 
       jquery.plugin3.js 
      utils/ 
       util1.js 
       util2.js 
     images/ 

Dado que este proyecto no es una aplicación de una sola página, tengo un archivo principal independiente para cada página (aunque algunas páginas utilizan el mismo archivo principal).

Mis preguntas son:

  1. Es RequireJS incluso práctico para proyectos que no son de una sola página?

  2. Sin utilizar el optimizador, cada una de mis principales archivos empezar con esencialmente las mismas opciones de configuración:

    requirejs.config({ 
        paths: { 
        'jquery': 'http://ajax.googleapis.com/ajax/libs/jquery/1.7.2/jquery.min' 
        }, 
        baseUrl: '/media/js/', 
        // etc... 
    }); 
    require(['deps'], function() { /* main code */ }); 
    

    ¿Hay una manera de evitar esto? ¿Quiere que cada archivo principal incluya el mismo perfil de compilación sin tener que construirlo realmente?

  3. ¿Debería ir r.js en el directorio principal de httpdocs_siteroot?

  4. ¿Hay algo absolutamente incorrecto con la estructura de mi aplicación o el uso de RequireJS?

+0

Tengo una respuesta corta y larga, pero necesito algunos detalles: ¿cuántas páginas? El código que es específico para cada página es poco o mucho código (digamos 10kb de código para cada página). – devundef

+0

¿Está utilizando complementos requirejs, qué complementos? – devundef

+0

Normalmente <10kb por archivo mainjs. Solo lo uso para cosas como iniciar complementos jquery. Habrá muchas páginas ... Yo diría que 20 y cada vez más. Probablemente alrededor de 15 archivos mainjs y creciendo. Y los complementos que estoy usando son complementos jquery envueltos con una llamada a definir para ser compatible con AMD – AndyPerlitch

Respuesta

57

Antes que nada, esto no es una pregunta con una solución única. Explicaré la forma en que uso RequireJS que funciona para mí, y puede funcionar para usted :)

En segundo lugar, el inglés no es mi lengua materna. Las correcciones y sugerencias sobre el idioma serán muy apreciadas. Siéntase libre, muchachos :)

1) ¿Es necesario js incluso práctico para proyectos que no son de una sola página?

Depende. Si su proyecto no tiene código compartido entre páginas, por ejemplo, la ayuda de RequireJS será modesta. La idea principal de RequireJS es modularizar la aplicación en trozos de código reutilizable. Si su aplicación usa solo código específico de la página, entonces el uso de RequireJS puede no ser una buena idea.

2) Sin utilizar el optimizador, cada uno de mis archivos principales comienza esencialmente con las mismas opciones de configuración. Hay alguna manera de evitar esto? ¿Quiere que cada archivo principal incluya el mismo perfil de compilación sin tener que construirlo realmente?

La única forma que veo es hacer la configuración en el archivo principal, o crear un módulo que configure RequireJS y luego usar ese módulo como la primera dependencia de main.js. Pero esto puede ser complicado. No uso muchos archivos main.js en mis aplicaciones; Solo uso uno que actúa como cargador (ver a continuación).

3) ¿Debería r.js entrar en el directorio padre de httpdocs_siteroot?

No necesariamente. Puedes ponerlo dentro del directorio/media, ya que todas las cosas de tus clientes están ahí.

4) ¿Hay algo absolutamente incorrecto con la estructura de mi aplicación o el uso de requirejs?

No diría eso. Por otro lado, la estructura tal vez esté demasiado fragmentada. Por ejemplo, puede poner todas las 'cosas de terceros' dentro de un directorio/proveedor. Pero esto es solo azúcar; tu estructura funcionará bien y parece correcta. Creo que el problema principal es la llamada requirejs.config() en múltiples archivos principales.

que tenía los mismos problemas que tiene ahora y que terminó con la siguiente solución:

1) No envuelva los archivos que no son compatibles con AMD-con una definición. Aunque funciona, puede obtener los mismos resultados usando la propiedad "shim" en requirejs.config (ver a continuación).

2) En una aplicación de varias páginas, la solución para mí no es requerir los módulos específicos de la página del archivo main.js optimizado. En cambio, requiero todo el código compartido (de terceros y el mío) del archivo principal, dejando que el código específico de la página se cargue en cada página. El archivo principal termina siendo solo un cargador que inicia el código específico de la página después de cargar todos los archivos compartidos/lib.

Este es el texto modelo que utilizo para construir una aplicación de varias páginas con RequireJS

estructura de directorios:

/src - puse todas las cosas cliente dentro de un directorio src, por lo que se puede ejecutar el optimizador dentro de este directorio (este es su directorio de medios).

/src/vendor - Aquí coloco todos los archivos y complementos de terceros, incluido require.js.

/src/lib - Aquí coloco todo mi propio código que es compartido por toda la aplicación o por algunas páginas. En otras palabras, módulos que no son específicos de la página.

/src/page-module-xx - Y luego, creo un directorio para cada página que tengo. Esta no es una regla estricta.

/src/main.js: Este es el único archivo principal para toda la aplicación. El programa:

  • RequireJS configure, incluyendo cuñas
  • bibliotecas de carga compartida/módulos
  • carga el módulo principal específica de la página

Este es un ejemplo de una llamada requirejs.config:

requirejs.config({ 
     baseUrl: ".", 
     paths: { 
      // libraries path 
      "json": "vendor/json2", 
      "jquery": "vendor/jquery", 
      "somejqueryplugion": "vendor/jquery.somejqueryplufin", 
      "hogan": "vendor/hogan", 

      // require plugins 
      "templ": "vendor/require.hogan", 
      "text": "vendor/require.text" 
     }, 
     // The shim section allows you to specify 
     // dependencies between non AMD compliant files. 
     // For example, "somejqueryplugin" must be loaded after "jquery". 
     // The 'exports' attribute tells RequireJS what global variable 
     // it must assign as the module value for each shim. 
     // For example: By using the configutation below for jquery, 
     // when you request the "jquery" module, RequireJS will 
     // give the value of global "$" (this value will be cached, so it is 
     // ok to modify/delete the global '$' after all plugins are loaded. 
     shim: { 
      "jquery": { exports: "$" }, 
      "util": { exports: "_" }, 
      "json": { exports: "JSON" }, 
      "somejqueryplugin": { exports: "$", deps: ["jquery"] } 
     } 
    }); 

Y luego, después de la configuración podemos hacer la primera solicitud require() para todas esas bibliotecas y luego haga la solicitud de nuestro módulo "page main".

//libs 
require([ 
    "templ",  //require plugins 
    "text", 
    "json",  //3rd libraries 
    "jquery", 
    "hogan", 
    "lib/util" // app lib modules 
], 
    function() { 
     var $ = require("jquery"), 
      // the start module is defined on the same script tag of data-main. 
      // example: <script data-main="main.js" data-start="pagemodule/main" src="vendor/require.js"/> 
      startModuleName = $("script[data-main][data-start]").attr("data-start"); 

     if (startModuleName) { 
      require([startModuleName], function (startModule) { 
       $(function(){ 
        var fn = $.isFunction(startModule) ? startModule : startModule.init; 
        if (fn) { fn(); } 
       }); 
      }); 
     } 
    }); 

Como se puede ver en el cuerpo de la require() anterior, estamos esperando otro atributo de la etiqueta script require.js. El atributo data-start mantendrá el nombre del módulo para la página actual.

Por lo tanto, en la página HTML que hay que añadir este atributo adicional:

<script data-main="main" data-start="pagemodule/main" src="vendor/require.js"></script> 

Al hacer esto, vamos a terminar con un main.js optimizados que contiene todos los archivos en "/ proveedor" y "/lib "directorios (los recursos compartidos), pero no los scripts/módulos específicos de la página, ya que no están codificados en main.js como dependencias. Los módulos específicos de la página se cargarán por separado en cada página de la aplicación.

El módulo "página principal" debe devolver un function() que será ejecutado por la "aplicación principal" arriba.

define(function(require, exports, module) { 
    var util = require("lib/util"); 

    return function() { 
     console.log("initializing page xyz module"); 
    }; 
}); 

EDITAR

Aquí es ejemplo de cómo se puede utilizar el perfil de generación para optimizar los módulos específicos de la página que tienen más de un archivo.

Por ejemplo, supongamos que tenemos el siguiente módulo de la página:

/page1/main.js

/page1/dep1.js

/page1/dep2.js

Si no optimizamos este módulo, el navegador realizará 3 solicitudes, una para cada secuencia de comandos. Podemos evitar esto instruyendo a r.js para crear un paquete e incluir estos 3 archivos.

En el atributo "módulos" del perfil de construcción:

... 
"modules": [ 
    { 
     name: "main" // this is our main file 
    }, 
    { 
     // create a module for page1/main and include in it 
     // all its dependencies (dep1, dep2...) 
     name: "page1/main", 
     // excluding any dependency that is already included on main module 
     // i.e. all our shared stuff, like jquery and plugins should not 
     // be included in this module again. 
     exclude: ["main"] 
    } 
] 

De esta manera, se crea otro archivo principal por página con todas sus dependencias. Pero, dado que ya tenemos un archivo principal que cargará todas nuestras cosas compartidas, no es necesario que las vuelvas a incluir en la página1/módulo principal. La configuración es un poco prolija, ya que tiene que hacer esto para cada módulo de página donde tiene más de un archivo de script.

Cargué el código del modelo en GitHub: https://github.com/mdezem/MultiPageAppBoilerplate. Es una plantilla repetitiva, simplemente instale el nodo y el módulo r.js para el nodo y ejecute build.cmd (dentro del directorio/build, de lo contrario fallará porque usa rutas relativas)

Espero haber sido claro. Avíseme si algo suena extraño;)

Saludos!

+0

¡Gracias por la gran respuesta!Todavía tengo que leerlo un par de veces más y revisar su boilerplate de github para obtenerlo realmente, ¡pero estoy seguro de que tendré algunas preguntas muy pronto! – AndyPerlitch

+0

@AndyPerlitch, es bueno saberlo, gracias por la revisión. – devundef

+0

¿Utiliza la función $ (document) .ready() en cada módulo de página que necesita interactuar con el DOM? por lo que se vería así: define ( function() { función de retorno() {$ (documento) ready (function() {// hacer cosas }); }} ); Parece un poco detallado ... ¿Puedes poner el script require al final de la página? No estoy seguro porque sé que los documentos obligatorios dicen que lo pongas en la cabeza – AndyPerlitch

1
<script data-main="js/main" src="js/lib/require.js"></script> 


// file: js/main 

require(['./global.config'], function(){ 
    require(['./view/home'], function() { 
     // do something 
    }); 
}); 

Esto es lo que utilicé en mi proyecto.

Cuestiones relacionadas