2012-01-06 18 views
33

Creé una aplicación javascript con todo el código en un archivo. La aplicación ha crecido bastante y creo que es hora de dividirla en varios archivos, pero me está costando trabajo encontrar la manera de hacerlo. Creo que el problema radica en cómo me he decidido construir la aplicación, que utiliza la siguiente plantilla:¿Cómo puedo dividir una aplicación de JavaScript en varios archivos?

var myApp = function(){ 

    //there are several global variables that all of the modules use; 
    var global1, global2, module1, module2; 

    global1 = { 
     prop1:1 
    }; 

    //There are also several functions that are shared between modules 
    function globalFunction(){ 

    } 

    var ModuleOne = function(){ 

     function doSomething(){ 
      //using the global function 
      globalFunction(); 
     } 

     return{ 
      doSomething:doSomething 
     } 
    }; 

    var ModuleTwo = function(){ 

     function doSomething(){ 
      //module 2 also needs the global function 
      globalFunction(); 

      //Use the functionality in module 1 
      //I can refactor this part to be loosely coupled/event driven 
      module1.doSomething(); 
     } 
    }; 

    module1 = new ModuleOne(); 
    module2 = new ModuleTwo(); 
}; 

Incluso si todos los módulos fueron acoplamiento flexible y orientada a eventos, todavía no saben cómo lo haría dividir esto en varios archivos dada la dependencia de cada módulo en las funciones/variables compartidas. ¿Alguien tiene sugerencias?

+0

En serio, herramientas como [module8] (https://github.com/clux/modul8) resuelva su problema – Raynos

+0

Eche un vistazo al patrón de diseño en este artículo: http://www.adequatelygood.com/2010/3/JavaScript-Module-Pattern-In- Profundidad - usted puede dividir la definición de su módulo en varios archivos de manera que permita compartir propiedades comunes, pero también le permite crear variables o métodos que son privados solo para un archivo en particular. – nnnnnn

+0

@nnnnnn Gracias. Voy a comprobarlo ahora. –

Respuesta

34

Tome una mirada en el patrón de diseño en este artículo: http://www.adequatelygood.com/2010/3/JavaScript-Module-Pattern-In-Depth - se puede dividir su definición del módulo a través de múltiples archivos de una manera permite compartir propiedades comunes pero también permite crear variables o métodos que son privados solo para un archivo en particular.

La idea básica es que los archivos JS individuales se suman al mismo módulo con un código como éste:

var MODULE = (function (my) { 
    var privateToThisFile = "something"; 

    // add capabilities... 

    my.publicProperty = "something"; 

    return my; 
}(MODULE || {})); 

donde en cada archivo JS si MODULE ya está definido (desde otro archivo JS) se añaden a ella de lo contrario lo creas. Puede configurarlo para que (la mayoría) no importe en qué orden están incluidos los diversos archivos.

El artículo detalla varias variaciones y, por supuesto, probablemente obtendrá sus propios ajustes ...

1

Regístrese para require.js. http://requirejs.org/

Ejemplo:

require(["dir/file"], function() { 
    // Called when file.js loads 
}); 
+0

Sí, lo investigué, pero todavía no sé cómo resolvería el problema con las funciones compartidas ... –

+0

Pero, ¿cómo ayuda eso a dividir lo que actualmente es un gran archivo de código interdependiente? – nnnnnn

+0

Usted crea un archivo por clase (De ahí la etiqueta OOP) y la secuencia de comandos que se ejecuta simplemente tira de esas clases para su uso. Si me muestra el código, podría ayudarlo a distribuirlo entre los archivos. –

2

Usted puede poner las funciones compartidas y módulos compartidos en el objeto myApp para que no contaminan el espacio de nombres global, pero se puede acceder en cualquier lugar sin estar dentro del mismo cierre.

myApp.moduleOne = function() {...} 
myApp.moduleTwo = function() {...} 
myApp.globalFunction = function() {...} 

A continuación, se pueden definir en cualquier archivo y utilizarlos en cualquier archivo.

También podría simplemente dividir el archivo en varios archivos, pero debe incluirlos en un orden específico que preserve su cierre. Si está dividiendo los archivos por razones de edición práctica, pero los recombina y los minimiza para la implementación real, entonces esto no le costaría nada en términos de cómo escribe el código o cómo se implementa, pero le daría muchos archivos más pequeños. para la conveniencia de edición.

+0

myApp no ​​es el nombre real, solo lo uso para el ejemplo. Dada su sugerencia, necesitaría cambiar cada llamada a globalFunction a myApp.globalFunction() ¿correcto? –

+0

@MarkBrown - correcto. Es un poco menos deseable cuando se escribe código, pero le da más flexibilidad para segmentar su código en archivos completamente separados que pueden ser mucho más independientes. Agregué otra opción a mi respuesta también. – jfriend00

0

Mi solución favorita para esto es usar el scripting del lado del servidor para incluir los otros archivos dentro de mi archivo "principal". Por ejemplo, el uso de Template Toolkit de Perl:

var myApp = function(){ 
    [% INCLUDE lib/module1.js %] 
    [% INCLUDE lib/module2.js %] 
    [% INCLUDE lib/module3.js %] 
} 

o PHP:

var myApp = function(){ 
    <?php 
    include 'lib/module1.js'; 
    include 'lib/module2.js'; 
    ?> 
} 
+1

Eso es construir dinámicamente javascript. Esto debe evitarse a favor de la compilación estática en lugar de la inclusión dinámica. – Raynos

+0

Tanto TT como PHP pueden ejecutarse desde la consola para que pueda escribir fácilmente un script de compilación si desea una compilación estática. Ah, además TT se puede configurar para almacenar en caché los archivos, por lo que la compilación solo debe realizarse una vez. – slebetman

4

para no aumentar la confusión, pero viniendo de un fondo de C++, he intentado construir algo que se asemeje a algo así como un espacio de nombres de C++ de la manera que se describe a continuación. funciona, pero me gustaría saber si este es un patrón aceptable para el OP.

-------------------------------- archivo principal.js: ----------------

var namespacename = function(){} 

namespacename.mainvalue = 5; 

namespacename.maintest = function() { 
    var cm = new namespacename.game(); 
    cm.callme(); 
} 

------------------------- ------- file game.js: ----------------

namespacename.gamevalue = 15; 

namespacename.game = function(){ 
    this.callme = function(){ 
     console.log("callme"); 
    } 
} 

namespacename.gametest = function() { 
    console.log("gametest:gamevalue:" + this.gamevalue); 
    console.log("gametest:mainvalue:" + this.mainvalue); 
} 

--------------- ----------------- file index.html: --------------

<html> 
    <head> 
     <title>testbed</title> 
    </head> 

    <body onload="init();"> 
    </body> 

    <script type="text/javascript" src="main.js"></script> 
    <script type="text/javascript" src="game.js"></script> 

    <script type="text/javascript"> 

     init = function() 
     { 
      namespacename.maintest(); 
      namespacename.gametest(); 

      console.log("html main:" + namespacename.mainvalue); 
      console.log("html game:" + namespacename.gamevalue); 
     } 

    </script> 
</html> 
+4

¿Por qué declarar _namespacename_ como una función vacía que nunca se llama? Podría declararlo como un objeto vacío con _var namespacename = {} _ y no sería necesario cambiar el resto de su código. – nnnnnn

+0

¡Esta solución funciona para mí! –

Cuestiones relacionadas