¡Esta es una revisión vieja del documento!


15.1 Estructura de ficheros

Mucho se ha hablado sobre la estructura de los ficheros en una aplicación de AngularJS y se seguirá hablando de ello ya que no existe una estructura definitiva que se pueda aplicar a todos los proyectos sino que depende de las características del propio proyecto como puedan ser el tamaño del proyecto, el tiempo de desarrollo o los conocimientos del equipo de desarrollo. Por todo esto , lo que vamos a explicar aquí no debe tratarse como reglar fijas sino guías a aplicar que deben ser personalizadas para cada proyecto.

En muchos tutoriales se empieza diciendo que hay una carpeta llamada app donde está el código fuente del proyecto, en nuestro caso no vamos a tener dicha carpeta ya que al estar dirigido este curso a un desarrollo en la parte servidor en Java y usando NetBeans nuestra carpeta con las páginas HTML, JavaScript, etc. se llama web.

La carpeta web incluye las subcarpetas WEB-INF y META-INF pero no vamos aquí a hablar de ellas ya que únicamente son importantes en la parte servidora y ya se habló sobre ellas en la unida de Servidor.

Carpeta raíz

Inicialmente nuestro proyecto debe tener la siguiente estructura:

app.js
index.html
index.js
main.html
main.js
  • app.js : Aqui es donde definimos los siguiente:
    • El módulo de la aplicación
    • Las constantes
    • Los bloques config , incluyendo las rutas pero unicamente la ruta por defecto y no el resto de las rutas de la aplicación. Ya veremos después donde se definen cada una de ellas.
    • Los bloques run
  • index.html : Página principal que contendrá el resto de páginas. Es la que contiene la directiva ng-view. También puede contener sus propios controladores
  • index.js: Es el JavaScript específico de index.html , lo normal es que solo tenga los controladores específicos de index.html
  • main.html : Este es el HTML de la ruta por defecto que hemos definido en app.js
  • main.js : Es el JavaScript específico de main.html , lo normal es que solo tenga los controladores específicos de main.html

El contenido del fichero app.js sería parecido al siguiente:

var app = angular.module('app', [
    'ngRoute'
]);

//Añade aquí las constantes 

app.config(['$routeProvider', function ($routeProvider) {
    //En este bloque config solo se configuran las rutas

    $routeProvider.when('/', {
        templateUrl: 'main.html',
        controller: 'MainController'
    });

    $routeProvider.otherwise({
        redirectTo: '/'
    });
}])


app.config([function () {
    //Bloque config para configurar el resto de cosas que no son las rutas.
}])

app.run([function () {

}]);

Variaciones

En vez de tener un único fichero app.js para definir el módulo, los bloques config , los bloques run, etc. Se podría dividir en cada uno de eso tipos quedando de la siguiente forma:

app-module.js
app-constant.js  
app-route.js
app-config.js
app-run.js
  • app-module.js: Únicamente contiene la definición del módulo
  • app-constant.js : Únicamente las constantes de la aplicación
  • app-route.js: Bloque config con la definición unicamente de la ruta por defecto y no el resto de las rutas de la aplicación. Ya veremos después donde se definen cada una de ellas.
  • app-config.js: El resto de bloques config que no definen las rutas.
  • app-run.js: Los bloques run

Vemos que hemos separamos las rutas y los bloques config en dos ficheros aunque definir una ruta se hace en un bloque config. Se ha hecho para dar mas importancia a la rutas.

Otra variación sería una versión intermedia entre las 2 anteriores:

app.js
app-route.js
  • app-module.js: Contiene la definición del módulo, las constante y el resto de bloques config que no definen las ruta y los bloques run
  • app-route.js: Bloque config con la definición unicamente de la ruta por defecto y no todas las rutas de la aplicación. Ya veremos después donde se definen cada una de ellas.

Es decir que hacemos un fichero aparte solo para las rutas y dejamos el resto en app.js. El sentido es esto es porque suele ser lo que mas frecuentemente se mira ya que es necesario para recordar las operaciones que hay.

Servicios, directivas y filtros

Vamos a añadir una carpeta para los servicio, directivas , filtros, etc que son comunes a toda la aplicación.

app.js
index.html
index.js
main.html
main.js
common/
  directives/
    directive1.js
    directive2.js
  filters/
    filter1.js
    filter2.js
  services/
    service1.js
    service2.js
  • common: Es una carpeta que contiene los servicio, directivas , filtros, etc que son comunes a toda la aplicación.
  • directives : Carpeta con cada una de las directivas que son comunes en la aplicación. Cada fichero de esta carpeta contiene una única directiva.
  • filters : Carpeta con cada uno de los filtros que son comunes en la aplicación. Cada fichero de esta carpeta contiene un único filtro.
  • services: Carpeta con cada uno de los servicios que son comunes en la aplicación. Cada fichero de esta carpeta contiene un único servicio.

Variaciones

Si tenemos pocas directivas, filtros o servicios se pueden evitar las subcarpetas y ponerlos todos directamente en la carpeta common quedadon de la siguiente forma:

common/
  directive1.js
  directive2.js
  filter1.js
  filter2.js
  service1.js
  service2.js
  

en este último caso puede ser interesante añadir un sufijo en cada fichero para indicar el tipo de artefacto:

common/
  directive1-directive.js
  directive2-directive.js
  filter1-filter.js
  filter2-filter.js
  service1-service.js
  service2-service.js

Librerias

Ahora vamos a añadir una carpeta con las librerías CSS, JavaScript , etc. de terceros. Pueden ser tanto módulos de AngularJS como otro tipo de librerías web.

app.js
index.html
index.js
main.html
main.js
common/
  directives/
    directive1.js
    directive2.js
  filters/
    filter1.js
    filter2.js
  services/
    service1.js
    service2.js
lib/
  bootstrap/
    css/
      bootstrap.css
      bootstrap.min.css
    fonts/
      glyphicons-halflings-regular.eot
      glyphicons-halflings-regular.svg
      glyphicons-halflings-regular.ttf
      glyphicons-halflings-regular.woff
    js/
      bootstrap.js
      bootstrap.min.js
  angularjs/
    js/
      angular.js
      angular-route.js
      angular-locale_es-es.js
  • lib : La carpeta donde se guardan cada una de las librerías de terceros que vamos a usar.
  • bootstrap y angularjs: Dentro de lib creamos una subcarpeta con el nombre de la librería de terceros que vamos a usar, en este caso son bootstrap y AngularJS
  • css , fonts y js: Dentro de cada librería creamos las subcarpetas para los estilos CSS, las fuentes y el JavaScript. La idea de esta estructura está sacada de la propia distribución de bootstrap y la he aplicado tambien a AngularJS o cualquier otra librería.

Es importante en bootstrap mantener la estructura de css , fonts y js ya que los CSS de bootstrap hacen referencia a una ruta relativa llamad ”../fonts” por lo que debemos seguir esa estructura.

Variaciones

La carpeta lib también suele llamarse vendor. Personalmente prefiero el nombre de lib ya que así se llama igual que la carpeta lib donde guardamos las librerías Java quedando de esa forma todo mas coherente.

vendor/
  bootstrap/
  angularjs/

Por otro lado puede darse el caso que debamos usar varias versiones de la misma librería en la misma aplicación. Algo que puede suceder si estamos migrando a una nueva versión a mitad de proyecto pero no queremos modificar todo el código a la vez. En ese caos podríamos crear la siguiente estructura:

lib/
  angularjs/
    v1.2/
      js/
        angular.js
        angular-route.js
        angular-locale_es-es.js 
    v1.3/
      js/
        angular.js
        angular-route.js
        angular-locale_es-es.js 

Añadimos una subcarpeta mas indicando el número de versión. De esa forma podemos tener a la vez 2 versiones de la misma librería.

Esto último lo podríamos complicar un poco mas con una carpeta default para la librería que la aplicación debe usar por defecto si no dice nada sobre la versión. Aunque ya creo que así quizás nos estemos pasando de sobreingeniería.

lib/
  angularjs/
    default/
      js/
        angular.js
        angular-route.js
        angular-locale_es-es.js 
    v1.2/
      js/
        angular.js
        angular-route.js
        angular-locale_es-es.js 
    v1.3/
      js/
        angular.js
        angular-route.js
        angular-locale_es-es.js       

Funcionalidades

Ahora ahora hemos visto carpeta para preparar cosas de la aplicación de forma genérica pero sin incluir ninguna funcionalidad directa de la aplicación. Lo siguiente es crear una carpeta por cada una de las funcionalidades que tiene la aplicación. Dicho un poco mal y espero que se me perdone la frase: ”Habría que hacer mas o menos una carpeta por cada tabla de la base de datos.” o quizás dicho un poco mejor : ”Habría que hacer mas o menos una carpeta por cada entidad del interfaz REST

app.js
index.html
index.js
main.html
main.js
common/
  directives/
    directive1.js
    directive2.js
  filters/
    filter1.js
    filter2.js
  services/
    service1.js
    service2.js
lib/
  bootstrap/
    css/
      bootstrap.css
      bootstrap.min.css
    fonts/
      glyphicons-halflings-regular.eot
      glyphicons-halflings-regular.svg
      glyphicons-halflings-regular.ttf
      glyphicons-halflings-regular.woff
    js/
      bootstrap.js
      bootstrap.min.js
  angularjs/
    js/
      angular.js
      angular-route.js
      angular-locale_es-es.js
seguromedico/
  seguromedico-list.html
  seguromedico-list.js
  seguromedico-detail.html
  seguromedico-detail.js
  seguromedico.js
usuario/
  usuario-list.html
  usuario-list.js
  usuario-detail.html
  usuario-detail.js
  usuario.js
  • seguromedico : Esta carpeta tiene la funcionalidad para hacer un CRUD 1) sobre la entidad SeguroMedico. Lo mismo ocurre con la carpeta usuario que haría referencia a la entidad Usuario.
  • seguromedico-list.html: Contiene el HTML para mostrar una lista (Tabla HTML) con los seguros médicos.
  • seguromedico-list.js : Es el JavaScript específico de seguromedico-list.html , lo normal es que solo tenga el/los controlador/es específico/s de seguromedico-list.html
  • seguromedico-detail.html: Contiene el HTML para mostrar el detalle de un único seguro médico.
  • seguromedico-detail.js: Es el JavaScript específico de seguromedico-detail.html , lo normal es que solo tenga el/los controlador/es específico/s de seguromedico-detail.html
  • seguromedico.js : Este fichero se llamará igual que la carpeta y definimos lo siguiente:
    • Las constantes
    • Los bloques config , incluyendo las rutas de las funcionalidades de estas página. Fíjate que finalmente aquí es donde finalmente se ponen las rutas de la cada funcionalidad.
    • Los bloques run

Cada carpeta de funcionalidades , define sus propias rutas. En nuestro ejemplo sería en el fichero seguromedico.js

Hay otra carpeta llamada usuario ya que podemos poner tantas carpetas de funcionalidades como queramos en el proyecto.

Variaciones

Al igual que con el fichero app.js, el fichero seguromedico.js tambien podría ser dividido en los siguientes ficheros:

seguromedico-constant.js
seguromedico-route.js
seguromedico-config.js
seguromedico-run.js

O como en la segunda alternativa de la siguiente forma:

seguromedico.js
seguromedico-route.js

En la que le damos mas importancia a las rutas por lo que las dejamos en un fichero aparte.

Estructuras jerárquica

Podemos ver cada una de éstas carpetas de funcionalidades como una pequeña aplicación por lo tanto sería posible en cada carpeta añadir de forma recursiva las carpetas que ya hemos explicado.

seguromedico/
  seguromedico-list.html
  seguromedico-list.js
  seguromedico-detail.html
  seguromedico-detail.js
  seguromedico.js
  
  common/
    directives/
    filters/
    services/
    
  lib/
    heatmap/
      heatmap.js
  
  
  asistenciamedica/
    asistenciamedica-list.html
    asistenciamedica-list.js
    asistenciamedica-detail.html
    asistenciamedica-detail.js
    asistenciamedica.js    
  • common : Esta carpeta contendría directivas, filtros o servicios muy específicos de esta funcionalidad y por lo tanto que no queremos que esté en el common del raiz.
  • lib: Contendría librerías que sabemos que únicamente se usarán en esta funcionalidad y por lo tanto que no queremos que esté en el lib del raiz. Es nuestro ejemplo he puesto la librería heatmap.js que pemite hacer mapas de calor. ¿realmente queremos ponerla en la carpeta lib del raiz cuando es algo tan específico que nadie mas va a usarla?
  • asistenciamedica : Por último podemos añadir otra subcarpeta con otra funcionalidad y así recursivamente …..

Único módulo

Una cosa que puede chocar mucho en esta estructura de ficheros es que solo se cree un módulo y se use la variable global app con ese único módulo. En todas las páginas en las que hablan de este tema como pueden ser

explican que no hay que usar la variable global app y separar la aplicación en diversos módulos.

La forma es la siguiente:

angular.module('sub.module1');
angular.module('sub.module2');

angular.module('app',['sub.module1','sub.module2']);


angular.module('sub.module1')​.controller("Prueba1Controller",[function() {
    
}]);
 	    ​
angular.module('sub.module2')​.controller("Prueba2Controller",[function() {
    
}]);

  • No se guarda el módulo en la típica variable app
  • Se crean 2 submódulos: “sub.module1” y “sub.module2” de los que dependen el módulo principal llamado “app”.
  • No se usa la variable global , obtiene de nuevo una referencia al módulo y sobre él se añaden los controladores, módulos config, etc.

Ahora bien , mi recomendación es la siguiente. Para crear un módulo:

var app=angular.module('app',[]);

app​.controller("Prueba1Controller",[function() {
    
}]);
 	    ​
app.controller("Prueba2Controller",[function() {
    
}]);

  • Si se guarda el módulo en la típica variable app
  • No se crean submódulos
  • Se usa la variable global app y sobre ella se añaden los controladores, módulos config, etc.

¿Porque recomiendo tener un único módulo en vez de varios y usar la variable global app en vez de obtener el módulo cada vez que se necesita?

Briant Ford , uno de los desarrolladores de AngularJS comenta en su post Building Huuuuuge Apps with AngularJS : “From a performance perspective, it doesn't really matter how you organize your modules, so choose whatever method best suits your project.”. Es decir que no ayuda para nada al rendimiento separar la aplicación en módulo y en la presentación que hicieron en el ng-europe sobre Angular 2.0 no parece que haya nada sobre éste tema. Así que no hay ninguna justificación relativa al rendimiento para tener varios módulos.

1) O lo que necesite la aplicación
unidades/15_avanzado/01_ficheros.1414441914.txt.gz · Última modificación: 2014/10/27 21:31 por admin
Ir hasta arriba
CC Attribution-Share Alike 3.0 Unported
chimeric.de = chi`s home Valid CSS Driven by DokuWiki do yourself a favour and use a real browser - get firefox!! Recent changes RSS feed Valid XHTML 1.0