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!
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
¿Está utilizando complementos requirejs, qué complementos? – devundef
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