Node.js, grunt-express, ja json-proxy

Tuli ajankohtaiseksi säätää grunt-express testiserveri toimimaan proxyn kera. Yllättävän vaikea homma, grunt connectille oli jo valmiina esimerkkejä mutta kun olin rakentanut express serverin varaan jo aika paljon, sille ei tietysti löytynyt hyviä proxy-esimerkkejä. Ja suora soveltaminen connect oppaista ei auttanut.

Lopulta onnistui json-proxyn kanssa. Käännekohta oli hoksata että middleware-parametri, joka on Connectilla olio, on Expressillä taulukko. Tässä toimiva ratkaisu:

express: {
  all: {
    options: {
      port: 9000,
      hostname: "0.0.0.0",
      bases: [path.resolve('.')], 
      livereload: true,
      middleware: [
        require('json-proxy').initialize({
         proxy: {
           forward: {
             '/google': 'http://www.google.com/',
           },
           headers: {
             'X-Forwarded-User': 'Express Proxy'
           }
         }
       })
     ]
  }
}
}

Ja tietysti sopivassa kohtaa aiemmin:

var path = require(’path’);

Huomaa että tuossa ratkaisussa kaikki /google alkuiset menevät siis http://www.google.com/google osoitteeseen. Proxy näyttäisi kumminkin toimivan hienosti, ja proxyttelee toki muutakin kuin vain jsonia.

 

Java 8 SE Final Raspberry PI:hin

No niin, ehdin taas puuhastella kotiprojektin kimpussa. Asensin jo aikanaan Java 8 prereleasen Raspberry Pi:hini, pyörittelin sillä MongoDB:tä ja Glassfish 4:sta, ja rakentelin EJB:llä ja JAX-RS palveluilla releitä ohjaavaa koti-aivoa.

Nyt oli hetki aikaa päivittää finaaliversio, ja RasPille tosiaan Hard Float. Ei sillä että prerelerasenkaan kanssa olisi ollut ongelmia. Prosessi meni siis näin:

sudo apt-get update && sudo apt-get install oracle-java8-jdk

 

Easy 😉 Toki vanhat moskat voi poistaa ensin jos on käsin asennellut jotain. Itselläni lähti /opt/java menemään, tuo paketti asentelee näemmä oletuksena /usr/lib/jvm alle.

Hyvä tarkistaa ajamalla vielä:

javac -version
java -version

No melkein. Jostain syystä java ei linkittynyt tuolla paketilla /usr/bin/java alle. Ihan kaikki muut tärkeät JDK vimpaimet kyllä mukaanlukien jconsole ja jar ja javac. Joten tein käsin uuden linkin:

sudo update-alternatives --install /usr/bin/java java /usr/lib/jvm/jdk-8-oracle-arm-vfp-hflt/jre/bin/java 1
sudo update-alternatives --config java

Ja valitaan haluttu versio – varmaankin hyvä idea ottaa sama kuin ensimmäisellä komennolla. Testataan taas.

pi@romanov ~ $ java -version
java version "1.8.0"
Java(TM) SE Runtime Environment (build 1.8.0-b132)
Java HotSpot(TM) Client VM (build 25.0-b70, mixed mode)

 

Ja hienosti pelittää! Ei muuta kuin Glassfish uudelleen käyntiin.

 

 

Grunt siistimmäksi

Kun AngularJs/Yeoman projekteissa puuhailee aikansa, Grunt tiedostosta voi tulla aikamoinen. Itse näen punaista kun näen satoja rivejä pitkän projektille keskeisen tiedoston jossa on kaiken lisäksi vielä useita sisäkkäisiä lohko ja taulukkorakenteita. Se tulee ampumaan jalkaan ylläpito ja bugimielessä hyvinkin pian.

Satuin törmäämään mukavaan artikkeliin koskien Gruntin siistimistä. Ideana on purkaa Taskit omaan /tasks alikansioon ja ladata ne sieltä automaattisesti. Vielä mukavampaa on purkaa kaikkien taskien optiot tasks/options alikansioon. Tässä esim. clean optiot (tasks/options/clean.js):

module.exports = {
  publish: {
    src: ['./publish/**']
  }
};

Jep, nämä toistavat isäntädokumentin module.exports rakennetta. Itse plug-inin nimeä ei tässä ole, se ratkeaa suoraan tiedoston nimen perusteella, eli tässä on siis clean plug-inin optioita säädetty.

Tässä esimerkki task:sta nimeltä server (tasks/server.js):

module.exports = function (grunt) {
 grunt.registerTask('server', [
 'express',
 'open',
 'watch'
 ]);
};

Ja tässä lopullinen gruntfile.js päähakemistosta:

module.exports = function(grunt) {
 
  // Load Grunt options automatically from tasks/options folder
  function loadConfig(path) {
    var glob = require('glob');
    var object = {};
    var key;
    glob.sync('*', {cwd: path}).forEach(function(option) {
      key = option.replace(/\.js$/,'');
      object[key] = require(path + option);
    });
    return object;
  }

  var config = { 
    pkg: grunt.file.readJSON('package.json'),
    env: process.env
  };

  grunt.util._.extend(config, loadConfig('./tasks/options/'));
  grunt.initConfig(config);
  
  // Load Grunt tasks automatically from tasks folder 
  require('load-grunt-tasks')(grunt);
  
  grunt.loadTasks("tasks");
};

Alkuperäinen Grunt oli tässä vaiheessa jo 304 riviä pitkä, ja kasvamaan päin, ja sisäkkäisten lohkojen määrä…. ai jai jai!

Samalla on tosiaan hyvä pistää Grunt lataamaan taskit automaattisesti sensijaan että ne ladataan manuaalisesti. Huomaa tuossa yllä load-grunt-tasks moduuli, joka hoitaa homman, kunhan taskin alussa on: ’grunt-’.

Eli ristiretkellä kohden parempaa tuottavuutta ja koodin hallintaa, jälleen lisää niksejä. Kunnia tästä ei mene itselle, itse vain testatin ja toimivaksi havaitsin. Alkuperäinen artikkeli tässä:

http://www.thomasboyt.com/2013/09/01/maintainable-grunt.html

 

AngularJS Grunt livereload

Leikkiessäni AngularJS:llä ja Gruntilla tuli tarpeelliseksi pohtia nopeampaa workflowta editointiin kuin raskas Maven build joka kerta kun Javascript komennon puolipistettä viilaa. Grunt tarjoaa tähän montakin tapaa, mutta löysin artikkelin jossa oli mainittu toimivaa tavaraa.

Ensin ladataan package.json tiedostossa npm:n toimesta kaikki tarvittavat moduulit, esim. tähän tapaan:

{
 "name": "MyProject",
 "version": "0.0.0",
 "devDependencies": {
 "grunt": "latest",
 "matchdep": "latest",
 "grunt-contrib-clean": "latest",
 "grunt-contrib-watch": "latest",
 "grunt-open": "latest",
 "grunt-express": "latest",

… jne

Sitten mennään gruntfile.js puolelle, ja tehdään vähän taikuutta: ladataan kaikki grunt- alkuiset kirjastot:

require('matchdep').filterDev('grunt-*').forEach(grunt.loadNpmTasks);

Ja nyt voidaan grunttailla watch, open ja express moduulien kanssa. Esim. näin:

var path = require('path')
 module.exports = function (grunt) {
 grunt.initConfig({
 express: {
 all: {
 options: {
 port: 9000,
 hostname: "0.0.0.0",
 bases: [ path.resolve('.') ],
 livereload: true
 }
 }
 },
 watch: {
 static: {
 files: ['index.html'],
 options: {
 livereload: true,
 }
 },
 js: {
 files: ['app/*.js'],
 //tasks: ['concat:js', 'uglify:js'],
 options: {
 livereload: true,
 }
 },
 css: {
 files: ['content/*.less'],
 // tasks: ['less:style'],
 options: {
 livereload: true,
 }
 }
 },
 open: {
 all: {
 path: 'http://localhost:<%= express.all.options.port%>'
 }
 }
 //... etc
 })

Ja lopuksi mukava pikku server task:

// Creates the `server` task
 grunt.registerTask('server', [
 'express',
 'open',
 'watch'
 ]);

Kaikki nipussa: nyt voi sanoa: grunt server, ja grunt potkaisee käyntiin porttiin 9000 pikku serverin joka jakelee prosessoimattomat sivut, scriptit ja muut suoraan käyttöön, avaa selaimen, ja vahtii muutoksia filuihin. Kun tiedostot muuttuvat, nimensä mukaisesti livereload lataa ne uudestaan.

Mikä on kuitenkin metkointa on ylläolevan esimerkin tasks-parametrit: muutoksen yhteydessä voidaan ajaa haluttuja prosessointeja raa’alle lähdekoodille samantien.

Hauskaa! 😉

 

Lähde kokeiluihin:

http://rhumaric.com/2013/07/renewing-the-grunt-livereload-magic/

Pistä Netbeans Git:isemään!

Devaaja joutuu/pääsee päivän aikana tekemään update/commit tai commit/pull/push syklejä aika monta kertaa. Netbeansin oletus tälle on hieman raivostuttava wizardi joka kyselee kaikenlaista.

Onneksi pull/push upstream eivät pahemmin kysele kunhan versiohaara on jo määritelty ja remote repository paikallaan (Git)ssä. Vielä maukkaampaa on määritellä näille pikanäppäimet joilla voi paukutella commit/pull/push syklin ajatusta nopeammin.

Kuva

Ja taas säästyi devaajilta aikaa parempaan – kuten itsensä ihailuun ja kahvin juontiin 😉 No ei vain, vaikka nykyajan kehitysvälineet automatisoivat paljon ja suorastaan kirjoittavat koodin itsekseen jonkun pitää toki vielä kirjoittaa ne kolme ensimmäistä kirjainta ja painaa Ctrl+Space.

Netbeans Maven actionien pika-ajo

Huomasin Netbeansiä tutkiessani uuden mukavan piirteen Mavenin suhteen. Yksi mitä on ollut vähän kiven takana on ollut kyky ajaa mielikuvituksellisempiakin tehtäviä Netbeansistä kuin vain package, install, test. Nämähän löytyvät oikean hiirennapin takaa. Olisi myös kiva pystyä säätämään ympäristömuuttujia ja vaihtamaan profiileja helposti.

Vaivihkaa Netbeansiin onkin hiipinyt tämä toiminta. Jos avaat Maven-projektin asetukset (properties), kohdassa Configurations löytyy erilaisia konfiguraatioita, moodeja, joille voi tehdä eri tehtäviä. Konfiguraatio taas on helposti Netbeansissä vaihdettavissa yläpalkista.

Kun konfiguraatio on valittu aktiiviseksi, voit editoida sen Actioneitä kohdasta Actions samoin projektin asetuksissa. Voit myös editoida ihan oletus-konfiguraation toimintoja suoraan samasta paikkaa.

Netbeans projektin Maven Actions näkymä

Tässä listassa on erilaisia tehtäviä jotka ajavat Maven taskeja. Voit editoida niitä, tyhjentää niiden sisällön, tai lisätä ihan uusia. Joka actioniin liittyy myös mahdollisuus säätää komentoriviparametreja.

Pikavalikko Custom actioneille

Lisäämäsi custom actionit ilmestyvät sitten oikean hiirennapin alle kun projektia klikkaat, kohtaan custom action. Cool stuff? 😉

 

 

Maven pistää AngularJS:n Grunttimaan

Viime aikoina olen viettänyt enemmänkin aikaa JavaScriptin uuden aallon kirjastojen parissa, joista nimekkäimpiä varmaan AngularJS. Toisin kuin ennen vanhaan, JavaScriptiä ei nykyisellään van kirjoiteta. Siihen liittyy minifiointia, uglifiointia, tyylisivujen prosessointia, ja se on kasvanut vaatimaan build työkaluja kuten Javakin.

Grunt on yksi AngularJS:n suosituimpia build välineitä, se on vastaava kapistus kuin Maven Javalle jotakuinkin, ja aika nerokaskin. Mutta entäpä jos haluttaisiin saada aikaan yksi buildi CI palvelimelle, jossa voi kerralla tehdä asennukset, testaukset ja muut?

Maven tukee Grunt buildin ajoa moninkin tavoin, löysin lukuisia plug-ineita siihen ja Mavenhan kykenee ajamaan maven exec ja antrun taskien avulla muutenkin mitä vain komentoriviltä. Mutta haaviin jäi itselleni lopulta Eirslett Maven plug-in joka jotakuinkin teki kaiken mitä tarvitsin. Vaihtoehtoja oli monia, yksi mikä tässä houkutti oli fiksu tapa kyetä ajamaan npm ja grunt taskit ilman globaalia asennusta, joka taas saa buildit sujumaan CI palvelimella ilman kummempia kikkailuja.

https://github.com/eirslett/frontend-maven-plugin

Muita vaihtoehtoja mitä katsoin tässä, etenkin ensimmäinen näistä, Allegro plug-in, oli lupaava:

https://github.com/allegro/grunt-maven-plugin

http://addyosmani.com/blog/making-maven-grunt/

No niin, tein siis Maven Java web app pohjan, otin siis Eirslett plug-inin käyttöön build-osiossa näin:

<plugin>
 <groupId>com.github.eirslett</groupId>
 <artifactId>frontend-maven-plugin</artifactId>
 <version>0.0.14</version>
 <configuration>
 <workingDirectory>src/main/frontend</workingDirectory>
 </configuration>
 <executions>
   <execution>
     <id>install node and npm</id>
     <goals>
       <goal>install-node-and-npm</goal>
     </goals>
     <configuration>
       <nodeVersion>v0.11.12</nodeVersion>
       <npmVersion>1.4.6</npmVersion>
     </configuration>
   </execution>
   <execution>
     <id>npm install</id>
     <goals>
       <goal>npm</goal>
     </goals>
   </execution>
   <execution>
     <id>grunt build</id>
     <goals>
       <goal>grunt</goal>
     </goals>
     <configuration>
       <arguments>${grunt.args}</arguments>
     </configuration>
   </execution> 
  </executions>
  </plugin>
</plugins>

Tuossa listassa on huomattavaa lähinnä grunt.args muuttuja, joka on asetettu ylempänä näin:

<properties>
 <endorsed.dir>${project.build.directory}/endorsed</endorsed.dir>
 <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
 <grunt.args>debug --no-color</grunt.args>
 </properties>

… mutta sen voi myös komentoriviltä ja Netbeansistä asettaa esim.

mvn -Dgrunt.args=release clean install

Cool stuff? Jenkins rouskuttaa ihan iloisesti nyt niin Java server-side kuin AngularJS kilkkeetkin yhdessä synkassa, ajaen myös testit.