Scrivere un app Angular è un gioco da ragazzi, ovviamente giorno dopo giorno le conoscenze aumentano tanto da migliorar e rendere più sicuro il proprio codice, quello che seguirà in questo post e nei prossimi sono tutte le fasi, dalla più “spaghetti code” alla più sistemata di come strutturare un app Angular

Terza Fase: Single Responsibility, IIFE e Gulp

Nello scorso step abbiamo visto i costrutti base di angular, come prendere dei dati da fonti esterne e come usare librerie esterne, in questo post vedremo come ottimizzare la nostra applicazione Angular per renderla più sicura e facilmente manutenibile attraverlo le linee guida di John Papa

Single Responsibility

La Single Reponsability, anche chiamata regola dell’1, ci obbliga a definire un componente per ogni pagina cosi da permetterci una lettura migliore del nostro codice. Detto in linee di codice:

/* evitare */
angular.module(‘myApp.users’, [‘ngRoute’])
.config([‘$routeProvider’, function($routeProvider) {}])
.controller(‘UsersCtrl’, function($scope, Users) {})
.factory(“Users”, function($http) { });

ma separare in diversi file in questo modo:

/* consigliato */

// users.module.js
angular
  .module('myApp.users', ['ngRoute']);

...

/* consigliato */

// users.controller.js
angular
  .module('myApp.users')
  .controller('UsersCtrl', UsersCtrl);

function UsersCtrl() { }

...

/* consigliato */

// users.service.js
angular
  .module('myApp.services')
  .factory('Users', users);

function users() { }

Ovviamente, in questa prima fase, questo ci costringerà a importare ogni file nel nostro index.html, cosa che più avanti con l’utilizzo di Gulp non avremmo più bisogno di fare.
Andiamo nel nostro index.html e aggiungiamo:

<script src=”services/service.module.js”></script>
<script src=”services/users.service.js”></script>
<script src=”users/users.module.js”></script>
<script src=”users/users.controllers.js”></script>
<script src=”purchase/purchase.module.js”></script>
<script src=”purchase/purchase.controllers.js”></script>
<script src=”app.js”></script>

In questo modo la nostra app continuerà a funzionare esattamente come prima ma abbiamo pulito il codice in modo da renderlo molto più leggibile e manutenibile. Unico difetto in questo modo e che al crescere dei moduli creati la nostra pagina html avrà tanti import quanti file andremo a creare.

IIFE

L’utilizzo dell’IIFE , Immediately Invoked Function Expression, é qualcosa di tanto banale quanto utile.
Si tratta di andare a modificare tutti i nostri file js in modo da inglobarli all’interno di una funzione che auto invoca (function() {})();
Perche? L’uso dell’IIFE rimuove le variabili dallo scope globale. Questo aiuta a prevenire che variabili e dichiarazioni di funzione vivano più del previsto nello scope globale, inoltre aiuta ad evitare la collisione di variabili.
Ad esempio, quando il tuo codice è minificato e raggruppato in un file singolo per il rilascio ad un server di produzione (Gulp), potresti avere collisioni di variabili e parecchie variabili globali.

Andiamo quindi a modificare tutti i nostri file JS in modo da usare l’IIFE, ad esempio:

(function() {
‘use strict’;
 angular.module(‘myApp’, [
 ‘ngRoute’,
 ‘myApp.services’,
 ‘myApp.users’,
 ‘myApp.purchase’
]).
config([‘$routeProvider’, function($routeProvider) {
  $routeProvider.otherwise({ redirectTo: ‘/users’ });
}]);
})();

GULP

GulpJS è un task runner che ci permette di eliminare dal nostro flow di sviluppo tutti i task ripetitivi come minifizzare i file js, fare il require di ogni file js che scriviamo e molti altri come complilare LESS.
Per poter utilizzare Gulp avremo bisogno di node, infatti è un pacchetto npm facilmente installabile con:

npm install gulp -g

e andrà configurato all’interno di un file nella root del nostro progetto chiamato gulpfile.js
La prima azione da fare è rinominare tutti i file *.modules.js in modules.js e portare tutti e tre i moduli che abbiamo creato sotto la folder modules
Perche?
Come vederemo tra poco, possiamo far in modo che gulp prenda tutti i file sotto una cartella e li “parsi” con un certo ordine che daremo, per evitar di dover modificare il file gulpfile.js ogni qual volta aggiungiamo un modulo, mettendo tutti i moduli all’interno di una subfolder chiamata modules, potremmo dire a gulp di prendere tutti i file js che trova al suo interno e per ogni cartella di far il parse prima di quelli chiamati module.js in questo modo:

‘use strict’;
var gulp = require(‘gulp’),
 concat = require(‘gulp-concat’),
 uglify = require(‘gulp-uglify’),
ngAnnotate = require(‘gulp-ng-annotate’);
var jsOrder = [
‘app/modules/**/module.js’,
‘app/modules/**/*.js’,
‘app/*.js’
];
gulp.task(‘js’, function() {
gulp.src(jsOrder)
  .pipe(concat(‘app.js’))
  .pipe(ngAnnotate())
  .pipe(uglify())
  .pipe(gulp.dest(‘app/dist’))
});
gulp.watch([‘app/*.js’, ‘app/modules/**/*.js’], [‘js’])

In questo modo stiamo dicendo a gulp di:

  • equire di gulp e di alcuni suoi sotto moduli che servono, in ordine, per concatenare tutti i file js, per minifizzarli e per far in modo che anche minifizzati e uglifizzati angular riesca a passarli aggiungendo le annotation di angular che altrimenti avremmo dovuto scrivere a mano
  • nella variabile jsOrder non facciamo altro che dare l’ordine che spiegavamo poco fa, diciamo di prendere per prima tutti i file module.js all’interno della cartella modules, dopo di che tutti gli altri file nella cartella modules e solo alla fine i file js generali che in questo momento è app.js che deve essere sempre caricata alla fine
  • con gulp.taks definiamo il primo vero e proprio task di gulp in questo caso gli stiamo chiedendo di fare il require di tutti i file js con l’ordine sopra indicato,
    concatenarli tutti all’interno di un solo file js, aggiungere le annotazioni Angular utili per l’uglify, minificare e uglifizzare il nostro codice e salvare il file, chiamato app.js, all’interno di app/dist
  • in fine, per evitar di dover dar il comando gulp js ogni volta definiamo un watcher che rimarrà in ascolto e ogni qual volta salveremo un file js farà ripartire il task js che abbiamo sopra dichiarato.

Ora eseguendo il comando gulp da terminale avremo un log di questo tipo:

user-MBP:angular-base-project thecrz$ gulp
[17:41:28] Using gulpfile ~/Developer/personal/angular-base-project/gulpfile.js
[17:41:28] Starting ‘default’…
[17:41:29] Finished ‘default’ after 21 ms

Che ci farà capire che effettivamente è andato tutto a buon fine e infatti all’interno della cartella (che abbiamo creato prima) dist troveremo il nostro file app.jsche , in maniera poco chiara, contiene tutto i file js del nostro progetto.
Andando a modificare il nostro file index.html ora potremmo creare tutti i moduli/file js di cui avremmo bisogno nel nostro progetto senza preoccuparci di dover aggiungere dipendenze o dover far operazioni ripetitive, quindi:

/* togliamo */
<script src=”services/service.module.js”></script>
<script src=”services/users.service.js”></script>
<script src=”users/users.module.js”></script>
<script src=”users/users.controllers.js”></script>
<script src=”purchase/purchase.module.js”></script>
<script src=”purchase/purchase.controllers.js”></script>
<script src=”app.js”></script>

/* e inseriamo */
<script src="dist/app.js"></script>

NOTA: ricordiamoci di modificare i file module.js inserendo il path corretto dei nostri file .html visto che adesso abbiamo spostato tutto dentro la cartella modules

Conclusioni

Abbiamo visto come ottimizzare la leggibilità e la sicurezza della nostra app Angular,
l’esempio completo lo trovate a questo link su git:https://github.com/thecreazy/angular-base-project
il progetto conterrà man mano tutte le evolutive che pian piano andremo a studiar nei post a seguire, dalla seconda lezione in poi troverete nella cartella lessons le precedenti lezioni in modo da poter seguire l’evolutiva del progetto

Lezioni