Angular 2 pajahti finaaliin asti

Tämän päivän kiinnostava uutinen: Angular 2 on nyt Final, ei enää pelata RC tai Beta-versioilla.

http://angularjs.blogspot.fi/2016/09/angular2-final.html

Minulla on ollut ilo vuoden sisään veistellä ratkaisuja sekä Angular versiolla 1, Angular 2:lla, että Aurelialla. Näistä kolmesta Angular ykköstä en enää käyttäisi. Aureliassa on monta arkkitehtuurisesti ihastuttavaa asiaa, mutta monet kulmat tuntuvat vielä vähän puolivalmiilta. Voi johtua siitä, että se on vielä puolivalmis. Yksi närä on ylimääräisen jspm pakettimanagerin käyttö.

Angular 2 on tästä kolmikosta tuntunut käytössä parhaalta, jo esijulkaisuversioissa. Siinä on React-maista komponenttiajattelua: Ruutu on komponentti, joka pilkotaan osakomponentteihin, jne. Siinä on kaikki hyvä mitä oli Angular 1:ssä, mutta yksinkertaistettuna. Se vaatii välineiltä vähän enemmän, ja hauskasti ollaan tultu täysi kehä siinä miten yhdistetään html+css+javascript tai typescript koodit. Sen dokumentaatio on erinomaisella tolalla.

Odottelen innolla milloin pääsen taas viuhuttelemaan finaaliversion Angular kakkosta, ja tekemään lisää komponentteja.

https://angular.io/

Mainokset

Angular2 + NPM + Webpack

Lupailin kirjailla vähän lisää fiksusta Angular2 setupista tuotantohommiin. Tarkoitus oli tunkkailla minimaalinen paketti jossa on helppo erottaa eri tekniikoiden tehtävät. Valitettavasti Angular2 on aika liikkuva kohde tällä hetkellä – ja kiirettäkin on pitänyt, joten yksinkertainen POC projekti on jäänyt haaveeksi.

Onneksi joku muu on tehnyt sellaisen. Tällä hetkellä fiksuinta on aloittaa kokeilut ylläpidetystä Angular2 Webpack Starter projektista: https://github.com/AngularClass/angular2-webpack-starter

Valitettavasti tuo projekti ei ole yksinkertainen eikä siisti, mutta hoitaa homman. Ja se on kuitenkin hyvin linjassa sen kanssa mitä itse ajattelen. Angular2 kehittyy vauhdilla juuri nyt, ja joka releasen myötä se on siistimpi ja eheämpi ja vähemmän tarvitaan purkkaa taustalle. Sitä myöten voisin kuvitella että tämä webpack starterkin yksinkertaistuu.

Joka tapauksessa, vähän saatesanoja projektin suhteen. Senhän saa käyttöön nätisti kokeiluun (kun nodet on asennettuna), esim. näin:

 

git clone https://github.com/angularclass/angular2-webpack-starter.git
cd angular2-webpack-starter
npm install
npm start
curl http://localhost:3000

Curlin sijasta voit luonnollisesti tyypittää oikealla selaimella. Kuten kynäilin viimeksi, Bower on vähän menemässä muodista pois, samoin Grunt – paljon kuin sitä ja Gulpia rakastankin. Jos haluaa, voihan molempia noita käytellä vieläkin, ja voi olla joku tehtävä jossa Gulp voi olla esim. hyödyllinen. Mutta vanilla on päivän maku näissä asioissa, ja aikalailla paljon saa aikaan ihan vain puhtaalla JavaScriptillä ja NPM:llä.

Kannattaa luoda silmäys package.json tiedostoon. Se on tässä kaiken avain. Ja voi olla pelottava kokemus tässä vaiheessa jos on tottunut että se on vain kirjastomanifesti. Tosiaan devdependencies-lista on aika kattava näinkin yksinkertaiselle projektille, mutta tulee yksinkertaistumaan jatkossa. Ja toki siinä on jo aika kattavasti testaustyökaluja mukana. Pääjuju kuitenkin, että riippuvuudet on fiksuinta hakea kaikki npm keinoin, softan omat riippuvuudet ovat dependencies kohdassa, ja Boweria ei käytetä.

Mielenkiintoinen osio on kuitenkin scripts-osio. Vielä pari vuotta sitten oli tavanomaista että tämä oli tyhjä tai siinä oli 1-2 kohtaa, build ja test. Nyt tässä näkyy hyvin painopisteen muutos. Perinteiset grunt/gulp työvaiheet on nyt npm scripts työvaiheina, ja ne ovat modulaarisia ja ketjutettuja. Tarvittaessa käytetään noita dpm dev moduuleja, esim. rimraf poistaa tyylikkäästi tarvittavat hakemistopuut. Jos tuosta poimii muutaman mehukkaan ja keskeisen komennon niin ne ovat:

"clean": "npm cache clean && rimraf node_modules doc typings coverage dist"
"build:dev": "webpack --progress --profile --colors --display-error-details --display-cached"
"server:dev": "webpack-dev-server --progress --profile --colors --display-error-details --display-cached --content-base src/"

Näitä pääsee ajamaan komennolla npm run, esim.

npm run build:dev (ajaa kehitysversion buildin)

Samaan listaan on myös määritetty oikopolkuja yleisimpiin, esim:

"build": "npm run build:dev"
"server": "npm run server:dev"

Siinäpä nuo yleisimmät. Ja loput hoitaa webpack. Webpackillä on tässä kaksi keskeistä tehtävää: Tärkein on lähdekoodin prosessoiminen halutuksi paketiksi (sisältäen tarpeen mukaan babelifioinnit, minifioinnit, obfuskoinnit, jne), ja sen ohella myös sisäänrakennettu testiserveri on mukava. Konfiguraatiot käännöksiin löytyvät projektin juuresta, esim. tsconfig.json ja webpack.config.js. En pui niiden sisältöä tässä sen enempiä, mutta ne ovat aika selkeitä ja tehtäväänsä keskittyneitä. Ehkä hyvä mainita että toisin kuin Angularin omassa yksinkertaisessa tutoriaalissa, moduulijärjestelmänä SystemJS on korvattu CommonJS:llä.

Mitäpä muuta? Sain aiemman artikkelin suhteen vähän kommenttia/kysymystä tuosta Mavenin käytöstä. Itsehän tyypillisesti teen backendit Javalla/Spring Bootilla, ja frontend on vain osa kokonaisprojektia. Ja koska asiat on kiva pitää yksinkertaisena, samalla kun buildataan Mavenillä backend hyväksi, on mukava rusauttaa läpi myös frontend buildit. Käytän tähän tosiaan eirslett maven plugaria, joka voi yksinkertaisimmillaan näyttää tältä:

<plugin>
  <groupId>com.github.eirslett</groupId>
  <artifactId>frontend-maven-plugin</artifactId>
  <version>0.0.27</version>
  <executions>
    <execution>
      <id>install node and npm</id>
      <goals>
        <goal>install-node-and-npm</goal>
      </goals>
      <configuration>
        <nodeVersion>v5.5.0</nodeVersion>
        <npmVersion>3.3.12</npmVersion>
      </configuration>
    </execution>
    <execution>
      <id>npm install</id>
      <goals>
        <goal>npm</goal>
      </goals>
    </execution>
    <execution>
      <id>npm build</id>
      <goals>
        <goal>npm</goal>
      </goals>
      <configuration>
        <arguments>run build:prod</arguments>
      </configuration>
      <phase>compile</phase>
    </execution>
  </executions>
</plugin>

Käytännössä siis tuo tarkoittaa:

  • Varmista että node ja npm ovat asennettuna paikallisesti
  • Aja npm install
  • Aja npm run build:prod scripti – automaattisesti Mavenin Compile vaiheessa, eli samalla kuin backend kooditkin käännetään

Yksinkertaista. Webpack on konfiguroitu puskemaan prosessoidut .js tiedostot, html:t ja muut staattiset osat sopivaan kansioon, josta Mavenin paketointivaihe ne sitten nappaa mukaan .war pakettiin.

Huomaa että jos haluat ajaa Mavenin läpi muitakin npm taskeja, se onnistuu määrittämällä sopiva Maven property jonka voit komentoriviltä ylikirjoittaa, ja käyttämällä sitä tuon npm taskin konfiguraatiossa, esim. näin:

<execution>
  <id>npm build</id>
  <goals>
    <goal>npm</goal>
  </goals>
  <configuration>
    <arguments>${npm.argument}</arguments>
  </configuration>
  <phase>compile</phase>
</execution>

En kuitenkaan nykyisellään koe tälle erityistä tarvetta. Mavenin päätehtävä on varmistaa että riippumatta koneen varustuksesta paketti osaa buildata itsensä eheäksi itsenäisesti, oli sitten kyseessä Jenkins ympäristö tai uuden projektiin tulevan kehittäjän kone, tai vanhan devaajan uusi kone. Eli toiminta varmistetaan kaikissa olosuhteissa. Mutta noita muita npm käskyjä voi hyvin ajaa ohi mavenin esim. frontend-painotteisten kehittäjien toimesta, esim.watch on varsin hyödyllinen kun haluaa saada käyttöliittymäkehityksessä jatkuvaa palautetta. Siksi perusbuildi Mavenin kautta ajettuna usein riittää, ja oletuksena production buildi on tietysti hyvä.

Tässä mietteitä tällä kertaa. Matka vilkkaassa frontend maailmassa jatkuu….

 

 

Angular 2 aloitusopas

Jep, lupailin kirjailla jossain vaiheessa vähän Angular kakkosesta lisää, ja nyt on jossain vaiheessa. Alkuvaikutelmat hyvin positiiviset. En lähde vertailemaan Reactiin, molemmat oikein hyviä tekkialustoja, samoin Aurelia, mutta Angular ykkösen hakkaa iisisti kaikki kolme.

Ensiksi projekti pystyyn: Node ja NPM

Miten kannattaa aloitella? Itse sekoittelen Angularia useimmiten Java-pohjaisiin ratkaisuihin, joskus Nodeen. Joka tapauksessa, homma alkaa Java-puolella Maven Eirslett plugarilla joka varmistaa että kun Jenkins päräyttää buildin, buildikoneesta löytyy projekti-paikallisena asennettuna Node 5.3 ja npm. Paikallisena siksi että sama Jenkins voi tarvittaessa vedellä eri buildiversioita, ja on helppoa kokeilla voiko uuteen päivittää ilman oireita tms. Eirslett konffa tällä hetkellä Mavenin pom.xml:ssä näyttää tältä:

<plugin>
  <groupId>com.github.eirslett</groupId>
  <artifactId>frontend-maven-plugin</artifactId>
  <version>0.0.26</version>
  <executions>
    <execution>
      <id>install node and npm</id>
      <goals>
        <goal>install-node-and-npm</goal>
      </goals>
      <configuration>
        <nodeVersion>v5.3.0</nodeVersion>
        <npmVersion>3.3.6</npmVersion>
      </configuration>
    </execution>
    <execution>
      <id>npm install</id>
      <goals>
        <goal>npm</goal>
      </goals>
    </execution>
  </executions>
</plugin>

Sitten kirjastot kasaan

No niin, ajat mvn package tai asentelet noden ihan vain nvm:llä taikka käsin, ja siitä se lähtee. Angular kakkosen kanssa en käytä enää Boweria, se on muutenkin mennyt vähän suosiosta. En ole vielä törmännyt juttuun johon ei npm riitä. Asiaa helpottaa, että Angular kakkoselle ei ole vielä niin paljoa sisältöä, ja saa varautua pioneerihengessä vähän rakentelemaan itse melko karuista komponenteista. Joka tapauksessa, tuikataan package.json pystyyn esim. tähän tapaan:

npm init
npm install --save angular2 es6-promise es6-shim@0.33.3 reflect-metadata@0.1.2 rxjs@5.0.0-beta.0 zone.js systemjs

Noilla pääsee alkuun. Toki angular2 riittäisi, mutta nykyisellään näkee kaipaavan pari lisäkirjastoa kaverikseen, liittyen ES6 tukipalveluihin ja vanhojen selainten tukeen. Nykyisellään Angular2 on vähän versiotarkka, siksi versionumerot yllä – korjaantunee rennommaksi jahka päästään irti betasta. Laitetaan myös pari työkalua buildaukseen:

npm install --save-dev concurrently lite-server typescript

Angular 2 on vahvasti suuntautunut TypeScriptin suuntaan – toki sallitaan myös JavaScript, mutta TypeScript on ihanaa! Joten lähdetään alkuun rakentamalla pari asiaa.

Hakemistorakenne ja tiedostot

Tarvitaan perinteinen index.html, bootstrap, sekä ainakin yksi komponentti. Eli tehdään ihan angular2 tutorialin mukainen hakemistorakenne:

touch index.html
mkdir app
touch app/app.component.ts
touch app/boot.ts

Ensin index.html – sinne tarvitaan perus sivurakenne, sekä kirjastojen lataus. Jostain syystä wordpress tänään nikottelee reippaasti eikä anna laittaa tähän kohtaan koko sivua edes pre-tagien avulla. Joten selitän mitä tarvitaan. Otetaan pohjaksi normaali HTML sivu:

<html>
 <head>
 <title>Blogautus</title>
 </head>
 <body>
 <my-app>Loading...</my-app>
 </body>
</html>

Tähän tarvitaan muutama script-tagi. Ensin head-tagien välissä lataa seuraavat kirjastot script-tagein:

node_modules/angular2/bundles/angular2-polyfills.js
node_modules/systemjs/dist/system.src.js
node_modules/rxjs/bundles/Rx.js
node_modules/angular2/bundles/angular2.dev.js

Sitten laitetaan Angular2 bootstrap kohta, myös script-tagien väliin:

 System.config({
   packages: { 
   app: {
     format: 'register',
     defaultExtension: 'js'
   }
 }
 });
 System.import('app/boot')
   .then(null, console.error.bind(console));

Ja lisäile vapaasti kaikki muu mitä haluat. Sivulla ladataan tässä vaiheessa kaikki scriptit, sitten homma käynnistyy app-kansion boot-moduulista, mitä ikinä tekeekään. Tässä tapauksessa potkaisee ensimmäisen, my-app komponentin käyntiin, näin:

import {bootstrap} from 'angular2/platform/browser'
import {AppComponent} from './app.component'
bootstrap(AppComponent);

Siinä oli siis boot.ts tiedosto. Angular2 pohjautuu ES6 malliin ja tuo sieltä hyviä piirteitä mukaan, kuten esim. moduulit. Bootstrap koodi ottaa käyttöön Angular2 bootstrap funktion, ja lataa app-kansiosta component moduulin, ja käynnistää sen. Siitä käynnistyy kaikki muu. Component.ts tiedosto voi näyttää vaikkapa tältä:

import {Component} from 'angular2/core';
@Component({
 selector: 'my-app',
 template: '<h1>Blogautus</h1>'
})
export class AppComponent { }

Tätä  on ehkä jo helpompaa seurata aiemman pohjalta. Käyttöön Component niminen kapistus, jota Angularissa kutsutaan decoratoriksi, mutta muistuttaa myös muiden kielten annotaatiota/metadataa. Tässä tapauksessa on tyhjä komponenttiluokka, johon decorator lisää metadataa kuten komponentin tag-koodin (selector), ja template-osion, jossa on komponentin generoima koodi. Komponenttiluokka itse on tässä tyhjä koska ei ole vielä tilaa eikä funktioita.

Angular ykkösen kanssa puuhastelleet saattavat huomata että tämähän muistuttaa jollain lailla direktiiviä – ja se on totta. Mutta angular ykkösen direktiivi oli aikamoinen hirvitys jota useimmat käyttivät väärin. Angular kakkosen komponentti on lähtökohdiltaan yksinkertainen ja helpommin käytettävä.

Tässä voi myös huomata että jos template-osio on pidempi, voidaan käyttää sensijaan templateUrl-parametria, ja hakea template erillisestä tiedostosta. Tähän ei kuitenkaan kannata haksahtaa – IT’S A TRAP! Suurikokoinen template on nimittäin Code Smells-kohta – oiretta siitä että komponentti kannattaisi rikkoa alikomponenteiksi. Tämä on nimittäin Angular kakkosen yksi parhaista oivalluksista – ja muistuttaa paljon React ajattelutapaa. Sivu on komponentti, joka koostuu komponenteista, jotka koostuvat komponenteista, jotka ovat kaikki uudelleenkäytettäviä, testattavia, ja pieni.

Buildaus ja ajaminen

No niin, mitä tarvitaan että tämän voi pistää prosessoiden ja ajaen? Ensin tarvitaan typescript konfiguraatio ja käännös, esim. näin:

node_modules/.bin/tsc --init
node_modules/.bin/tsc

Ensimmäinen luo tsconfig.json tiedoston, jota voit editoida halusi mukaan. Se määrittää miten typescriptiä prosessoidaan Javascriptiksi. Toinen kääntää koodit. Voi olla että haluat muokata vähän tsconfig.json tiedostoa, tässä versio mitä angular tutorial käyttää:

{
 "compilerOptions": {
 "target": "ES5",
 "module": "system",
 "moduleResolution": "node",
 "sourceMap": true,
 "emitDecoratorMetadata": true,
 "experimentalDecorators": true,
 "removeComments": false,
 "noImplicitAny": false
 },
 "exclude": [
 "node_modules"
 ]
}

Alunperäinen tiedosto generoi ES3 tasoista kamaa, ja laittoi ne built-kansion alle. Nyt jos ajat tsc-kääntäjän uudestaan, tulee vähän modernimpaa tavaraa, samoihin kansioihin .ts alle. Joka ei ole hyvä, mutta palataan siihen myöhemmin. Se on nyt aluksi helppo. Voit poistaa built-kansion.

Mitäs vielä? Olisi kiva varmaan ajaa ja testata koodia vähän. Se onnistuu ajamalla:

node_modules/.bin/lite-server

Kevyt testiserveri käynnistyy porttiin 3000 ja avaa selaimen näyttämään mitä sieltä löytyy.

Screenshot 2016-01-17 20.59.28.png

Jep, ei ole vielä kovin kummoinen, mutta on se alku. Angular tutorialin tapaan voit vielä laittaa kääntämisen ja ajamisen fiksummin package.jsoniin npm taskeiksi, tähän tapaan:

 "scripts": {
  "tsc": "tsc",
  "tsc:w": "tsc -w",
  "lite": "lite-server",
  "start": "concurrent \"npm run tsc:w\" \"npm run lite\" "
 }

Tässä tulee käyttöön concurrent-moduuli, joka ajaa rinnakkain kahta taskia. tsc -w valvoo muutoksia kansioihin ja uudelleekääntää muuttuneet tiedostot. lite-serveri valvoo koodia ja virkistää selaimen kun käännetyt koodit ovat muuttuneet. Voit ajaa tässä kehitysmoodissa komennolla:

npm start

Kokeile vaikka! Tämä on jo aika päheä setti, mutta toisaalta vain ensi osa Angular2 omissa tutorialeissa – ehkä hiukan eri vinkkelistä selitettynä vain. Mutta se on hyvä alku ponnistaa, ja ajattelin kirjailla jatkossa lisää esim. testauksesta ja webpack käytöstä Angular2 kanssa. Saatan myös avautua siitä miksi TypeScript on ihanampaa kuin JavaScript, ja miten homma pelittää vanhemmissa selaimissa.

Oma mielipide siis on ytimekkäästi:

+++Angular2
+++Node5 ja npm
+++Webpack
+++Typescript

Lue myös: https://angular.io/docs/ts/latest/quickstart.html