A JavaScriptet szerver oldali scriptelésre is használhatjuk, ilyenkor a PHP-hez hasonlóan működik: a HTML oldalba ágyazzuk a kódot, amit a szerver az oldal lekérésekor lefuttat, és a kód helyére beszúrja annak kimenetét a HTML oldalba. A szerver oldali script kapcsolódhat egy adatbázishoz, vagy hozzáférhet a szerver fájlrendszeréhez is. Ezzel helyettesíthetjük a CGi programozást, sőt, egy annál rugalmasabb eszközt kapunk.
A szerver oldali scriptek futtatása a klienssel szemben semmilyen követelményt nem állít, viszont a szerver webkiszolgálóját fel kell készíteni a futtatására, azaz szükség van egy ún. JavaScript runtime engine-re. Ilyen található a Netscape Enterprise Serverben, Application Manager néven.
Ezek a scriptek egy bytekódban tárolódnak, hogy futtatásuk gyorsabb legyen. A HTML és JavaScript forrásokból a jsac nevű fordító készíti el ezt a bytekódot, amit installálni is kell, hogy futtatni tudjuk. Az installálás csak abból áll, hogy a futtató rendszernek megadjuk az alkalmazás helyét, és néhány, a futtatást befolyásoló paramétert. Ezután az alkalmazás bármikor leállítható és újraindítható, sőt módosíthatunk is rajta újratelepítés nélkül.
A szerver oldali scriptet a <server></server> tagok közé kell írnunk. Az itt lévő kódot a szerver nem fogja elküldeni, hanem lefuttatja, és annak kimenete kerül a kód helyére.
Ezeket a szolgáltatásokat nem tárgyaljuk részletesen, csak a lehetőségeket soroljuk fel. Bővebb információ a http://docs.iplanet.com/docs/manuals/ssjs/1_4/ssjs.pdf címen található leírásban érhető el.
A SendMail "osztály" segítségével küldhetünk levelet. Egy példa:
Lehetőség van a szerver fájlrendszerének manipulálására a File "osztály" segítségével. Bármely fájl elérhető, amit a webkiszolgáló elérhet, ezért ezt a szolgáltatást elővigyázatosan alkalmazzuk!
Lehetőségünk van natív függvények meghívására is, ha alkalmazásunkban valamely hardverközeli, vagy erőforrásigényes feladatot kell megoldanunk.
A LiveWire adatbázis szolgáltatás segítségével kapcsolódhatunk egy relációs adatbáziskezelőhöz és manipulálhatjuk az abban tárolt adatokat. A LiveWire minden elterjedtebb adatbáziskezelőt támogat.
A NoSQL egyes értelmezések szerint a „nem csak SQL”, más értelmezések szerint „nem SQL” adatbázisok gyűjtőneve. Ezek az adatbázisok többnyire nem táblázatokban tárolják az adatokat és nem nagyon használnak SQL-t az adatok lekérdezésére. A műveleteket illetően, a NoSQL adatbázisok az írás és olvasás műveletekre vannak kihegyezve, mivel hatalmas mennyiségű adatok kezelésére tervezték őket.
A NoSQL adatbázis rendszereket több típusba sorolhatjuk az alapján, hogy hogyan tárolják az adatokat.
Az egyik legelterjedtebb ilyen típus, az ún. dokumentum alapú adatbázisok, dokumentumtárolók. A központi szerepet a dokumentum tölti be. A dokumentum valamilyen formában tárolt információ, amelyeknek formátuma gyakran XML vagy JSON. A dokumentumok abban térnek el a relációs adatbázisok tábláitól, hogy a dokumentumok teljesen eltérő struktúrával rendelkezhetnek.
JSON adatformátum
A CouchDB egy nyílt forráskódú NoSQL adatbázis rendszer. A dokumentum alapú tárolási szemléletet követi. A dokumentumokat JSON formátumban tárolja és a JavaScript nyelvet használja, mint lekérdező nyelvet.
Az adatbázis az adatokat, mint dokumentumokat tárolja, amelyek mező/érték párokkal vannak reprezentálva JSON formában. Az értékek típusa lehet string, szám, dátum, de akár rendezett lista és asszociatív tömb is. Minden dokumentumnak van egy egyedi azonosítója és egy verzió száma, amely minden egyes módosításkor változik. Lehetőség van az előző verziók megtekintésére.
A tárolt adatokat ún. nézeteken keresztül kérdezhetjük le. Minden ilyen nézet egy JavaScript függvényként épül fel, amelyet mi magunk írhatunk meg.
Példa:
Eredmény:
Az összes elemnek van egy egyedi URI címe, amely http elérést biztosít az adatokhoz. A REST olyan HTTP metódusokat használ, mint a POST, GET, PUT, DELETE az négy alap művelethez (Kreálás, Olvasás, Frissítés, Törlés).
A Node.js (vagy más néven Node) egy rendszer, melyben JavaScriptben írhatunk szerver oldali alkalmazásokat. Maga a rendszer C/C++-ban íródott, és egy esemény alapú I/O rendszert takar a Google V8 JavaScript motorja felett. A Node célja, hogy egy egyszerű felületet adjon skálázható hálózati alkalmazások írására. Azt tudjuk, hogy a JavaScript a világon a jelenleg legnépszerűbb programozási nyelv, többek között ezért esett erre a nyelvre a választás. A JavaScript nyelvnek vannak más sajátosságai, amelyek szintén előtérbe kerülnek a rendszer használata során. Ahogy a böngészőben, úgy Node alatt is egyetlen esemény hurokban (event loop) fut a program, és ez adja az egyik legfontosabb előnyt.
A Node.js-t úgy írták meg, hogy (szinte) minden esemény aszinkron legyen, ezért a program sosem blokkolódik, azaz nem kell várni, hogy egy művelet befejeződjön, vele párhuzamosan futtathatunk további műveleteket. Ez pontosan úgy működik, mint a böngészőben levő XHR kérések, vagy más események, mint például a click, mouseover. Ez az alkalmazás folyamatosabb futását, több alkalmazás párhuzamosítását, valamint az egész rendszer optimálisabb működését teszi lehetővé.
A közhiedelemmel ellentétben a Node.JS és a böngésző jelentősen különböznek egymástól, annak ellenére hogy mindkettő a JavaScript nyelven alapszik. A node.js veszi az alap nyelvet akárcsak bármelyik böngésző motor, és különböző API-kkal bővíti azt, ezzel lehetőséget nyújtva szerveroldali műveletekre, hálózati feladatok ellátására.
A böngészőben a window a globális objektum, bármi amit window property-ként definiálunk, elérhető lesz a weboldal teljes futása alatt bárhonnan. Fontos megemlíteni hogy minden globálisan var kulcsszó nélkül hivatkozott és elérhető változó a window objektum egyik attribútuma. Például setTimeout, document, stb. A node is rendelkezik két hasonló objektummal amik biztosítják a könnyű szeparálhatóságot:
A böngészőben definiált globális változók nagy része, nem a nyelv specifikációja miatt áll rendelkezésre, sok esetben a böngésző vendorok adtak hozzá a webes alkalmazások fejlesztésének megkönnyítéséért. Például a setTimeout nem része az ECMAScript szabványnak.
A node sok olyan API-t tartalmaz amik már proposalként jelen vannak az ECMAScript dokumentációjában, viszont a szerveroldali müködéshez elengedhetetlenek voltak. Ilyen például a setImmediate API-t megvalósító process.nextTick.
Böngészőben jelenleg nem rendelkezünk module implementációval (ECMAScript 7-ben már érkezik), tehát ha bármilyen thirdparty scriptet adunk hozzá az oldalhoz akkor globális változóként válik elérhetővé. Fontos megemlíteni, hogy ennek ellenére készültek már egyedi modukezelől implementációk mint például a RequireJS.
A node ezzel ellentétben natív modul rendszerrel rendelkezik, amit a require, module és export globális változó hármas biztosít számunkra.
Ha például szeretnénk egy globális module-t importálni, akkor ezt egy egyszerű require(example’) paranccsal tehetjük meg, ekkor a globális node könyvtárban lévő modulok között keresi majd az interpreter a modulunkat.
Ha szeretnénk egy saját API-t exportálni az adott modul-ból, ezt a module és az exports globális változók segítségével tehetjük meg. Ekkor a require hívás ezt az API-t kapja vissza.
Alapból minden module egy üres object literált ({}) ad vissza, és ha szeretnénk ehhez új értékeket adni akkor az exports változót kell bővíteni.
Például (example_module):
Az egyik legfontosabb API az EventEmmiter. A böngészőhöz hasonlóan a Node.js is az eseményalapú működésen alapszik. A böngészőben az események triggereléséért a DOM felel, viszont Node-ban mi is bármikor emitelhetünk saját eseményeket. Az EventEmmiter a a process-en belül érhető el.
Eseménykezelés és kilövés példa:
A Buffer egy globális objemtum ami egy fixen allokált memória területet reprezentál (ezért inicializálásnál szükséges a méret megadása) és úgy viselkedik mint egy octet-ekből álló tömb. Segítségükkel bináris adatokat tárolhatunk.
Az egyik legfontosabb képességük pedig az, hogy az adatot különböző enkódolások között koncertálhatjuk. Például egy készíthetünk egy base64 kép reprezentációt tartalmazó buffert, amit utána bináris formában fájlba írunk.
Példa:
Az egyik legtöbbet használt Node modul az fs, aminek segítségével fájlműveleteket hajthatunk végre. Sok esetben szükség van szinkron és aszinkron műveletekre egyaránt, ezért mindkét módszerhez szükséges metódusok rendelkezésünkre állnak.
Példa:
A streamek eredete egészen a UNIX rendszerek létezésének első napjaiig vezethető vissza, és azóta mindenhol jelen vannak. Ha sima unix parancsokra gondolunk akkor ott a | (pipe) jel segítségével használhattuk őket. A Node.js egy belső stream modul implementációval rendelkezik ami a unix rendszerhez hasonlóan szintén a pipe() metódus használatára épül. Segítségükkel komplex adatfolyamokat hozhatunk létre, ahol minden kezelő osztály a folyamat egy újabb állapotát kapja bemenetül, és az elvégzett műveletek után, a módosított állapotot adja tovább a következő kezelőnek.
Példa:
Köszönhetően annak hogy egy szerveroldali nyelvről beszélünk a command-line használata elengedhetetlen, ezért az itt átadok argumentumok olvasásának ismerete is fontos.
Az express js egy olyan nodejs framework ami igyekszik egyszerűvé tenni a webalkalmazások fejlesztését node alapokon. A connect modul-ra épülve egy olyan API-t definiál ami elfedi számunkra a nyelv nehézségeit. A telepítése megegyezik bármely más node moduléval:
Szinte akármilyen operációs rendszerre telepíthetjük a Node-ot, Linuxtól kezdve a Mac OS X-en át a Solarisra. Fordíthatjuk ezen kívül Windows alatt Cygwin-en, FreeBSD-re és OpenBSD-re. A rendszer telepítése elég egyszerű, letöltjük az aktuális stabil változatot, konfiguráljuk, és fordítjuk (make). A fordításhoz szükségünk van egy C++ (gcc) fordítóra, és a Python 2.4 vagy újabb változatára.
Ez lefordítja a Node.js-t valamint a benne található motort is, azaz azt nem kell külön letölteni és telepíteni.
Amennyiben a telepítés sikeresen lezajlott, mentsük el a következő JavaScript alkalmazást hello.js néven:
Majd futtassuk a következőképpen:
Ekkor előbb a konzolon megjelenik, hogy Hello, majd 2 másodperccel később, hogy World!
Az egyik lényeges különbség például a PHP-hoz képest – azon kívül, hogy JavaScript-ben írjuk az alkalmazásunkat –, hogy nincsen szükségünk HTTP szerverre (mint amilyen az Apache httpd), mivel mi magunk írjuk a HTTP szerverünket. Írjuk is meg az első hasonló alkalmazásunkat httpszerver.js néven:
A következő módon tudjuk futtatni:
Ekkor a programunk a 8124-es porton várakozik a HTTP kérésekre, és csak annyit ír ki a böngészőben a http://127.0.0.1:8124/ URL-re látogatva, hogy Hello World.
A Node.js alapértelmezetten is rengeteg modullal érkezik, hasonlóan az előbb említett http modulhoz. A modulok a CommonJS specifikáció szerint íródtak, és ennek megfelelően a require('modulneve'); paranccsal tudjuk behúzni őket az alkalmazásunkba. Ezek egy objektumot tesznek elérhetővé, és egy változóhoz rendelve később kényelmesen tudjuk használni is őket. Az alap telepítésben elérhető modulokról a Node hivatalos API dokumentációjában olvashatunk.
A Node hivatalos csomagkezelője az npm, amellyel kényelmesen listázhatjuk, telepíthetjük, frissíthetjük és eltávolíthatjuk az elérhető modulokat, valamint mi magunk is publikálhatjuk az általunk fejlesztett modulokat az npm rendszerébe. Rendszerkövetelményei azonosak a Node-éval, telepítése egyszerű:
Jelenleg több mint 600 modul érhető el az npm rendszerében. Természetesen a modulok minősége változó, de azért könnyű találni a konkrét problémát megoldó modulok közül a nekünk megfelelőt.
Az elérhető modulok listáját az npm ls paranccsal érhetjük el, és ezek nevében a split() parancsnak megfelelő paramétert átadva szűrhetünk is, tehát reguláris kifejezéseket is használhatunk. Például:
Ez szűri azon modulokat, melyek nevében az „xml” szerepel.
Amennyiben további részletekre vagyunk kíváncsiak egy modullal kapcsolatban, használhatjuk a view parancsot, mely egy JSON objektumban írja le a modult, például nevét, leírását, szerzőjét, a repository-t, ahol elérhető a forráskód, a modul weboldalát stb.
A modulokat az install paranccsal telepíthetjük.
A frissítésre az update, eltávolításra az uninstall parancs szolgál. További segítséghez használjuk a help utasítást.
Egy Node alkalmazás egyetlen szálon fut, ami a többmagos processzorok korában talán furcsának tűnhet. Ugyanakkor nem is olyan bonyolult egy már létező alkalmazást többszálúra átalakítani. Az egész lényege, hogy az alkalmazásunkat úgy írjuk meg, hogy a parancssori paraméterekben fogadni tudja, hogy melyik porton is fogadja a kéréseket, valamint írunk egy pár soros proxy alkalmazást, ami ezekhez a most már párhuzamosan futtatható alkalmazásokhoz továbbítja a kéréseket.
Álljon itt egy minimális alkalmazás, ami csak annyit ad vissza válaszként a HTTP kérésekre, hogy Hello World @ [port]. Legyen ez az app.js:
Írjuk meg hozzá a proxy.js alkalmazásunkat, ami ezeket a futó alkalmazásokat fogja hívogatni. Ehhez a http-proxy modult kell telepíteni. Sajnos ennek a modulnak rengeteg követelménye van, de npm-mel egyszerű telepíteni:
Ezután az alkalmazásunkat a következőképpen futtathatjuk:
Ekkor elindul az app.js a 8081-es és 8082-es porton, amikhez a proxy.js fog majd csatlakozni. A proxy.js-nek is megadhatjuk hogy mely porton várakozzon, illetve hogy milyen szórási metódust használjon az elérhető 3 közül.
Ha úgy érezzük, hogy a HTTP kérések proxyn keresztüli továbbítása hátrányosan érinti az alkalmazásunk sebességét – ebben eléggé kételkedek, ugyanis majdnem egyenesen arányos a növekedés új szerverek hozzáadásakor (természetesen csak bizonyos határokig) –, akkor alkalmazhatunk például Unix socketeket. Ekkor azonban az alkalmazásunkat át kell írni, és nehezebb a hibakeresés is, ugyanis nem lehet önállóan futtatni.