Když nám klient řekl, že chce nahradit svůj JSF frontend „moderní single-page aplikací”, měli jsme smíšené pocity. JavaScript v enterprise? Ale po roce s AngularJS 1.3 musím přiznat: Google udělal framework, který enterprise Java vývojáři dokáží přijmout za svůj.
Proč AngularJS (a ne Backbone nebo Ember)¶
V roce 2014 máte na výběr tři seriózní kandidáty pro enterprise SPA: Backbone.js, Ember.js a AngularJS. Backbone je minimalistický — dává vám svobodu, ale taky zodpovědnost za každé architektonické rozhodnutí. Ember je opinionated a výborný, ale komunita v Česku je malá. AngularJS vyhrál kombinací faktorů: silná podpora Google, two-way data binding, dependency injection (Java vývojáři znají z Springu) a obrovská komunita.
Klíčový argument pro náš tým: AngularJS se konceptuálně podobá tomu, co Java vývojáři znají. Moduly, services, dependency injection, testování přes Jasmine — to vše má paralely v Java světě. Křivka učení byla překvapivě mírná.
Architektura aplikace¶
Stavěli jsme interní CRM systém pro středně velkou firmu — asi 200 uživatelů, desítky obrazovek, komplexní formuláře, real-time notifikace. Architektura:
Frontend: AngularJS 1.3 + UI-Router + Bootstrap 3
Backend: Java EE 7, JAX-RS (Jersey), JPA (Hibernate)
API: RESTful JSON, JWT autentizace
Build: Grunt + Bower (frontend), Maven (backend)
Testy: Karma + Jasmine (unit), Protractor (E2E)
Rozhodli jsme se pro striktní oddělení frontendu a backendu. Frontend je statická aplikace servírovaná z Nginx, backend je čisté REST API na WildFly. Žádný JSP, žádný server-side rendering. Čistý kontrakt přes JSON API.
Co nás naučil AngularJS¶
Two-way data binding je skvělý — dokud není. Pro formuláře s deseti poli je to magie. Pro tabulku s tisíci řádky je to katastrofa. Každý $digest cycle prochází všechny watchery. S 2000+ watchery na stránce se aplikace začne sekat. Řešení: virtuální scrolling, one-time binding ({{ ::value }}) a track by v ng-repeat.
Direktivy jsou síla frameworku. Vytvořili jsme knihovnu reusable direktiv — datepicker, autocomplete, datová tabulka s filtrováním a řazením, formulářové validátory. Po třech měsících práce jsme měli komponentový systém, ze kterého nové obrazovky skládáme jako z kostek.
Služby a dependency injection. Angular services jsou přesně to, co Java vývojář očekává. Singleton instance, injektované přes konstruktor (resp. funkční parametry). AuthService, ApiService, NotificationService — struktura kódu je čitelná i pro kolegu, který na projektu nepracoval.
Integrace s Java backendem¶
REST API designované podle pragmatických principů — ne striktní HATEOAS, ale ani chaos. Konvence: substantiva v URL, HTTP metody pro operace, stránkování přes query parametry, chybové odpovědi ve standardním formátu.
// Angular service pro práci s kontakty
angular.module('crm').factory('ContactService', function($http) {
var api = '/api/v1/contacts';
return {
list: function(params) { return $http.get(api, {params: params}); },
get: function(id) { return $http.get(api + '/' + id); },
create: function(data) { return $http.post(api, data); },
update: function(id, d) { return $http.put(api + '/' + id, d); },
remove: function(id) { return $http.delete(api + '/' + id); }
};
});
JWT tokeny pro autentizaci — Angular interceptor přidává Authorization header ke každému requestu. Refresh token mechanismus řeší expiraci. CORS správně nastavený na backendu. Žádné session cookies, žádný server-side stav. Stateless architektura, která se krásně škáluje.
Testování — překvapivě dobré¶
Karma runner + Jasmine pro unit testy. Angular je navržený s testovatelností jako prioritou — $httpBackend pro mockování API, $provide pro nahrazení závislostí. Pokrytí máme na 78 % — víc než náš Java backend.
Protractor pro end-to-end testy. Selenium pod kapotou, ale s Angular-aware API. Automaticky čeká na dokončení $digest cycle a pending $http requestů. E2E testy běží v CI na Jenkins — headless Firefox přes Xvfb.
Bolesti a poučení¶
- IE 8 podpora — klient ji vyžadoval. AngularJS 1.3 ji oficálně dropnul. Kompromis: IE 9+ s polyfilly. Trvalo týdny přesvědčit stakeholders.
- SEO — pro interní aplikaci nepodstatné, ale pro budoucí veřejné projekty je SPA problém. Prerender.io nebo server-side rendering budeme muset řešit.
- Build tooling — Grunt + Bower funguje, ale ekosystém se mění rychle. Gulp přebírá, Browserify a Webpack klepou na dveře. Investice do build pipeline je nutná.
- Angular 2.0 — Google oznámil Angular 2.0, který nebude zpětně kompatibilní. To je pro enterprise projekt znepokojivé. Sledujeme situaci.
AngularJS v enterprise funguje¶
Po roce provozu máme stabilní, udržovatelnou a dobře testovanou aplikaci. AngularJS dal Java týmu strukturu a konvence, které znají. Není to bez problémů — performance s velkými datasety vyžaduje péči, budoucnost frameworku je nejistá. Ale pro rok 2014 je to nejlepší volba pro enterprise SPA, kterou máme.