Johdanto JavaScript-sovellusten kehitykseen Node.js:llä

Jaakko Salonen (@jsalonen)

5.6.2012 (päivitetty 17.9.2012)

Johdanto

Tässä artikkelissa kuvataan johdanto JavaScript-sovellusten kehitykseen Node.js:llä. Artikkeli käy läpi esittelynomaisesti kaikki vaiheet kokonaisen JavaScript-sovelluksen toteuttamiseksi node.js:llä. Oletuksena on, että lukija ymmärtää perusteet JavaScript-kielestä. Hyvä opas JavaScript-ohjelmointiin taustaksi on esimerkiksi JavaScript-puutarhan tarjoama dokumentaatio (http://bonsaiden.github.com/JavaScript-Garden/fi/).

Sisällys

  1. IDE-ympäristöt
    1. Sublime Text 2
    2. Jetbrains WebStorm
    3. Eclipse JavaScript-tuella
    4. Selainpohjaiset kehitysympäristöt (Cloud 9 IDE, Nide)
  2. Git
  3. Node.js
    1. NPM
  4. Yksinkertaisen web-sovelluksen toteutus
  5. Node-sovellusten julkaiseminen
    1. LAMP ja jaetut palvelinympäristöt
    2. Julkaisu pilvialustalle
    3. Julkaisu omalla palvelimella (Linux)
      1. forever
      2. upstart

1. IDE-ympäristöt

JavaScript-palvelinsovellusten kehitys ei vaadi komentoriviä ja perustekstieditoria kummallisempia välineitä. Kehittyneet tekstieditorit ja IDE-ympäristöt voivat kuitenkin helpottaa sovelluskehitystä merkittävästi. Käymme läpi muutamia tällaisia vaihtoehtoja.

1.1. Sublime Text 2

Sublime Text on tekstieditori, johon on tuotu laajasti sovelluskehitystä helpottavia ominaisuuksia. Omalla kokemuksellani Sublime Text 2 on tällä hetkellä parasta, mitä näissä on tarjolla. Sovellus toimii sekä Windows, Linux että Mac-ympäristöissä. Sublime Text on maksullinen; sitä voi testata, mutta pidemmän päälle se kannattaa ostaa. Hinta ei päätä huimaa. Editorin tehokäyttö vaatii opettelua, mutta tuo työhön lisää tehokkuutta.

Linkkivinkkejä:

1.2. Jetbrains WebStorm

Jetbrains WebStorm on täysiverinen JavaScript IDE. Ympäristö tarjoaa IDE:lle tyypillisesti älykkäitä lisäpiirteitä, kuten koodin automaattisen käännöksen ja täydentämisen, refaktoroinnin sekä rakenteiset näkymät lähdekoodiin. IDE tukee myös Node.js:ää (1] sekä JavaScript-yksikkötestausta. Tuki git-versionhallinnalle löytyy ympäristöstä valmiina.

WebStorm on saatavilla 30-päivän kokeiluversiona (http://www.jetbrains.com/webstorm/). WebStorm on Sublimea hieman kalliimpi (hinta n. 100 € / kehittäjä).

1.3. Eclipse

Myös Eclipse saa sopivilla moduuleilla konfiguroitua JavaScript-kehitykseen soveltuvaksi:

Eclipse on ilmainen, mutta sen konfigurointi ja käyttöönotto on muita ympäristöjä haastavampaa. Myös helppokäyttöisyys jättää toivomisen varaa. Hyvänä puolena ilmaisuuden lisäksi Eclipsessä on sen joustavuus: alustan saa konfiguroitua myös erilaisiin sovelluskehitystarpeisiin.

Esitellyistä vaihtoehdoista Eclipse on ainoa, joka on täysin ilmainen. Toisaalta Eclipse on myös selvästi kankein ja tarjoaa vähiten hyötyjä sovelluskehitykseen. Käyttö voi kuitenkin tulla kysymykseen erityisesti silloin, kun samalla ympäristöllä halutaan kehittää useita erityyppisiä ohjelmistoja.

1.4. Selainpohjaiset kehitysympäristöt

Vaihtoehtona paikallisesti asennettaville kehitysympäristöille on sovelluskehitysympäristön ajaminen selainpohjaisesti tai pilvipalveluna. Kehitysympäristön käyttö pilvipalveluna on keveä ratkaisu, jossa kehitysympäristöä on helppo käyttää mistä tahansa. Haasteina keskitetyissä pilviympäristöissä on riippuvuus verkkoyhteydestä, sekä ulkoisesta toimijasta kehitystyössä.

Cloud9 IDE (http://c9.io) on täysiverinen node.js-kehitys ja -ajoympäristö, joka toimii kokonaan selaimella. Avoimen lähdekoodin sovellusprojekteihin Cloud9 on maksuton. Suljettuihin projekteihin ympäristö on ostettavissa käyttöön kuukausimaksuperustaisesti (http://c9.io/site/pricing/). Cloud9 sisältää myös versionhallintajärjestelmän ja integroituu node.js:n julkaisupalveluihin, jolloin koko kehitystyö voidaan tehdä alusta loppuun asti samassa ympäristössä ilman ulkoisia järjestelmiä.

2. Git

Git on avoimen lähdekoodin hajautettu versionhallintajärjestelmä. Käytämme Git:iä erityisesti siksi, että se mahdollistaa 1) koko versiohistorian käsittelyn paikallisesti ilman keskitettyä palvelinta (ja internet-yhteyttä), 2) muutosten tarkan tallennuksen ja helpon yhdistämisen useiden repositorien välillä, sekä 3) Git:n avulla voidaan integroitua erilaisiin deployment-ratkaisuihin helposti (Heroku, CI-työvälineet). Git:n eduksi voidaan katsoa myös mahdollisuus tehdä helposti tuotanto- ja staging-ympäristöjen kautta muutoksia sovelluksiin hallitusti.

Git:n käyttöönotto riippuu IDE-ympäristöstä: tekstieditorien ja kevyiden IDE-ympäristöjen kanssa tarvitset Git:n komentorivityökalun. Varsinaiset IDE-ympäristöt tarjoavat Git:n laajennuksena -- katso tällöin oman ympäristösi tarkka ohjeistus

2.1. Komentorivi Git:n asentaminen ja käyttöönotto:

Lyhyt oppimäärä Git-komentorivin käyttöön:

3. Node.js

Node.js on suhteellisen tuore - ja rehellisesti sanoen - vielä kovaa tahtia kypsyvä kirjasto. Palvelinpään JavaScript-ajoympäristöistä Node.js on tällä hetkellä selvästi pisimmälle viety. Tietyllä tavalla parhaimmillaan node.js on silloin, kun se voidaan ylläpitää pilvialustoilla: sen tekniset vaatimukset ovat melko niukat, jolloin kevytkin pilvialusta riittää hyvin suorituskykyisen node.js-palvelun ylläpitämiseen. Perinteisistä sovelluskehyksistä node.js poikkeaa myös siten, että se on vahvasti tapahtumavetoinen: sovellukset ohjelmoidaan nodelle lähtökohtaisesti asynkronisesti callback-mekanismien pohjalle. Etuna tässä on, että esimerkiksi yksittäisiin HTTP-pyyntöihin voidaan helposti kytkeä useita asynkronisia palvelukutsuja. Toinen merkittävä etu node:ssa on JavaScript-olioiden helppo sarjallistaminen sekä tietokannasta että selaimessa toimivista asiakassovelluksista. Näistä syistä myös reaaliaikaisten sovellusten ohjelmointi on poikkeuksellisen helppoa. Haastavaa noden käytöstä tekee sen, että callback-kutsuista voi helposti muodostua pitkiä, vaikeasti ymmärrettäviä ketjuja. Tätä "callback-viidakon" ongelmaa ratkotaan aktiivisesti (esimerkki: common-node).

Toimi seuraavasti:

Lataa ja asenna node.js:

http://nodejs.org/

Testaa, että node.js toimii oikein. Avaa komentorivi ja kirjoita:

node -v

Jos kaikki menee hyvin saat tulosteen tyyliin:

v0.8.8

Saat node.js-tulkin auki kirjoittamalla

node

Käytännössä node.js on siis JavaScript-tulkki. Hello world -esimerkki:

> console.log('Hello World!')
Hello World!
undefined

JavaScript-sovelluksia ajetaan node:lla vastaavasti. Esimerkiksi:

node helloworld.js

Sovellukset, kuten myös konsolin, saa suljettu Ctrl+C:llä.

Node.js:n keskeinen dokumentaatio: http://nodejs.org/api/

Käytännössä node-sovelluksien asennus pysyvästi palvelimelle vaatii hieman lisätyötä. Yksittäinen node-sovellus käyttää (nykyisin) ainoastaan yhtä säiettä. Jos sovellus jostain syystä kaatuu tai heittää poikkeuksen, jota ei oteta kiinni, se pysähtyy. Node on ainoastaan kevyt, tapahtumapohjainen JavaScript-ajoympäristö. Jos node:lla halutaan toteuttaa verkkosovelluksia, kannattaa käyttöön lisäksi ottaa jonkinlainen web-sovelluskehys, kuten express.js (http://expressjs.com/). Vastaavasti myös palvelinasennus kannattaa järjestää siten, että sovellus tarvittaessa skaalautuu suuremmille käyttäjämäärille ja että node-sovelluksia ajetaan siten, että ne ovat vikasietoisia.

3.1. NPM

NPM (http://npmjs.org/) on node:n oma pakettienhallintajärjestelmä. Koko idea node:ssa on että sen ydin on kevyt ja mahdollisimman suurin osa toiminnallisuudesta saadaan ulkoisten pakettien avulla käyttöön. Tästä syystä npm:n käyttö ja sen ymmärtäminen on välttämätöntä node:n käytölle.

Varmista, että npm asennettu oikein kirjoittamalla:

npm -v

Tulosteena saat tiedon npm:n versiosta, esimerkiksi:

1.1.59

Omalla kokemuksellani npm on monipuolisin ja tehokkain pakettienhallintajärjestelmä, mitä olen ikinä käyttänyt. Esimerkiksi pakettien väliset riippuvuudet voidaan hallita moduulikohtaisesti ja riippuvuudet asentuvat automaattisesti. Lisäksi yksittäinen sovellus voi sisältää komponenttiensa kautta riippuvuuksia samojen kirjastojen eri versioihin, vaikka versiot olisivat keskenään epäyhteensopivia. Versioinnista saa myös semanttisen semver-lisäsovelluksella (http://npmjs.org/doc/semver.html). Myös pakettien listaus ja poistaminen ovat triviaaleja toimenpiteitä npm:llä.

Listaa kaikki asennetut paketit (suhteessa työhakemistoon):

npm list

Asenna express.js:

npm install express

npm asentaa paketit aina node_modules-kansioon, riippuen valitsimista ja työhakemistosta:

Kun npm:llä asennettuja paketteja käytetään osana sovelluksia, etsitään soveltuvaa pakettien vastaavassa järjestyksessä: ensisijaisesti ladataan projektikohtainen paketti ja vasta sen jälkeen haetaan vaihtoehtoja ylätason kansioista sekä globaaleista paketeista.

Lisävinkkejä npm:n käyttöön:

4. Yksinkertaisen web-sovelluksen toteutus

Käydään lopuksi läpi yksinkertaisen web-sovelluksen toteutus JavaScript-palvelinsovelluksena node.js:n avulla. Käytämme sovelluksen toteutukseen express.js-sovelluskehystä (http://expressjs.com). Kattavampi opas kehyksen käyttöön löytyy sen omaasta oppaasta (http://expressjs.com/guide.html).

4.1. Toteutus

Asenna express.js:

npm install express

Uuden projektin luonti tapahtuu komennolla express:

express hellojs
cd hellojs

Projektin luonnin yhteydessä sovellukselle luodaan oletuksena seuraavanlainen runko:

public/
routes/
views/
app.js
package.json

Runkoa sovelletaan seuraavasti:

Jotta voit kokeilla luomaasi sovellusta on sinun ensin kuitenkin asennettava siihen liittyvät riippuvuudet komennolla:

npm install -d

Esimerkiksi jade on ulkoinen riippuvuus, joka pitää tällä tavalla asentaa.

Pääset nyt testaamaan sovellustasi ajamalla sen node:lla.

node app.js

Avaa sovellus selaimeesi syöttämällä siihen osoite http://localhost:3000/

Linkkivinkkejä Express.js-sovelluskehykseen:

4.2. Sovelluksen laajentaminen kirjastoilla

Suosituksia kirjastoista käytettäväksi Express.js:n kanssa:

5. Node-sovellusten julkaiseminen

5.1. LAMP ja jaetut palvelinympäristöt

Node.js-sovelluksien julkaiseminen web-palveluna on poikkeuksellisen hankalaa. Tyypillisesti erityisesti jaetuissa palvelinympäristöissä ylläpidetään valmista LAMP-pinoa (Linux, Apache, MySQL, PHP). Käytännössä node on asennettava palvelimelle näiden rinnalle. Node sisältää itsessään jo myös web-palvelimen, joten sitä ei sellaisenaan voi esimerkiksi Python-sovellusten tavoin ajaa esimerkiksi Apache-palvelimella.

Node.js-sovellusten julkaisun tekee myös haastavaksi se, että node itsessään ei ota kantaa siihen, miten esimerkiksi sovellukset skaalautuvat. Tavallisesti web-palvelimet ovat säikeistettyjä: esimerkiksi Apachelle voi määritellä, kuinka monta säiettä palvelin tarvittaessa avaa rinnakkain. Node-sovelluksien skaalaus tapahtuu esimerkiksi ajamalla samaa sovellusta rinnakkain, esimerkiksi useissa eri porteissa siten, että edustapalvelimella (proxy) hoidetaan pyyntöjen reititys vapaalle instanssille.

Node-sovellusten etuna on toisaalta myös julkaisuvaiheessa niiden keveys ja mahdollisuus tavalliseen HTTP-palvelimeen liittyen rajoitusten kiertämiseen. Esimerkiksi Web Socket -sovellusten toteutus node:n avulla on huomattavan helppoa. Koska node:n ajoympäristö on lisäksi suhteellisen kevyt, ei node aseta palvelimelle teknisesti kovia vaatimuksia.

5.2. Julkaisu pilvialustalle

Kaikista helpoin tapa node-sovellusten julkaisuun on valmiin pilvijulkaisualustan käyttö. Suomalaiset palveluntarjoajat eivät kirjoitushetkellä pilvialustoja tarjoa, mutta kansainvälisesti vaihtoehtoja node:llekin on jo runsaasti. Erityisesti seuraavat alustat tukevat nodea:

Maininnan arvoinen projekti on myös Nodester (https://github.com/nodester/nodester), joka kehittää avoimen lähdekoodin julkaisualustaa node:lle. Nodester on saatavilla myös palveluna (http://nodester.com), mutta itse palveluun kannattaa suhtautua lähinnä teknologiademona.

5.2.1. Esimerkki: sovelluksen julkaisu Heroku-alustalle

Herokun käyttö vaatii paikallisesti asennettavan työkalukirjaston (https://toolbelt.herokuapp.com/). Kirjaston avulla node-sovelluksia voi viedä ajoon Heroku-pilvialustalle helposti komentorivin avulla.

Periaatetasolla projektiin liitetään Procfile-tiedosto, joka kuvaa, mitä sovelluksia alustalla halutaan ajaa. Esimerkiksi, jos haluat ajaa app.js:ää node:n avulla, kirjoita Procfileen sisältö:

app: node app.js

Herokun asennus perustuu git-versionhallinnan hyödyntämiseen. Jos projektisi ei ole vielä versioituna git:ssä, lisää se seuraavasti:

git init
git add .
git commit -m "init"

Tämän jälkeen voit luoda Herokuun sovelluksellesi ajoympäristön:

heroku create

Ajoympäristön luonti liittää git:iin uuden etäkohteen heroku. Voit julkaista palvelun pilveen päivittämällä tämän etäkohteen komennolla:

git push heroku master

Samassa yhdessä, kun git lähettää palvelimelle uuden version, Heroku asentaa myös automaattisesti package.json:ssa kuvatut riippuvuudet, sekä suorittaa myös muut tarvittavat alustustoimenpiteet. Tästäkin syystä on tärkeää, että node_modules-kansiota ei sijoiteta versionhallintaan!

Kun asennus on valmis, saat sovelluksen auki paikallisessa selaimessasi komennolla:

heroku open

Sovelluksen tila näkyy komennolla:

heroku ps

Vastaavasti lokitiedot näkyvät komennolla:

heroku logs

Sovelluksen skaalaus useammalle prosessille on Herokussa todella helppoa. Jos sovelluksesta halutaan ajaa esimerkiksi 5 instanssia, voit kutsua komentoa:

heroku ps:scale web=5

Node:n ajoympäristö voidaan vaihtaa config komennnolla. Esimerkiksi, jos sovellus halutaan ajaa tuotantoympäristössä, voidaan ajaa:

heroku config:add NODE_ENV=production

Lisätietoja ja tarkemmat ohjeet Herokun käytöstä: https://devcenter.heroku.com/articles/nodejs

5.3. Julkaisu omalla palvelimella (Linux)

Node-sovellusten julkaiseminen omalla palvelimella vaatii hieman virittelyä, mutta ei ole missään määrin kovin hankalaa. Käymme tässä läpi muutamia lisäkirjastoja, joiden avulla julkaisu sujuu jouhevammin.

Lyhyenä yhteenvetona suosittelen seuraavaa:

5.3.1. forever

Jotta sovelluksen kaatuminen ei lopettaisi palvelun toimintaa, on node-sovelluksien kaatumista jollain tavalla valvottava. Yksi hyvä sovellus tähän tarkoitukseen on forever (https://github.com/nodejitsu/forever/).

Aloita asentamalla forever npm:llä:

npm install -g forever

Voit nyt ajaa forever-sovelluksia valvotusti forever:llä:

forever app.js

Forever mahdollistaa myös sovellusten tausta-ajon:

forever start app.js

Näet ajossa olevat sovellukset kommennolla:

forever list

Vastaavasti sovellukset saa pysäytettyä komennolla:

forever stop app.js

5.3.2. upstart

Pelkkä foreverin käyttö ei riitä, mikäli haluat, että sovelluksesi pysyvät pystyssä myös palvelimen uudelleenkäynnistyksen jälkeen. Tätä varten tarvitset käyttöösi esimerkiksi upstart:in.

Upstart (http://upstart.ubuntu.com/) on tapahtumapohjainen vaihtoehto Linuxissa yleisesti käytetylle /sbin/init daemonille. Upstarttia käytetään init:n tavoin pitämään huolta, että palvelimella pyörivät palvelut pysyvät pystyssä hallitusti, sulkeutuvat kun palvelin suljetaan sekä käynnistyvät uudelleen palvelimen uudelleenkäynnistyksen yhteydessä. Upstartin saa käyttöön helposti ainakin Ubuntu, Fedora ja Debian -jakeluissa.

Aloita asentamalla upstart:

sudo apt-get install upstart

Luo sovelluskohtainen upstart-konfiguraatiotiedosto, esim. Ubuntu 10.10:ssä /etc/init/app.conf (vrt. http://calip.so/installing-as-upstart-service.html):

#!upstart
description "Node-sovellus"

start on (filesystem and net-device-up)
stop on shutdown

chdir /var/www/app
exec sudo -u username sh -c "NODE_ENV=production /usr/sbin/node app >> /var/www/app/logs/upstart.log 2>&1"
respawn

respawn limit 3 60

Esimerkissä säädöt ovat seuraavanlaiset:

Tämän jälkeen voit käynnistää sovelluksesi upstartin avulla palveluna kutsumalla:

sudo start app

Palvelun tilan saa esille vastaavasti:

sudo status app

Uudelleenkäynnistys:

sudo restart app

Ja pysäytys:

sudo stop app

5.3.3. monit

Vinkkejä monit:n käyttöön upstart:n kanssa:

Muutoshistoria