table of contents - asis.anambaskab.go.id · memakai server seperti apache - php, nginx - php, java...

102

Upload: phamthuy

Post on 06-Mar-2019

258 views

Category:

Documents


0 download

TRANSCRIPT

0

1

1.1

1.2

2

2.1

2.2

3

3.1

4

5

5.1

5.2

6

6.1

6.2

7

7.1

7.1.1

7.1.2

7.2

8

8.1

8.1.1

8.1.2

8.1.2.1

8.2

8.2.1

8.3

8.3.1

TableofContentsIntroduction

Node.js

JavaScriptDiServer

Node.jsInAction

AsinkronI/O&Event

PHP&ServerHTTPApache

Javascript&Node.js

ServerHTTPDasar

MenjalankanServer

ServerFileStatis

PemrosesanDataFormHTML

URLEncode

MultipartData

Modulenpm

Konsep

Paketnpm

ExpressJS

ServerFile

Middleware

AksesServer

ServerREST

Database

SQLite

NodeSqlite3

Enkripsi

sqlcipher

MySQL

NodeMySQL

MongoDB

NodeMongoDB

AplikasiWebNode.js

2

8.3.2

9

9.1

9.2

10

10.1

10.2

10.3

11

11.1

11.2

11.3

12

13

14

Mongoose

Testing

REST

Automasi

ToDataURI

Penggunaan

todatauri.js

KoneksiMySQL

PersonRESTAPI

CaraKerja

Server

Pengetesan

ImageUploader

MemakaiES6

TentangPengarang

AplikasiWebNode.js

3

AplikasiWebNode.jsNote:ThisbookiswritteninBahasaIndonesiaandthemainreasonforthatisbecausemostofNode.jsbeginnersinmycountryIndonesiaishavingdifficultiestofindNode.jsresourceswritteninmynativelanguage.

BukuinicocokbagisiapasajayanginginmulaibelajarpemrogramandiplatformNode.jskhususnyauntukmembangunaplikasiweb.SyaratyangdibutuhkanadalahpembacasetidaknyapernahatausudahbisamemakaibahasapemrogramanJavaScript.

Ebookinibisaandaaksesdiduatempatyaitu:

GithubIDJS(versionline).Gitbook(versionline,PDF,Epub&Mobi).

FeedbackUntukpertanyaan,kesalahanketikataupermintaanbisamenghubungipenulismelaluiemailequan.p[at]gmail.meataumelaluiGithubissue.

LisensiAplikasiWebNode.jsolehEquanPr.dikerjakandibawahlisensiCreativeCommonsAttribution-NonCommercial4.0InternationalLicense.

AplikasiWebNode.js

4Introduction

Node.jsJavascriptmerupakanbahasapemrogramanyanglengkaphanyasajaselamainidipakaisebagaibahasauntukpengembanganaplikasiwebyangberjalanpadasisiclientataubrowsersaja.TetapisejakditemukannyaNode.jsolehRyanDhalpadatahun2009,JavascriptbisadigunakansebagaibahasapemrogramandisisiserversekelasdenganPHP,ASP,C#,RubydlldengankatalainNode.jsmenyediakanplatformuntukmembuataplikasiJavascriptdapatdijalankandisisiserver.

UntukmengeksekusiJavascriptsebagaibahasaserverdiperlukanengineyangcepatdanmempunyaiperformansiyangbagus.EngineJavascriptdariGooglebernamaV8yangdipakaiolehNode.jsyangmerupakanengineyangsamayangdipakaidibrowserGoogleChrome.

AplikasiWebNode.js

5Node.js

JavaScriptDiServerTakterelakkanbahwaJavascriptmerupakanbahasapemrogramanyangpalingpopuler.JikaandasebagaideveloperpernahmengembangkanaplikasiwebmakapenggunaanJavascriptpastitidakterhindarkan.

SekarangdenganberjalannyaJavascriptdiserverlaluapakeuntunganyangandaperolehdenganmempelajariNode.js,kuranglebihsepertiini:

Pengembanghanyamemakaisatubahasauntukmengembangkanaplikasilengkapclient&serversehinggamengurangiLearningCurveuntukmempelajaribahasaserveryanglain.

Sharingkodeantaraclientdanserveratauistilahnyacodereuse.

JavascriptsecaranativemendukungJSONyangmerupakanstandartransferdatayangbanyakdipakaisaatinisehinggauntukmengkonsumsidata-datadaripihakketigapemrosesandiNode.jsakansangatmudahsekali.

DatabaseNoSQLsepertiMongoDBdanCouchDBmendukunglangsungJavascriptsehinggainterfacingdengandatabaseiniakanjauhlebihmudah.

Node.jsmemakaiV8yangselalumengikutiperkembanganstandarECMAScript,jaditidakperluadakekhawatiranbahwabrowsertidakakanmendukungfitur-fiturdiNode.js.

AplikasiWebNode.js

6JavaScriptDiServer

Node.jsInActionSupayaandalebihtertarikdalambelajarNode.jsberikutbeberapawebsiteterkenalyangsudahmemakaiNode.js

www.myspace.com

www.yummly.com

www.shutterstock.com

AplikasiWebNode.js

7Node.jsInAction

www.klout.com

www.geekli.st

AplikasiWebNode.js

8Node.jsInAction

www.learnboost.com

ApakahmasihraguuntukmemakaiNode.js?...KalaumasihpenasaranapayangmembuatNode.jsberbedadaribackendpadaumumnya,silahkandilanjutkanmembaca:smile:

AplikasiWebNode.js

9Node.jsInAction

AsinkronI/O&EventTidaksepertikebanyakanbahasabackendlainnyaoperasifungsidijavascriptlebihbersifatasinkrondanbanyakmenggunakaneventdemikianjugadenganNode.js.SebelumpenjelasanlebihlanjutmarikitalihatterlebihdahulutentangmetodesinkronsepertiyangdipakaipadaPHPdenganwebserverApache.

AplikasiWebNode.js

10AsinkronI/O&Event

PHP&ServerHTTPApacheMarikitalihatcontohberikutyaituoperasifungsiakseskedatabaseMySQLolehPHPyangdilakukansecarasinkron

$hasil=mysql_query("SELECT*FROMTabelAnggota");

print_r($hasil);

pengambilandataolehmysql_query()diatasakandijalankandanoperasiberikutnyaprint_r()akandiblokatautidakakanberjalansebelumakseskedatabaseselesai.YangperlumenjadiperhatiandisiniyaituprosesInputOutputatauI/Oakseskedatabaseolehmysql_query()dapatmemakanwaktuyangrelatifmungkinbeberapadetikataumenittergantungdariwaktulatensidariI/O.Waktulatensiinitergantungdaribanyakhalseperti

QuerydatabaselambatakibatbanyakpenggunayangmengaksesKualitasjaringanuntukakseskedatabasejelekProsesbacatuliskediskkomputerdatabaseyangmembutuhkanwaktu...

SebelumprosesI/Oselesaimakaselamabeberapadetikataumenittersebutstatedariprosesmysql_query()bisadibilangidleatautidakmelakukanapa-apa.

LalujikaprosesI/Odiblokbagaimanajikaadarequestlagidariuser?apayangakandilakukanolehserveruntukmenanganirequestini?..penyelesaiannyayaitudenganmemakaipendekatanprosesmultithread.Melaluipendekataninitiapkoneksiyangterjadiakanditanganiolehthread.Threaddisinibisadikatakansebagaitaskyangdijalankanolehprosesorkomputer.

SepertinyapermasalahanI/Oyangterblokterselesaikandenganpendekatanmetodeinitetapidenganbertambahnyakoneksiyangterjadimakathreadakansemakinbanyaksehinggaprosesorakansemakinterbebani,belumlagiuntukswitchingantarthreadmenyebabkankonsumsimemory(RAM)komputeryangcukupbesar.

BerikutcontohbenchmarkantarawebserverApachedanNginx(serverHTTPsepertihalnyaApachehanyasajaNginxmemakaisistemasinkronI/OdaneventyangmiripNode.js).Gambarinidiambildarigoo.gl/pvLL4

AplikasiWebNode.js

11PHP&ServerHTTPApache

BisadilihatbahwaNginxbisamenanganirequestyangjauhlebihbanyakdaripadawebserverApachepadajumlahkoneksibersamayangsemakinnaik.

AplikasiWebNode.js

12PHP&ServerHTTPApache

Javascript&Node.jsKembalikeJavascript!.Untukmengetahuiapayangdimaksuddenganpemrogramanasinkronbisalebihmudahdenganmemakaipendekatancontohkode.PerhatikankodeJavascriptpadaNode.jsberikut

varfs=require('fs');

fs.readFile('./resource.json',function(err,data){

if(err)throwerr;

console.log(JSON.parse(data));

});

console.log('Selanjutnya...');

fungsireadFile()akanmembacamembacaisidarifileresource.jsonsecaraasinkronyangartinyaproseseksekusiprogramtidakakanmenunggupembacaanfileresource.jsonsampaiselesaitetapiprogramakantetapmenjalankankodeJavascriptselanjutnyayaituconsole.log('Selanjutnya...').Sekarnglihatapayangterjadijikakodejavascriptdiatasdijalankan

Jikaprosespembacaanfileresource.jsonselesaimakafungsicallbackpadareadFile()akandijalankandanhasilnyaakanditampilkanpadaconsole.Yah,fungsicallbackmerupakankonsepyangpentingdalamprosesI/OyangasinkronkarenamelaluifungsicallbackinidatadatayangdikembalikanolehprosesI/Oakandiproses.

LalubagaimanaplatformNode.jsmengetahuikalausuatuprosesitutelahselesaiatautidak?...jawabannyaadalahEventLoop.Event-eventyangterjadikarenaprosesasinkronsepertipadafungsifs.readFile()akanditanganiolehyangnamanyaEventLoopini.

Campuranteknologiantaraeventdrivendanprosesasinkroninimemungkinkanpembuatanaplikasidenganpenggunaandatasecaramasifdanreal-time.SifatkomunikasiNode.jsI/Oyangringandanbisamenanganiusersecarabersamaandalamjumlahrelatifbesartetapitetapmenjagastatedarikoneksisupayatetapterbukadandenganpenggunaanmemoriyangcukupkecilmemungkinkanpengembanganaplikasidenganpenggunaandatayangbesardankolaboratif...Yeah,Node.jsFTW!:metal:

AplikasiWebNode.js

13Javascript&Node.js

AplikasiWebNode.js

14Javascript&Node.js

ServerHTTPDasarPenggunaanNode.jsyangrevolusioneryaitusebagaiserver.Yup...mungkinkitaterbiasamemakaiserversepertiApache-PHP,Nginx-PHP,Java-Tomcat-ApacheatauIIS-ASP.NETsebagaipemrosesdatadisisiserver,tetapisekarangsemuaitubisatergantikandenganmemakaiJavaScript-Node.js!.LihatcontohdasardariserverNode.jsberikut(kodesumberpadadirektoricodepadarepositoriini)

server-http.js

varhttp=require('http'),

PORT=3400;

varserver=http.createServer(function(req,res){

varbody="<pre>HaruskahbelajarNode.js?</pre><p><h3>...YoMesto!</h3></p>"

res.writeHead(200,{

'Content-Length':body.length,

'Content-Type':'text/html',

'Pesan-Header':'PengenalanNode.js'

});

res.write(body);

res.end();

});

server.listen(PORT);

console.log("Port"+PORT+":Node.jsServer...");

PakethttpmerupakanpaketbawaandariplatformNode.jsyangmendukungpenggunaanfitur-fiturprotokolHTTP.ObjectservermerupakanobjectyangdikembalikandarifungsicreateServer().

varserver=http.createServer([requestListener])

TiaprequestyangterjadiakanditanganiolehfungsicallbackrequestListener.Carakerjacallbackinihampirsamadenganketikakitamenekantombolbuttonhtmlyangmempunyaiatributeventonclick,jikaditekanmakafungsiyangteregistrasioleheventonclickyaituclickHandler(event)akandijalankan.

onclick-button.html

AplikasiWebNode.js

15ServerHTTPDasar

<script>

functionclickHandler(event){

console.log(event.target.innerHTML+"Terus!");

}

</script>

<buttononclick="clickHandler(event)">TEKAN</button>

SamahalnyadengancallbackrequestListenerpadaobjectserverinijikaadarequestmakarequestListenerakandijalankan

function(req,res){

varbody="<pre>HaruskahbelajarNode.js?</pre><p><h3>...YoMesto!</h3></p>"

res.writeHead(200,{

'Content-Length':body.length,

'Content-Type':'text/html',

'Pesan-Header':'PengenalanNode.js'

});

res.write(body);

res.end();

}

PakethttpNode.jsmemberikankeleluasanbagideveloperuntukmembangunservertingkatrendah.Bahkanmudahsajakalauharusmen-settingnilaifieldheaderdariHTTP.

SepertipadacontohdiatasagarrespondarirequestdiperlakukansebagaiHTMLolehbrowsermakanilaifieldContent-Typeharusberupatext/html.SettinginibisadilakukanmelaluimetodewriteHead(),res.setHeader(field,value)danbeberapametodelainnya.

Untukmembacaheaderbisadipakaifungsisepertires.getHeader(field,value)danuntukmenghapusfieldheadertertentudenganmemakaifungsires.removeHeader(field).Perludiingatbahwasettingheaderdilakukansebelumfungsires.write()ataures.end()dijalankankarenajikares.write()dijalankantetapikemudianadaperubahanfieldheadermakaperubahaniniakandiabaikan.

SatuhallagiyaitutentangkodestatusdariresponHTTP.Kodestatusinibisadisettingselain200(requesthttpsukses),misalnyabiladiperlukanhalamanerrordengankodestatus404.

AplikasiWebNode.js

16ServerHTTPDasar

MenjalankanServerUntukmenjalankanserverNode.jsketikperintahberikutditerminal

$nodeserver-http.js

Port3400:Node.jsServer...

Bukabrowser(chrome)danbukaurlhttp://localhost:3400kemudianketikCTRL+SHIFT+IuntukmembukaChromeDevTool,dengantoolinibisadilihatresponheaderdariHTTPdimanabeberapafieldnyatelahdisetsebelumnya(lingkaranmerahpadascreenshotdibawahini).

AplikasiWebNode.js

17MenjalankanServer

ServerFileStatisAplikasiwebmemerlukanfile-filestatissepertiCSS,fontdangambarataufile-filelibraryJavaScriptagaraplikasiwebbekerjasebagaimanamestinya.File-fileinisengajadipisahkanagarterstrukturdansecarabestpracticesfile-fileinimemangharusdipisahkan.LalubagaimanacaranyaNode.jsbisamenyediakanfile-fileini?...okmarikitabuatserverNode.jsyangfungsinyauntukmenyediakanfilestatis.

AgarserverNode.jsbisamengirimkanfilestatiskeklienmakaserverperlumengetahuipathatautempatdimanafiletersebutberada.

Node.jsbisamengirimkanfiletersebutsecarastreamingmelaluifungsifs.createReadStream().SebelumdijelaskanlebihlanjutmungkinbisadilihatataudicobasajaserverfileNode.jsdibawahini

server-file.js

AplikasiWebNode.js

18ServerFileStatis

varhttp=require('http'),

parse=require('url').parse,

join=require('path').join,

fs=require('fs'),

root=join(__dirname,'www'),

PORT=3300,

server=http.createServer(function(req,res){

varurl=parse(req.url),

path=join(root,url.pathname),

stream=fs.createReadStream(path);

stream.on('data',function(bagian){

res.write(bagian);

});

stream.on('end',function(){

res.end();

});

stream.on('error',function(){

res.setHeader('Content-Type','text/html');

varurl_demo="http://localhost:"+PORT+"/index.html";

res.write("cobabuka<ahref="+url_demo+">"+url_demo+"</a>");

res.end();

})

});

server.listen(PORT);

console.log('Port'+PORT+':ServerFile');

Berikutsedikitpenjelasandarikodediatas

__dirnamemerupakanvariabelglobalyangdisediakanolehNode.jsyangberisipathdirektoridarifileyangsedangaktifmengeksekusi__dirname.rootmerupakandirektorirootataureferensitempatdimanafile-fileyangakandikirimkanolehserverNode.js.Padakodeserverdiatasdirektorirootdisettingpadadirektoriwww.pathadalahpathfileyangbisadidapatkandenganmenggabungkanpathdirektorirootdanpathname.pathnameyangdimaksuddisinimisalnyajikaURLyangdimintayaituhttp://localhost:3300/index.htmlmakapathnameadalah/index.html.Nilaivariabelpathdihasilkandenganmemakaifungsijoin().

varpath=join(root,url.pathname)

AplikasiWebNode.js

19ServerFileStatis

streamyangdikembalikanolehfungsifs.createReadStream()merupakanclassstream.Readable.Objekstreaminimengeluarkandatasecarastreaminguntukdiolahlebihlanjut.Perlumenjadicatatanbahwastream.Readabletidakakanmengeluarkandatajikalautidakdikehendaki.Nah...carauntukmendeteksidatastreaminginisudahsiapdikonsumsiataubelumadalahmelaluievent.

Eventyangdidukungolehclassstream.Readableadalahsebagaiberikut

Event:readableEvent:dataEvent:endEvent:errorEvent:close

Mungkinandabertanyakenapaserverfilestatisdiatasmemakaistream,bukankahmenyediakanfilesecaralangsungsajasudahbisa?jawabannyamemangbisa,tetapimungkintidakakanefisienkalaufileyangakandiberikankeclientmempunyaiukuranyangbesar.Cobalihatkodeberikut

varhttp=require('http');

varfs=require('fs');

varserver=http.createServer(function(req,res){

fs.readFile(__dirname+'/data.txt',function(err,data){

res.end(data);

});

});

server.listen(8000);

Jikafiledata.txtterlalubesarmakabufferyangdigunakanolehsistemjugabesardankonsumsimemorijugaakanbertambahbesarseiringsemakinbanyakpenggunayangmengaksesfileini.

JikaandainginlebihbanyakmendalamitentangNode.jsStreamsilahkanlihatresourceberikut(dalamBahasaInggris):

Node.jsAPIStreamStreamHandbook

AplikasiWebNode.js

20ServerFileStatis

PemrosesanDataFormHTMLAplikasiwebmemperolehdatadaripenggunaumumnyamelaluipengisianformHTML.ContohnyasepertiketikaregistrasidimediasosialatauaktifitasupdatestatusdiFacebookmisalnyapastiakanmengisitextfielddankemudianmenekantombolsubmitataupunenteragardatabisaterkirimdandiprosesolehserver.

Datayangdikirimolehformbiasanyasalahsatudariduatipemimeberikut

application/x-www-form-urlencodedmultipart/form-data

Node.jssendirihanyamenyediakanparsingdatamelaluibodydarirequestsedangkanuntukvalidasiataupemrosesandataakandiserahkankepadakomunitas.

AplikasiWebNode.js

21PemrosesanDataFormHTML

URLEncodeHanyaakandibahasuntuk2metodeHTTPyaituGETdanPOSTsaja.MetodeGETuntukmenampilkanformhtmldanPOSTuntukmenanganidataformyangdikirim

Oklangsungkitalihatkodeserversederhanauntukparsingdataformmelaluiobjekrequestdengandataformbertipeapplication/x-www-form-urlencodedyangmerupakandefaultdaritagform.

varhttp=require('http');

vardata=[];

varqs=require('querystring');

varserver=http.createServer(function(req,res){

if('/'==req.url){

switch(req.method){

case'GET':

tampilkanForm(res);

break;

case'POST':

prosesData(req,res);

break;

default:

badRequest(res);

}

}else{

notFound(res);

}

});

functiontampilkanForm(res){

varhtml='<html><head><title>DataHobiku</title></head><body>'

+'<h1>Hobiku</h1>'

+'<formmethod="post"action="/">'

+'<p><inputtype="text"name="hobi"></p>'

+'<p><inputtype="submit"value="Simpan"></p>'

+'</form></body></html>';

res.setHeader('Content-Type','text/html');

res.setHeader('Content-Length',Buffer.byteLength(html));

res.end(html);

}

functionprosesData(req,res){

varbody='';

req.setEncoding('utf-8');

req.on('data',function(chunk){

body+=chunk;

AplikasiWebNode.js

22URLEncode

});

req.on('end',function(){

vardata=qs.parse(body);

res.setHeader('Content-Type','text/plain');

res.end('Hobiku:'+data.hobi);

});

}

functionbadRequest(res){

res.statusCode=400;

res.setHeader('Content-Type','text/plain');

res.end('400-BadRequest');

}

functionnotFound(res){

res.statusCode=404;

res.setHeader('Content-Type','text/plain');

res.end('404-NotFound');

}

server.listen(3003);

console.log('serverhttpberjalanpadaport3003');

UntukmengetestGETdanPOSTbisadilakukanmelaluicurl,browserataumelaluiguiPostman.

GET

AplikasiWebNode.js

23URLEncode

POST

AplikasiWebNode.js

24URLEncode

modulequerystringdariNode.jsberfungsiuntukmengubahurlencodedstringmenjadiobjekJavaScript.Contohnya

querystring.parse('nama=lanadelrey&job=singer&album=borntodie&ultraviolence');

//returns

{nama:'lanadelrey',job:'singer',album:['borntodie','ultraviolence']}

AplikasiWebNode.js

25URLEncode

MultipartDataParsingdataformdanfileyangdiuploadkeserverNode.jsadalahpekerjaanyangcukupsusahkalodikerjakansecaramanualataudariscratchkarenadisampingharusparsingdatabinaryyangberupafilejugaharusparsingdataform.

Protokoluntukmultipart/form-datadidefinisikansecaralengkapdiRFC2388.

AplikasiWebNode.js

26MultipartData

ModuleNpmnicepeoplematter

npmmerupakanpackagemanageruntukNode.jsdanuntuknamanpmbukanlahsuatusingkatan.Hanyadalamwaktu2tahunsejakdireleasenyaNode.jskepublikjumlahmodulmelesatjauhbahkanhampirmenyamaimoduljavaataupunrubygems.

Grafikdiatasdidapatdarihttp://modulecounts.com.

BanyaknyapushmodulekerepositorinpmdapatdiartikanadanyakepercayaanpublikterhadapplatforminidanuntukkedepannyaNode.jsakanmenjadiplatformyangprospektifuntukberinvestasi.

AplikasiWebNode.js

27Modulenpm

KonsepnpmmemakaisistemmodulCommonJSyangcukupmudahdalampenggunaanya.Sistemmoduliniakanmeng-exportobjekJavaScriptkevariabelexportsyangbersifatglobaldimodultersebut.

Sebagaicontoh

band.js

'usestrict';

functionBand(){}

Band.prototype.info=function(){

return'NamaBand:'+this.name;

}

Band.prototype.add=function(name){

this.name=name;

}

module.exports=newBand();

Untukpemakaiannyasepertidibawahini

app.js

varband=require('./band.js');

band.add('Dewa19');

console.log(band.info);

require()diatasadalahfungsisinkronyangmeloadpaketataumodullaindarisistemfile.

AplikasiWebNode.js

28Konsep

PaketnpmSecaradefaultdatapaketnpmdisimpandiregistrynpmjs.org.Sehinggauntukmenginstallpaketnpmtertentuandabisamencaripaketinimelaluicommandnpmataulangsungmelaluiwebsite.

SejakversiNode.js0.6.3commandnpmsudahter-bundledenganinstallerNode.js.Untukmenginstallmodulnpmyangandabutuhkanketikmisalnya

npminstallexpress

perintahdiatasakanmendownloadpaketexpressdarihttp://npmjs.orgdansecaraotomatisakanmembuatdirectorynode_modules.

UntukmemakaimodulexpressinicukupdenganmembuatfileJavaScriptbarudiluardirektorinode_modulesdanloadmoduldengankeywordrequire.

varapp=require('express');

//kodelainnya

MembuatPaketnpmSebelummembuatpaketnpmpastikanfungsionalitasyangandacaritidakadadalamregistrynpm.Caranyayaituandabisamenggunakanperintah

npmsearch

ataudenganmemakaiwebsiteberikutnpmjs.org,node-modules.comataunpmsearch.com

Untukmembuatpaketnpmcaranyacukupmudah.Berikutalurumumuntukmembuatpaketnpmuntukdipublishkeregistrynpmjs.org.

AplikasiWebNode.js

29Paketnpm

Secaragarisbesarprosespembuatanpaketnpmmenurutalurdiatasakandijelaskansebagaiberikut

Registrasi

Sebelumpublishkeregistrynpmjs.orgkitaharusregistrasidulumelaluiperintahberikut

AplikasiWebNode.js

30Paketnpm

npmadduser

BuatProject

Untukmembuatprojectbarudarinollangkahpertamaadalahmembuatdirektori

mkdirnpmproject

Kemudianinisialisasiprojecttersebut

npminit

perintahdiatasakanmembuatfilepackage.jsonyangisinyaadalahinfodandependensiproject.Ikutisajatiappertanyaandanisiinformasisesuaidenganpaketyanginginandabuat.

Contohnyapadapaketsvhberikutini

package.json

{

"name":"svh",

"version":"0.0.7-beta",

"author":"EquanPr.",

"description":"Simplefileserverforhtml-javascriptwebclientappdevelopment",

"keywords":[

"process",

"reload",

"watch",

"development",

"restart",

"server",

"monitor",

"auto",

"static",

"nodemon"

],

"homepage":"https://github.com/junwatu/svh",

"bugs":"https://github.com/junwatu/svh/issues",

"main":"./lib/core.js",

"scripts":{

"test":"./node_modules/mocha/bin/mocha"

},

"dependencies":{

"async":"~0.2.9",

"chalk":"0.2.x",

"cheerio":"0.12.x",

AplikasiWebNode.js

31Paketnpm

"commander":"2.0.x",

"compression":"^1.0.2",

"concat-stream":"1.0.x",

"express":"4.x",

"morgan":"^1.1.1",

"send":"^0.3.0",

"watch":"0.8.x",

"wordgenerator":"0.0.1"

},

"devDependencies":{

"gulp":"^3.5.6",

"gulp-uglifyjs":"^0.3.0",

"gulp-util":"2.2.14",

"mocha":"1.13.x",

"supertest":"0.8.x"

},

"repository":{

"type":"git",

"url":"http://github.com/junwatu/svh.git"

},

"bin":{

"svh":"./bin/svh"

},

"license":"MIT"

}

PublishLokal

Sebelumdipublishpastikanpaketandabisaberjalanataudigunakanpadakomputerlokal.Perintahberikutakanmenginstallpaketandasecaraglobaldikomputer.

npmpublish.-g

ataujikadiinginkanlinksimbolikbisamemakaiperintahnpmberikut

npmlink

PublishPublik

npmpublish

Untuklebihjelasnyasilahkankunjungidokumentasiuntukdevelopernpm.

AplikasiWebNode.js

32Paketnpm

ExpressJSUntukmemudahkanpembuatanaplikasiwebandabisamenggunakanframeworkExpressJSdaripadaharusmenggunakanmodulehttpbawaanNode.js.Frameworkinimenawarkanbeberapafitursepertirouting,renderingviewdanmendukungmiddlewaredengankatalainandaakanbanyakmenghematwaktudalampengembanganaplikasiNode.js.

ExpressJSmerupakanframeworkminimalyangsangatfleksibel.AndabisamembuatwebserverHTML,serverfilestatik,aplikasichat,searchengine,sosialmedia,layananwebdenganaksesmelaluiRESTAPIatauaplikasihybridyaituselainpenggunamempunyaiaksesmelaluiRESTAPIjugamempunyaiakseskeHTMLpage.

AplikasiWebNode.js

33ExpressJS

ServerFileSebelumnyabikinprojectkecildenganmengetikkanperintahberikutpadadirektoriproject

$npminit

danberikannamaprojectsebagaiserver-file-statik.Direktoriprojectdariserverfilebisadilihatpadasususantreedibawahini.

Susunanfiledandirektori

server-file-statis

├──package.json

├──app.js

├──node_modules

└──publik

├──index.html

DenganadanyanpminstalasiExpressJSsangatmudah,ketikperintahberikutpadadirektoriproject.

$npminstallexpress--save

Catatan:

PerintahdiatasakanmenginstallExpressJSdenganversiyangpalingterbaru(padasaatbukuiniditulisversiterbaruadalah4.x).Jikamembutuhkanversitertentucukupdenganmenambahkan'@'dannomerversiyangakandiinginkanseperticontohberikut

$npminstallexpress@3--save

UntukkedepannyabahasanmengenaiExpressJSiniakanmemakaiversi4.x.

Kode

AplikasiWebNode.js

34ServerFile

JikaandaingatserverfileyangmemakaimodulhttppadababsebelumnyaberikutmerupakanversiyangmemakaiExpressJS

app.js

'usestrict';

varexpress=require('express');

varserver=express();

varlogger=require('morgan');

server.use(logger('dev'));

server.use(express.static(__dirname+'/publik'));

server.listen(4000,function(){

console.log('Serverfilesudahberjalanbos!');

});

SepertiyangdijelaskanpadababsebelumnyauntukmemakaimoduleNode.jsdigunakankeywordrequire.

Modulexpressakanmenanganitiaprequestdariuserdankemudianakanmemberikanresponseberupafileyangdiinginkan.Padakodediatasfileyangakandiberikankepenggunadisimpanpadafolderpublik.

AplikasiWebNode.js

35ServerFile

MiddlewareFungsionalitasyangdiberikanolehExpressJSdibantuolehyangnamanyamiddlewareyaitufungsiasinkronyangbisamengubahrequestdanrespondiserver.

Padakodediatascontohmiddlewareyaitumodulmorgan.Carapemakaianmiddlewareyaitumelaluiapp.use().

Modulemorganmerupakanmoduluntukloggeryangberfungsiuntukpencatatantiaprequestkeserver.Pencatataniniatauistilahnyaloggingakanditunjukkandiconsoleterminal.

Untukmenginstallmoduliniketikperintahberikut

$npminstallmorgan--save

Middlewaremiddlewareinibisaandalihatdilinkberikut

https://github.com/senchalabs/connect#middleware

AplikasiWebNode.js

36Middleware

AksesServerUntukmenjalankanserverfilestatikini

$nodeapp.js

Andabisameletakkanfileapasajapadadirektori'publik'.Untukmengaksesserveriniketikalamatberikutpadabrowser

http://localhost:4000

dansecaradefaultakanmenampilkanfileindex.htmldibrowser.

UntukmengaksesfileyanglainformatURLadalah

http://localhost:4000/[nama-file]

misalnyauntukmengaksesfileimg.jpg

AplikasiWebNode.js

37AksesServer

ServerRESTFrameworkExpressJSsangatbanyakdigunakansebagaiaplikasiRESTful.Bagiandayangbelumtahu,RESTatauRepresentationalStateTransferadalaharsitekturyangdigunakandalamdesainaplikasinetwork.IdenyayaitudaripadamemakaitekniksepertiCORBA,SOAPatauRPCuntukmembuatWebServicelebihbaikjikamemakaiprotokolHTTPyanglebihmudah.

AplikasiRESTfulmemakairequestHTTPuntukoperasiCreate,Read,UpdatedanDeletedata.RESTitusendiribukanlahsuatustandardjaditidakadayangnamanyaspecdariW3C.Sehinggasangatmudahbagibahasapemrogramanuntukmenggunakanarsitekturini.KeuntunganlainnyayaitudenganarsitekturinibisadibangunberbagaimacamteknologikliensepertiwebataumobileataupundekstopuntukmengaksesaplikasiRESTfultersebut.

UntukcontohaplikasiRESTfulmemakaiExpressJSakandiberikanpadaBabPersonRESTAPI.

AplikasiWebNode.js

38ServerREST

DatabaseBerkembangpesatnyakomunitasNode.jsmenyebabkandukunganpustakayangsemakincepatjuga.DenganwaktuyangrelatifcepatplatforminisekarangmendukungbanyaktipedatabasesepertiSQLite,MySQL,MongoDB,Redis,CouchDBdll.Dalambukuinihanyaakandibahasa3databasesajayaituSQLite,MySQLdanMongoDB.

AplikasiWebNode.js

39Database

SQLiteMungkindatabaseinisudahtidakasinglagibagidevelopersepertiandakarenamemangbanyakdigunakandalamaplikasiportabledanembeddable.

KekuatanSQLitesecaragarisbesarsebagaiberikut

Serverless

SQLitetidakmemerlukanproseslainuntukberoperasisepertipadadatabaselainyangumumnyasebagaiserver.LibrarySQLiteakanmengaksesfiledatasecaralangsung.

ZeroConfiguration

Karenasifatnyabukanservermakadatabaseinitidakmemerlukansetuptertentu.Untukmembuatdatabasecukupsepertiketikamembuatfilebaru.

Cross-Platfrom

Semuadatatersimpanpadasatusistemfileyangbersifatcrossplatformdantidakmemerlukanadministrasi.

Self-Contained

LibrarySQLitesudahmencakupsemuasistemdatabasesehinggadenganmudahdapatdiintegrasikankeaplikasihost.

SmallRuntimeFootprint

UkurandefaultdariSQLiteinikurangdari1MBdanmembutuhkanhanyabeberapaMegabytememory.

Transactional

OperasitransaksikompatibeldenganACIDsehinggaamankalauharusmengaksesdatadariprosesbanyakthread.

Untukpenjelasanlebihdetil,silahkankunjungiwebsiteresmihttp://sqlite.org

AplikasiWebNode.js

40SQLite

nodesqlite3KomunitasnodemenyediakanbanyaksolusiuntukmemakaiSQLitediplatformNode.js.Salahsatuyangpalingpopuleradalahmodulnode-sqlite3.

Instalnodesqlite3merupakanbindingmodulJavaScriptyangasinkronuntukdatabasesqlite3.

Untukpenginstalanmoduliniketikperintahberikut

$npminstallsqlite3--save

CRUDOperasidatabasesepertiCreate,Read,UpdatedanDeleteuntukdatabaseSQLitesangatmudahsepertipadacontohberikut

app.js

/**

*AksesSQLite3

*/

varsqlite=require('sqlite3').verbose();

varfile='film.db';

vardb=newsqlite.Database(file);

varfs=require('fs');

//SampleData

varfilm={

judul:"Keramat",

release:"2009",

imdb:"http://www.imdb.com/title/tt1495818/",

deskripsi:"Filmhorrorpalinghorror!"

}

varfilmUpdate={

id:1,

deskripsi:"BestIndonesianHorrorMovie."

}

//SQLStatement

varCREATE_TABLE="CREATETABLEIFNOTEXISTSfdb(idINTEGERPRIMARYKEYAUTOINCREMENT,judulTEXTNOTNULL,releaseTEXTNOTNULL,imdbTEXT,deskripsiTEXT)";

AplikasiWebNode.js

41NodeSqlite3

varINSERT_DATA="INSERTINTOfdb(judul,release,imdb,deskripsi)VALUES(?,?,?,?)";

varSELECT_DATA="SELECT*FROMfdb";

varUPDATE_DATA="UPDATEfdbSETdeskripsi=$deskripsiWHEREid=$id";

//RunSQLoneatatime

db.serialize(function(){

//Createtable

db.run(CREATE_TABLE,function(err){

if(err){

console.log(err);

}else{

console.log('CREATETABLE');

}

});

//Insertdatawithsampledata

db.run(INSERT_DATA,[film.judul,film.release,film.imdb,film.deskripsi],function(err){

if(err){

console.log(err);

}else{

console.log('INSERTDATA');

}

});

//Queryalldata

selectAllData();

//Updatedata

db.run(UPDATE_DATA,{$deskripsi:filmUpdate.deskripsi,$id:filmUpdate.id},function(err){

if(err){

console.log(err);

}else{

console.log('UDATEDATA');

}

});

selectAllData();

db.run('DELETEFROMfdbWHEREid=$id',{$id:1},function(err){

if(err){

console.log(err)

}else{

console.log("DELETEDATA");

};

})

});

functionselectAllData(){

db.each(SELECT_DATA,function(err,rows){

if(!err){

console.log(rows);

AplikasiWebNode.js

42NodeSqlite3

}

})

}

Aplikasidiatasakanmembuattabelfdb,memasukkandatabarukemudiandatatersebutakandiupdatedanterakhirakandihapus.

ContohdiatasmemakaiAPIberikutini

db.serialize()

db.run(operasi_sqlite,callback)

Denganmemakaifungsidb.serialize()makaeksekusisqlakandieksekusisecaraserialatauberurutandanoperasiSQLapasajabisadieksekusiolehnode-sqlite3denganmemakaimetodedb.run()tersebut.

PenjelasanAPIlebihlanjutuntukNodeSQLitebisadilihatpadalinkberikut

https://github.com/mapbox/node-sqlite3/wiki/API.

AplikasiWebNode.js

43NodeSqlite3

EnkripsiKalauandamemakaiSQLitedanmembutuhkansupayadatabaseiniterenkripsimakaberuntunglahkarenanodesqlite3mendukungpenggunaandatabaseSQLiteyangterenkripsi.

EnkripsiyangdidukungolehSQLiteyaitumelaluiekstensisqlcipher.Sqlciphermerupakanekstensisqliteyangmendukungenkripsi256bitAES.Ekstensiinibisadididownloadmelaluiwebsiteberikut

https://github.com/sqlcipher/sqlcipher

AplikasiWebNode.js

44Enkripsi

sqlcipherInstalasiekstensiinisangatmudahyaitujikaandaberadadalamlingkunganLinux

$sudoapt-getinstalllibsqlcipher-dev

Kemudiankompilasiulangnode-sqlite3denganperintahberikutini

$npminstallsqlite3--build-from-source--sqlite_libname=sqlcipher\

--sqlite=/usr/

Untukmenggunakanfiturenkripsiiniperuditambahkanbeberapabariskodeberikutpadaaplikasinode-sqlite3.

//encryptdatabase

db.run('PRAGMAkey="passwordmu!"');

PadacontohCRUDnode-sqlite3padabagiansebelumnyakodediatasbisadituliskansebelumoperasiCRUDataupadasaatinisialisasi.

...

//RunSQLoneatatime

db.serialize(function(){

//encryptdatabase

db.run('PRAGMAkey="passwordmu!"');

//Createtable

db.run(CREATE_TABLE,function(err){

if(err){

console.log(err);

}else{

console.log('CREATETABLE');

}

});

...

BandingkanjikaSQLitetidakmemakaienkripsi,andabisamenggunakanSQLiteBrowseratautoolhexdumppadaLinux

AplikasiWebNode.js

45Enkripsi

danjikaSQLitememakaienkripsibisadilihatdariscreenshotdibawahinibahwaisidaridatabasemenjadi"meaningless".

AplikasiWebNode.js

46Enkripsi

AplikasiWebNode.js

47Enkripsi

MySQLKalauandaterbiasadenganbahasapemrogramanPHPmakapastisudahtidakasinglagidengandatabaserelasionalyangpalingbanyakdipakaisaatiniyaituMySQL.

AplikasiWebNode.js

48MySQL

NodeMySQLImplementasidriverdariMySQLuntukplatformNode.jssudahsangatmaturesepertimodulnode-mysqldihttps://github.com/felixge/node-mysql/

InstalasiSepertibiasauntukmenginstallmodulinidansecaraotomatismenyimpannama&versimoduldifilepackage.jsonyaitudenganmemakaiperintahberikut

$npminstall--savemysql

KoneksiSederhanaUntukmembuatkoneksikedatabaseMySQLsalahsatucaranyaadalahdenganmenggunakanmetodeconnection.connect()

AplikasiWebNode.js

49NodeMySQL

//app.js

varmysql=require('mysql');

/**

*Settingopsidariconnection,

*lihathttps://github.com/felixge/node-mysql/

*/

varconnection=mysql.createConnection({

host:'localhost',

user:'root',

password:''

});

//MembukakoneksikedatabaseMySQL

connection.connect(function(err){

if(err){

console.log(err);

}else{

console.log('Koneksidenganid'+connection.threadId);

}

});

//Querybisadilakukandisini

//Menutupkoneksi

connection.end(function(err){

if(err){

console.log(err);

}else{

console.log('koneksiditutup!');

}

});

QueryIstilahquerymungkinmenurutmindsetumumartinyaadalahmengambildatadaridatabasetetapidalammodulnode-mysqliniuntukmembuatdatabaseatauschemajugadidefiniskansebagaiquery.Adabeberapabentukfungsiuntukwrapperquery

connection.query(sqlString,callback)

DenganmemakaistatemenSQLkitabisamembuatschemadatabaseebooksepertiberikut

AplikasiWebNode.js

50NodeMySQL

varcreate_db='CREATEDATABASEIFNOTEXISTSebook'

connection.query(create_db,function(err,result){

if(err){

console.log(err);

}else{

console.log(result);

}

)

connection.query(sqlString,value,callback)

Misalnyauntukmenyimpandatasemuajudulbukupadadatabaseebook

varebook={

id:1,

title:'WiroSablengPendekarKapakMautNagaGeni212:BatuTujuhWarna',

pengarang:'BastianTito'

}

varinsert_sql='INSERTINTOebookSET?';

connection.query(insert_sql,ebook,function(err,result){

err?console.log(err):console.log(result);

})

KalaudibutuhkanescapingvaluesebelumdimasukkankedatabaseMySQLbisamemakaimetode.escape()ataupakeplaceholder?.

varebook={

id:1,

title:'WiroSablengPendekarKapakMautNagaGeni212:BatuTujuhWarna',

pengarang:'BastianTito'

}

varinsert_sql='UPDATEebookSETtitle=?WHEREid=?';

connection.query(insert_sql,[ebook.title,ebook.id],function(err,result){

err?console.log(err):console.log(result);

})

connection.query(options,callback)

Bentukwrapperqueryyangterakhirinicukupringkas.Sesuaikansajamanabentukwrapperyangsesuaidengankebutuhananda.

AplikasiWebNode.js

51NodeMySQL

varebook={

sql:'INSERTINTOebookSETpengarang=?',

timeout:14000,

values:['PramoedyaAnantaToer']

}

connection.query(ebook,function(err,result,fields){

if(err){

console.log(err);

}else{

console.log(result);

}

})

MetodequeryinisangatfleksibeldanpadaintinyakitabisamemakaistatemenSQLyangbiasadipakaiuntukquerydatadiMySQL.Jadipenggunaandarimodulnpminisebenarnyacukuplahmudah.

UntukpenggunaanmodulnpminilebihlanjutsilahkankunjungiGithubnode-mysqldanuntukcontohaplikasiyangmemanfaatkandatabaseinibisadilihatpadababPengubahGambarPNGKeDataURI.

AplikasiWebNode.js

52NodeMySQL

MongoDBKalauandasudahterbiasamemakaidatabaserelasionalsepertiMySQLmungkindiperlukansedikitperubahanmindsetuntukmengenaltipedatabaseyangnamanyaNoSQL.Sepertiartidarinamanya,databaseinimerupakandatabaseyangtidakmemakaibahasaSQLquerydatatapibisasecaralangsungmenggunakanbahasapemrogramanclientsebagaicontohadalahMongoDB.

DatabaseNoSQLsepertiMongoDBmenyimpandatasebagaidokumenyangschema-lessyangartinyayaitudatayangdisimpanmempunyaikey-valueyangtidakterikatataubebas.AndabisamembayangkannyasebagaidataJSONyangtersimpandidatabase.

KlienbisaberinteraksilangsungdengandatabaseMongoDBdenganmenggunakanshellJavaScriptmongountukadministrasidanquerydata.Sebagaicontohjikakitainginmembuatsampledatasebanyak100dicollectionsamplemakaperintahdalamshelladalahsepertiberikut,

AplikasiWebNode.js

53MongoDB

$mongo

MongoDBshellversion:2.6.9

connectingto:test

>usesample;

switchedtodbsample

>for(vari=0;i<100;i++){db.sample.insert({band:"Dewa"+i})};

WriteResult({"nInserted":1})

>db.sample.count()

100

>db.sample.find();

{"_id":ObjectId("55cf520e2dd317a13673d11b"),"band":"Dewa0"}

{"_id":ObjectId("55cf520e2dd317a13673d11c"),"band":"Dewa1"}

{"_id":ObjectId("55cf520e2dd317a13673d11d"),"band":"Dewa2"}

{"_id":ObjectId("55cf520e2dd317a13673d11e"),"band":"Dewa3"}

{"_id":ObjectId("55cf520e2dd317a13673d11f"),"band":"Dewa4"}

{"_id":ObjectId("55cf520e2dd317a13673d120"),"band":"Dewa5"}

{"_id":ObjectId("55cf520e2dd317a13673d121"),"band":"Dewa6"}

{"_id":ObjectId("55cf520e2dd317a13673d122"),"band":"Dewa7"}

{"_id":ObjectId("55cf520e2dd317a13673d123"),"band":"Dewa8"}

{"_id":ObjectId("55cf520e2dd317a13673d124"),"band":"Dewa9"}

{"_id":ObjectId("55cf520e2dd317a13673d125"),"band":"Dewa10"}

{"_id":ObjectId("55cf520e2dd317a13673d126"),"band":"Dewa11"}

{"_id":ObjectId("55cf520e2dd317a13673d127"),"band":"Dewa12"}

{"_id":ObjectId("55cf520e2dd317a13673d128"),"band":"Dewa13"}

{"_id":ObjectId("55cf520e2dd317a13673d129"),"band":"Dewa14"}

{"_id":ObjectId("55cf520e2dd317a13673d12a"),"band":"Dewa15"}

{"_id":ObjectId("55cf520e2dd317a13673d12b"),"band":"Dewa16"}

{"_id":ObjectId("55cf520e2dd317a13673d12c"),"band":"Dewa17"}

{"_id":ObjectId("55cf520e2dd317a13673d12d"),"band":"Dewa18"}

Type"it"formore

>

UntuklebihjelasnyajikaandatertarikuntukbermainmaindenganterminalMongoDBsilahkankunjungidokumentasinya.

SebelumkitalanjutkankekoneksiNode.jsdanMongoDB,perludiingatbeberapakonseppentingdariMongoDB

Collection

Collectionadalahkumpulandaridocument,analoginyawalaupunkurangtepatsebenarnyabisadibilangsepertitabelkalodalamdatabaserelasional.

Document

AplikasiWebNode.js

54MongoDB

DocumentitusendiriadalahdatayangtersimpandidatabaseNoSQLdandidefinisikanolehyangnamanyaSchema.

Schema

SebelumnyadikatakanbahwaNoSQLmenyimpandatayangschema-less,memangbenartapitetapuntukmenyimpansuatudokumendidatabasebiasanyaaplikasibekerjadenganmodeldatatertentumisalnyauntukdataPersonbisamempunyaikey-valuesepertiberikut

{

nama:"KeboIjo",

email:"[email protected]",

username:"obek_seloso"

}

AplikasiWebNode.js

55MongoDB

NodeMongoDBMongoDBmenyediakandriverresmiuntukplatformNode.js.Modulenpminitersediadilinkberikuthttps://www.npmjs.com/package/mongodbdandapatdenganmudahdiinstallmelaluinpm

$npminstall--savemongodb

PenulismengasumsikanbahwaMongoDBsudahterinstaldanberjalanpadasistem.Untukmemulaikoneksidapatdenganmudahdilakukansepertiscriptberikutini,

app.js

varMongoClient=require('mongodb').MongoClient;

varMONGODB_URL='mongodb://localhost:27017/sample';

MongoClient.connect(MONGODB_URL,function(err,db){

err?console.log(err):console.log('KoneksikeMongoDBOk!');

db.close();

});

MongoDBakanmembuatdatabasebarujikadatabasetersebuttidakada,sepertihalnyadengandatabasesamplepadakodediataskarenasebelumnyadatabaseinitidakadamakasecaraotomatisMongoDBakanmembuatnya.BentukumumURIuntukkoneksikeMongoDBadalahsepertiberikut

mongodb://<username>:<password>@<localhost>:<port>/<database>

JalankanapikasiditerminaldanjikatidakadamasalahmakaakanmunculpesanpadakonsolbahwakoneksikeMongoDBtelahsukses.

$nodeapp.js

KoneksikeMongoDBOk!

BerikutnyaakankitalakukanoperasidasaruntukMongoDByaituCRUDtapisebelumnyakitabuatschematerlebihdahulu.

person.js

AplikasiWebNode.js

56NodeMongoDB

functionPersonSchema(data){

this.nama=data.nama;

this.email=data.email;

this.username=data.username;

};

module.exports=PersonSchema;

SchemadiatasmerupakanmodeldatasederhanayangdituliskandalamobjectJavaScriptdantanpabuilt-intypecastingataupunfiturvalidasi.Jikaandamembutuhkanpemodelandatayanglebihhandaldanlebihbaik,makapakailahpustakaODM(Object-DocumentModeler)sepertiMongoose.

DriverNodeMongoDBmenyediakanAPIyanglengkapuntukbekerjadengandatabaseini.SilahkanlihatlinkberikutuntukmelihatlebihlengkaptentangAPIini

http://mongodb.github.io/node-mongodb-native/2.0/api/Collection.html#insert

InsertUntukmemasukkandokumenbisamemakaimetodeinsertOne()untukmemasukkansatudokumen

app.js

AplikasiWebNode.js

57NodeMongoDB

/**

*BalajarNode-MongoDB

*

*

*MIT

*EquanPr.2015

*/

varPersonSchema=require('./person.js');

varMongoClient=require('mongodb').MongoClient;

varMONGODB_URL='mongodb://localhost:27017/sample';

varperson=newPersonSchema({

nama:'KeboIjo',

email:'[email protected]',

username:'obek_rebo'

});

MongoClient.connect(MONGODB_URL,function(err,db){

err?console.log(err):console.log('KoneksikeMongoDBOk!');

db.collection('persons').insertOne(person,function(err,result){

if(err){

console.log(err);

}else{

console.log(result);

}

db.close();

})

});

Secaraotomatisoperasiinsertiniakanmenghasilkanprimarykey_idyangunikyaituberupaObjectId.Yangmembedakan_idinidenganidpadadatabaseyanglainadalahdenganObjectIdbisadidapatkankapandatainidimasukkanmelaluipemakaianmetodegetTimestamp().

$mongo

MongoDBshellversion:2.6.9

connectingto:test

>_id=ObjectId()

ObjectId("55d81f48bb934a51424dbd37")

>ObjectId("55d81f48bb934a51424dbd37").getTimestamp();

ISODate("2015-08-22T07:05:44Z")

>

AplikasiWebNode.js

58NodeMongoDB

Jikaandamempunyaibanyakdokumen,untukmemasukkandokumen-dokumentersebutkecollectionpersonsandabisamemakaimetodeinsertMany().

UpdateOperasiupdatedatajugacukupmudahapalagijikaandasangatpahamntentangMongoDB.Untukmeng-updatedatabisadilakukanmelaluimetodeupdateOne()atauupdateMany().

app.js

varPersonSchema=require('./person.js');

varMongoClient=require('mongodb').MongoClient;

varMONGODB_URL='mongodb://localhost:27017/sample';

varperson=newPersonSchema({

nama:'KeboIjo',

email:'[email protected]',

username:'obek_rebo'

});

MongoClient.connect(MONGODB_URL,function(err,db){

err?console.log(err):console.log('KoneksikeMongoDBOk!');

db.collection('persons').insertOne(person,function(err,result){

if(err){

console.log(err);

}else{

console.log('Simpandatapersonok!');

//updatedata

varpersonUpdate={

nama:'SukatTandika'

}

db.collection('persons').updateOne({nama:person.nama},personUpdate,function(err,result){

if(err){

console.log(err);

}else{

console.log('Datapersonberhasildimodifikasi!');

}

db.close();

})

}

})

});

MetodeupdateOne()mempunyaibeberapaargumensepertiberikut

AplikasiWebNode.js

59NodeMongoDB

updateOne(filter,update,options,callback)

Untukdataupdateandabisamemakaioperatorseperti$setcontohnyasepertiberikutini

db.collection('persons').updateOne({nama:person.nama},{$set:{nama:'Angel'}},function(err,result){

if(err){

console.log(err);

}else{

console.log('Datapersonberhasildimodifikasi!');

}

db.close();

})

daribeberapaoptionsyangterpentingadalahkeyupsertyaituupdateinsertdanjikaoptioninidiberikanmakajikadatayangakandi-updatetidakadamakaMongoDBsecaraotomatisakanmembuatdatayangbaru.UntuklebihjelasnyaandabisamelihatdokumentasidariAPIupdateOne().

QueryQuerydatapadadatabaseMongoDBdapatdenganmudahdilakukandenganmemakaimetodefind(),sebagaicontohuntukmenemukandatapersonpadacollectionpersons

AplikasiWebNode.js

60NodeMongoDB

MongoClient.connect(MONGODB_URL,function(err,db){

if(!err){

findPerson({nama:'MorbidAngel'},db,function(err,doc){

if(!err){

console.log(doc);

}else{

console.log(err);

}

db.close();

});

}else{

console.log(err);

}

});

functionfindPerson(filter,db,callback){

varcursor=db.collection('persons').find(filter);

cursor.each(function(err,docResult){

if(err){

callback(err,null);

}else{

if(docResult!=null){

console.log(docResult);

callback(null,docResult);

}else{

callback(null,'empty!');

}

}

})

}

Denganmetodefind()andabisamemakaioperatorqueryseperti$lt,$gt,operatorkondisiAND,ORdll.UntuklebihlengkapnyasilahkanlihatdokumentasiquerydaridrivernodeMongoDB.

DeleteUntukmenghapusdataandabisamenggunakanfungsideleteOne()ataudeleteMany().Misalnyauntukmenghapussemuadatapadacollectionpersonsandabisamenggunakanemptyobject{}sebagaiquery.

AplikasiWebNode.js

61NodeMongoDB

functiondeleteAllPerson(db,callback){

db.collection('persons').deleteMany({},function(err,rec){

if(!err){

callback(null,rec.result.n);

}else{

callback(err,null);

}

})

}

ataujikainginmenhapussatudatapadacollectionperson

fucntiondeletePerson(filter,db,callback){

db.collection('persons').deleteOne(filter,function(err,rec){

if(!err){

callback(null,rec.result.n);

}else{

callback(err,null);

}

})

}

DuafungsiinibisaandalihatsecaralengkappadadokumentasiAPIMongoDB.

AplikasiWebNode.js

62NodeMongoDB

MongooseSepertidikatakansebelumnyauntukmemudahkanpemodelandatadiMongoDBandabisamemakaipustakaMongoose.MeskipunsebenarnyaMongoosememakaiobjekJavaScriptbiasadanmendukungbanyakmetodequerydatatetapiyangpalingmembedakanadalahMongoosemendukungschematypedanvalidasidilevelschema.

data:{type:schemaType}

SchemaTypeAdabeberapaschematypeyangdidukungolehpustakainiyaitu

StringNumberDateBooleanBuffer(untukdatabinarymisalnyagambar,mp3dll.)Mixed(datadengantipeapasaja)ArrayObjectId

PemodelanDataLalubagaimanaMongoosememodeldata?ambilcontohmisalnyadalampengembanganaplikasi,datayangakandipakaisepertiberikut

varlokasiWisataKotaBatu=[{

nama:'BatuNightSquare',

alamat:'Jl.Orooroombo13,Tlekung'

rating:3,

fasilitas:['Wahanabermain','Rollercoaster','Tamanlampion']

}]

DaridatadiatasdenganmemakaiMongoosesangatmudahuntukditerjemahkankeskemadantipedatauntuktiapfield

AplikasiWebNode.js

63Mongoose

varlokasiWisataKotaBatuSchema=newmongoose.schema({

nama:String,

alamat:String,

rating:Number,

fasilitas:[String]

})

Bagaimanadenganvalidasidata?.Jikaandalihatfielddataratingdiatasdanumumnyamempunyainilaiantara0-5danjikasecaradefaultdiberinilai0makaskemaratingakanmenjadi

rating:{type:Number,'default':0}

Andajugabisamemakaikeyrequireduntukmenandakanbahwafielddatatersebutbersifatwajibadamisalnya

nama:{type:String,required:true}

UntuklebihjelasnyasilahakanlihatdokumentasidariValidatorsMongoose.

Aplikasinode.jsdengandatabaseMongoDByangmemakaipustakaMongoosedapatdikatakanmempunyaihubunganrelasisatu-satuartinyadenganmemakaimodelMongooseberartisecaralangsungaplikasiakanmemakaidatapadaMongoDB.

KalaumisalnyaandabekerjadengandatabaserelasionalMySQLmakaandaakanmemakaibahasaSQLsepertiINSERTINTOtableVALUES(field1=data)untukmemasukkandatasedangkansepertiandaketahuijikadengandatabaseNoSQLuntukmenyimpanmodelobjectcukupdenganmemakaimetodemisalnyamodel.save().DalamMongooseuntukmemakaimodelyangtelahmempunyaischemasepertidiatas

varLokasiModel=mongoose.model('Lokasi',lokasiWisataKotaBatuSchema,'lokasiWisataBatu')

KodediatasmemberiartibahwaaplikasiakanmemakaimodelLokasidenganschematypeyangtelahdidefinisikansebelumnyayaitulokasiWisataKotaBatuSchemadanmodeliniakandisimpanpadakoleksidatadiMongoDBdengannamakoleksiadalahlokasiWisataBatu.

UntukmemakaimodelLokasicaranyaadalahdenganmenciptakaninstancedarimodeltersebut

AplikasiWebNode.js

64Mongoose

varlokasiModel=newLokasiModel()

lokasiModel.nama='MuseumAngkut'

lokasiModel.alamat='Jl.Kembar11'

lokasiModel.rating=5

lokasiModel.fasilitas=['Restoran','Parkirluas']

KemudianuntukmenyimpandatatersebutkedalamdatabaseMongoDB

lokasiModel.save(function(err){

if(!err)console.log('DataDisimpan!')

})

Cukupmudahbukandanmemangpustakainibertujuanuntukmemudahkandeveloperdalampemodelandataterutamajikadatayangakandimodelmempunyaistrukturyangrumitmisalnyanesteddocument.Untuklebihlengkapnyasilahkanandamengunjungisitusresmimongoosejs.com.

ProjekBagiandayangsudahmengertigambaranumumdaripustakaMongooseinisilahkanmengutakatikcontohprojeksederhanayangmemakaiframeworkExpressJSdanMongoose,PersonRESTAPI.

AplikasiWebNode.js

65Mongoose

TestingPerangkatlunaktidakadayangsempurnadanpastimempunyaibugs.Salahsatucarauntukmenguranginyaataumencegahnyauntukmunculdikemudianhariadalahdenganjalanmelakukanpengetesan.Pengetesanmemberikankeyakinanpadadeveloperbahwaperangkatlunakbekerjasebagaimanamestinyadanjikaadaperubahanmisalnyapenambahanataupenguranganfiturdipastikanbahwapengetesanakanselaluberhasil.

AdabanyaktipepengetesantetapidalampengembanganaplikasiwebadaduatipepengetesanyangpentinguntukdiketahuiyaituUnitTestingdanAcceptanceTesting.

UnitTestingUnitTestingdilakukanlangsungpadalevelkodeaplikasiyaitupadafungsiataumetodedanadaduametodologiyangseringdigunakanyaituTDDdanBDD.DalamJavaScripttersediabanyakpustakayangdibuatuntukpengetesansepertimoduleassertbawaandariNode.js,Nodeunit,Mocha,Jasminedll.

TestDrivenDevelopment(TDD)

IstilahTDDinimenjadisangatkerenbeberapatahunbelakanganini.KonsepTDDadalahmelakukanpengetesanterlebihdahulubarukemudianmenuliskodedariaplikasi,jadimindsetdaripembuatanperangkatlunakdibalikkalodalampengembanganperangkatlunakyangkonvensionalalurnyayaitumenuliskodeterlebihdahulubarukemudianmenuliskodeuntukpengetesansedangkandalamTestDrivenDevelopmentprosesinidibalik.

Kelemahanpengetesaniniadalahpadaprosesawalbiasanyadibutuhkanwaktuyangrelatiflebihlamauntukmengembangkanaplikasikarenaharusmenuliskodepengetesanterlebihdahulutetapikeuntunganjangkapanjangnyayaituaplikasiyangdihasilkanbiasanyamempunyaibugsyanglebihsedikit.

BehaviorDrivenDevelopment(BDD)

PengetesansecaraBDDmemakaibahasaataumetodepengetesanyanglebihramahyaitudenganmelakukanpengetesandengancaraataualursepertiuserstorysehinggapengetesaninirelatiflebihpopulerkarenasecarabahasamenjembataniataumemungkinkankolaborasiantaradeveloperdanklien.AdabanyakpustakapengetesanyangmemakaiBDDsepertiMocha,Jasmin,Vowsdll.SebagaigambarancontohuntukpustakaMochamisalnya

AplikasiWebNode.js

66Testing

describe('Uploadfile',function(){

it('Harusbisamenerimafilejpeg',function(){

//testingdisini

})

it('Harusbisamenerimafilepng',function(){

//testingdisini

})

it('Harusbisamenerimafilexcf',function(){

//testingdisini

})

})

KalauditerjemahkansecarabahasamanusiamakakodetestingBDDdiatasakanmudahdibacayaituUploadfileharusbisamenerimafilejpeg,pngatauxcf.

AcceptanceTestingUntukpengetesandariantarmukaaplikasiwebbesertafungsinyacontohnyasepertipengetesanpenekananbuttonapakahberfungsidenganbaikatautidakadalahtermasukdariAcceptanceTesting.TestinginibisadilakukandenganmemakaibantuanbrowserdandenganmunculnyaheadlessbrowsersepertiPhantomJSmemungkinkanpengetesandilakukansecaraterintegrasidengankodeback-end.

Catatanpentingdaritestingadalahpengetesandiusahakanberjalansecaraautomatissehinggajikaadakesalahanyangterjadimakadeveloperbisasegeramemperbaikinya,makadariitutestingpastimempunyaiyangnamanyainfolaporanentahituberupafile,outputterminalatauantarmukaberupaweb.Padaprosespengembanganperangkatlunakmodern,automasitestingmerupakanbagianyangsangatpenting.

DalambukuinipengetesanakandibatasipadapengetesanaplikasiwebkhususnyaaplikasiNode.jsdenganRESTdenganmemakaiMocha.

AplikasiWebNode.js

67Testing

PengetesanRESTKitaambilcontohserveryangdibuatdenganExpressJS.ServerdibawahiniakanmengeluarkandataberupaJSONpadaURL/.

varexpress=require('express')

varapp=express()

app.get('/',function(req,res){

res.json({

message:'hello'

})

})

module.exports=app

LalubagaimanacaramengetestURL/diatas?denganmemakaiMocha,moduleassertdanmodulSupertestyaitumodulnpmyangkhususuntukmengetestserverHTTP.MochatermasukpustakapengetesanyangbisadipakaisecaraBDDataupunTDD.PustakainisecaradefaultmemakaistyleBDDdanmetodeyangyangbiasadipakaiadalahdescribe&it.

varmocha=require('mocha')

varrequest=require('supertest')

varassert=require('assert')

varapp=require('../app')

describe('TestRESTAPI',function(){

describe('GET/',function(){

it('shouldreturnjsonwithkey"message"andvalue"hello"',function(done){

request(app).get('/')

.set('Accept','application/json')

.expect('Content-Type',/json/)

.expect(200)

.expect(function(res){

assert.equal(res.body.message,'hello')

})

.end(function(err,res){

if(err)returndone(err)

done()

})

})

})

})

AplikasiWebNode.js

68REST

PerluandaingatbahwasupertestakansecaraotomatismenjalankanserverExpressJSdanmengalokasikanportsehinggaandatidakperlumejalankanserversecaralangsung.

request(app)

Kalauditerjemahkandalambahasamanusiakodediatasakanmengetestbeberapakondisiyaitu

expect('Content-Type',/json/)

kodediatasartinyadiharapkanresponsedariGETuntukURL/adalahbertipejson

expect(200)

kodediatasartinyaresponsecodedarirequestHTTPharusmempunyaikode200.

expect(function(res){

assert.equal(res.body.message,'hello')

})

dankodediatasartinyadiharapkanbahwaresponsebodydenganfieldmessagemempunyaivaluehellodantentusajaandabisamenambahkanbanyakkondisiuntukpengetesanyanglebihdetil.

Untukmelakukanpengetesancukupdenganmenginstaldanjalankanmochamakasecaraotomatismochaakanmenjalankanberkasberkaspengetesanyangberadapadafoldertest.

$npminstall-gmocha

AplikasiWebNode.js

69REST

Sebenarnyabanyakyangbisadijelaskantentangpengetesandansudahbanyakresourceonlinediluarsanayangmembahastentanginitapiyangperluandaingatadalahpastikanpengetesandimasukkandalamalurkerjadalampengembanganperangkatlunakyangsedangandakerjakan.

AplikasiWebNode.js

70REST

AutomasiDalamprakteknyabiasanyatestinginidilakukansecaraotomatismisalnyajikaandamemakaiGithubdalampengembanganperangkatlunakopensourcemakaandabisamemakaiserverTravisyangdengansettingkonfigurasitertentuakanmenjalankanpengetesanjikaandamenge-pushkodekerepositoryGithubatauandabisamemakaibuildserveryangadadiluaransepertiJenkins,Bamboo,TeamCitydll.

TravisJikaandamemakaiGithubdanmenggunanakanTravismakasecaradefaultservertravisiniakanmenjalankancommand

$npmtest

sehinggadalampackage.jsonyangandapushkeGithubandaperlumenulisscriptuntukpengetesanmisalnyajikamemakaiMocha

"scripts":{

"test":"mocha"

}

.travis.yml

UntuksettingTravisandacukupmembuatfile.travis.ymlpadafolderprojekmisalnyasepertidibawahini(contohsourcecodeprojektestadadisini)

.

├──app.js

├──.travis.yml

├──node_modules

├──package.json

└──test

└──app.test.js

DenganisifiletersebutadalahversidariNode.jsdimanatestakandijalankan.MisalnyauntukmenjalankanpengetesanNode.jsversi4.1dan4.0

AplikasiWebNode.js

71Automasi

language:node_js

node_js:

-"4.1"

-"4.0"

KemudianandaperlumengaturkonfigurasirepodiGithub(TestingLearn).SupayaGithubbisamemakaiservicedariTravismakaandaperlumeengubahkonfigurasirepo(MasukkemenuSettings)

EnableBuild

SupayabuildselaludijalankanolehTravismakaandaharusmeng-ON-kantombolenableditravis-ci.orgpadarepoyangandainginkan.

TestBuild

AplikasiWebNode.js

72Automasi

BuildakandijalankanolehTravissetiapadakodebarudiGithubatauandabisamenggunakantombolTestServicepadaSettings->Webhooks&servicesuntukforcebuild.

Notifikasi

NotifikasiTravisbisadiintegrasikandenganSlack,Email,dllataubiasanyadengangambarstatusdiREADMErepo.UntukkonfigurasigambarstatuskliktombolBuild/PassingdisebelahnamarepodiTravisdancopypastekeREADMErepodiGithub.

SehinggajikaandamembukarepodiGithubmakaakanmunculgambarstatusyangapakahbuildsuksesataudalamstatuserror.

AplikasiWebNode.js

73Automasi

AplikasiWebNode.js

74Automasi

ToDataURIAplikasiiniadalahaplikasiNode.jsCLIyangmengubahgambarpngkeformatdataURIdankemudianmenyimpandatatersebutkedatabaseMySQL.Prosesinibisadigambarkansepertigambaralurdibawahini.

DataURIBagiyangbelumtahuDataURIadalahsalahsatucarauntukmeng-embeddatasecarainlinealih-alihharusmengambildatatersebutdariresourceluar.DatayangakandiubahkeDataURIdisinibisaberupaimage,filecsvdll.Untukaplikasiinihanyadibatasiuntukgambarberformatpng.

FormatDataURIadalahsepertiberikutini

data:[<MIME-type>][;charset=<encoding>][;base64],<data>

Umumnyauntukgambarjenisencodingyangdipakaiadalahbase64.SebagaicontohnyalihatformatgambarpngyangtelahdirubahkeDataURIberikutini

AplikasiWebNode.js

75ToDataURI

data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAFgAAAAfCAMAAABUFvrSAAAABGdBTUEAANjr9RwUqgAAACBjSFJNAABtmAAAc44AAPXqAACD0AAAfHIAAN7iAAAyWgAAI0zujJoVAAADAFBMVEXW1tYxLS6EgYKtrKy7uro/OzxoZWZMSUrk5OR2c3SfnZ7y8vJaV1iRj5DJyMgjHyD///8RERESEhITExMUFBQVFRUWFhYXFxcYGBgZGRkaGhobGxscHBwdHR0eHh4fHx8gICAhISEiIiIjIyMkJCQlJSUmJiYnJycoKCgpKSkqKiorKyssLCwtLS0uLi4vLy8wMDAxMTEyMjIzMzM0NDQ1NTU2NjY3Nzc4ODg5OTk6Ojo7Ozs8PDw9PT0+Pj4/Pz9AQEBBQUFCQkJDQ0NERERFRUVGRkZHR0dISEhJSUlKSkpLS0tMTExNTU1OTk5PT09QUFBRUVFSUlJTU1NUVFRVVVVWVlZXV1dYWFhZWVlaWlpbW1tcXFxdXV1eXl5fX19gYGBhYWFiYmJjY2NkZGRlZWVmZmZnZ2doaGhpaWlqampra2tsbGxtbW1ubm5vb29wcHBxcXFycnJzc3N0dHR1dXV2dnZ3d3d4eHh5eXl6enp7e3t8fHx9fX1+fn5/f3+AgICBgYGCgoKDg4OEhISFhYWGhoaHh4eIiIiJiYmKioqLi4uMjIyNjY2Ojo6Pj4+QkJCRkZGSkpKTk5OUlJSVlZWWlpaXl5eYmJiZmZmampqbm5ucnJydnZ2enp6fn5+goKChoaGioqKjo6OkpKSlpaWmpqanp6eoqKipqamqqqqrq6usrKytra2urq6vr6+wsLCxsbGysrKzs7O0tLS1tbW2tra3t7e4uLi5ubm6urq7u7u8vLy9vb2+vr6/v7/AwMDBwcHCwsLDw8PExMTFxcXGxsbHx8fIyMjJycnKysrLy8vMzMzNzc3Ozs7Pz8/Q0NDR0dHS0tLT09PU1NTV1dXW1tbX19fY2NjZ2dna2trb29vc3Nzd3d3e3t7f39/g4ODh4eHi4uLj4+Pk5OTl5eXm5ubn5+fo6Ojp6enq6urr6+vs7Ozt7e3u7u7v7+/w8PDx8fHy8vLz8/P09PT19fX29vb39/f4+Pj5+fn6+vr7+/v8/Pz9/f3+/v7///8EKbe0AAAACXBIWXMAAAsTAAALEwEAmpwYAAAB/0lEQVRIx62W2W7sIBBE2Rf3UvX/X5sHYyczyb2eGRnJEjZw6C4KTOD7pQAtXHUKH4AthRabldvBIQZmm7GHm8HcOiVTErabweyF6mSJ82bwNjl2Uexe8IiyVxzlVjDnoYEdU9wEFoxVqdut4FFPU9dbwTmdscf8Cjj/6BXOwUzP85vxWLXZXwGbSRAnGQZdJZBOuqhzBJLBz34jLvL42xi/wB5T69JTS66uJEZPKXpLSaWntBR1LdAj5JjlFbCS2BLpC2yJ1C2qxtx6OzwQm9YVqWway4vgolKmq1dxZJVRcx9issmoa0CJW+hnoF7n5eKFRCqzzhASTbMya5rBWyssTX+69nt1pfR2j93W4KWAIWq6AAc/8nN/45diVxpPIO6btQMPBpWGvZjMvRKNtojl96H/9K7A3jcDwM+WhGhmZuYJmGaWgHKAKVblAtwQhWRFBTg8kKS4U890dTlYYfatwbALcInIpAMZoO0MB9jQ3d3/CeaVFG6opEL9ERzqrmz6GDywP09gMrh7BvxTMCfaROcvMElygZM2eQDnZyP/AQ4AkBe4urtvAIO7uxvgEzGXiB6RDTW7u7so4iWYCtQ9TNFlXvCopVNtdDnbvdX6X3BwIcWL7B4j5THifV8Gd/eJGMixPouPd84K3/dEfc5zv1yYyac3IVuZtvfPqi9DYJrPLQNESAAAAABJRU5ErkJggg==

CukuppanjangmemangkalodijadikankeformatDataURI.Cobakopicontohdatauridiatasdanpastekebrowserurldanjanganlupatekanenter.

AplikasiWebNode.js

76ToDataURI

PenggunaanUntukkodesumberselengkapnyabisadilihatdiGithubpadabranchtodatauri-mysqlatauketikperintahberikutpadacommandline.

$gitclone-btodatauri-mysqlhttps://github.com/junwatu/todatauritodatauri-mysql

$cdtodatauri-mysql

$npminstall

Adatigapenggunaanaplikasiiniyaitu

DownloadPNG&SimpanKeMySQL

$node./tdi.js<url_image_png_dari_internet>

Aplikasiiniakanmendownloadfileimagepngdariinternetdanmendukungprotokolhttpataupunhttps.

Demo

$node./tdi.js

JikadijalankantanpaargumenmakahasilnyaadalahkeluarandemoyangtidaklainadalahcontohformatDataURI.

TampilkanDataMySQL

$node./tdi.jsshow

JikaadaargumenshowmakadatadalamMySQLakanditampilkansemua.Hatihatijikaandabanyakmengkonversibanyakdatagambarpng.

AplikasiWebNode.js

77Penggunaan

KonverterPNGKeDataURIMarikitalihatisidarifiletodatauri.js.Padadasarnyafileinimerupakanpustakasederhanayangakanmendownloadimageberformat.pngdiinternetdankemudianmengubahnyamenjadiformatDataURI.

Jadiandabisamenggunakanpustakainisepertihalnyamodulnpmdenganbantuanrequire.

/**

*todatauri.js

*DownloadimageandconvertittoDataURI

*

*WTFPL

*(c)2015,EquanPr.

*/

varfs=require('fs');

varhttp=require('http');

varhttps=require('https');

varurl=require('url');

functionUtil(){

vardefaultImage='https://upload.wikimedia.org/wikipedia/commons/thumb/d/d9/Node.js_logo.svg/320px-Node.js_logo.svg.png';

varimageDest='download.png';

varfile;

return{

toDataURI:function(urlArg,cb){

varimageURL;

urlArg?imageURL=urlArg:imageURL=defaultImage;

if(url.parse(imageURL).protocol==='https:'){

Util().httpsGetImage(imageURL,function(err,data){

err?cb(err,null):cb(null,data);

});

}else{

Util().httpGetImage(imageURL,function(err,data){

err?cb(err,null):cb(null,data);

});

}

},

httpGetImage:function(url,cb){

file=fs.createWriteStream(imageDest);

http.get(url,function(response){

response.pipe(file);

AplikasiWebNode.js

78todatauri.js

console.log('Downloadnode.jsdefaultImagefrom',defaultImage);

console.log('\n');

file.on('finish',function(){

file.close();

Util().imageToDataUri(imageDest,function(err,data){

err?cb(err,null):cb(null,data);

});

});

})

},

httpsGetImage:function(url,cb){

file=fs.createWriteStream(imageDest);

https.get(url,function(response){

response.pipe(file);

console.log('Downloadnode.jsdefaultImagefrom',defaultImage);

console.log('\n');

file.on('finish',function(){

file.close();

Util().imageToDataUri(imageDest,function(err,data){

err?cb(err,null):cb(null,data);

});

});

})

},

imageToDataUri:function(imageName,cb){

//TODO:lookupmimetypehere

varmime='image/png';

varencoding='base64';

varuri='data:'+mime+';'+encoding+',';

fs.readFile(imageName,function(err,buf){

if(err)returncb(err,null);

cb(null,uri+buf.toString(encoding));

})

}

}

}

module.exports=Util();

Fungsiutamapadafiletodatauri.jsyaitufungsiimageToDataUri()danjikadilihatisinyamakasebenarnyasangatsederhanauntukmengubahgambarpngkeencodingbase64yangakandigunakandiDataURI.

AplikasiWebNode.js

79todatauri.js

buf.toString(encoding))

fs.readFile(filename[,options],callback)merupakanfungsiuntukmembacafilesecaraasinkrondanjikaencodingtidakdiberikanmakahasilpembacaanfileakanmengembalikandataberupabuffer.Sehinggauntukmengubahdatabufferinikebase64cukupdenganmemakaimetode.toString(encoding).

AplikasiWebNode.js

80todatauri.js

KoneksiMySQLUntukkoneksikedatabaseMySQLcukupmudahsepertiyangtelahdibahaspadababsebelumnyatentangNodedanDatabaseMySQL.

/**

*todatauri.jsdenganMysql

*

*

*WTFPL

*EquanPr.

*2015

*/

varUtil=require('./todatauri.js');

varmysql=require('mysql');

varconnection=mysql.createConnection({

host:'localhost',

user:'root',

password:''

});

connection.connect(function(err){

if(err){

console.log(err);

}else{

console.log('KoneksiMySQLdenganid'+connection.threadId);

}

});

varcreate_database='CREATEDATABASEIFNOTEXISTSdata_uri';

varcreate_table="CREATETABLEIFNOTEXISTSdata_uri.images(idINTAUTO_INCREMENTPRIMARYKEY,dataTEXT)";

connection.query(create_database,function(err,res){

if(err){

console.log(err);

}else{

console.log('Createdatabasedata_uri[ok]');

connection.query(create_table,function(err,result){

if(err){

console.error(err);

}else{

console.log('Createtableimages[ok]');

main(process);

}

})

}

});

AplikasiWebNode.js

81KoneksiMySQL

functioninsertData(data,connection){

connection.query('INSERTINTOdata_uri.imagesSET?',{data:data},function(err,res){

if(err){

console.log(err);

}else{

console.log(res);

closeConnection();

}

})

};

functionshowData(connection){

connection.query('SELECT*FROMdata_uri.images',function(err,result){

if(err){

console.log(err);

}else{

console.log('\n\nMySQLDatabase\n============================\n');

result.forEach(function(element,index){

console.log('id\u2192',element.id);

console.log('image\u2192',element.data);

});

closeConnection();

}

})

}

functionmain(process){

if(process.argv[2]){

if(process.argv[2].toLowerCase().trim()=='show'){

showData(connection);

}else{

Util.toDataURI(process.argv[2],function(err,data){

if(!err){

insertData(data,connection);

}

})

}

}else{

Util.toDataURI(null,function(err,data){

if(!err){

console.log(data);

closeConnection();

}

});

}

}

functioncloseConnection(){

connection.end(function(err){

if(err){

AplikasiWebNode.js

82KoneksiMySQL

console.log(err);

}

});

}

ParsingargumendilakukanolehprocessyangmerupakanobjectglobaldiNode.js.PerludiingatbahwaJavaScriptmemulaiarraydenganindex0sehinggaargumenyangdiperlukanberadapadaindex2

process.argv[2]

JikaandaberadapadaplatformUNIXatauGNULINUXscriptdiatasbisadirubahuntukselfexecutabledenganmenambahkanscriptberikutpadaline1difiletdi.js

#!/usr/bin/envnode

Kemudianuntukmenjalankannyacukupmudahsepertiberikut

$./tdi.js

Scripttdi.jssebenarnyacukupsederhanadancukupuntukmelakukantugasyangdiinginkan.Mungkinkelihatanagakrumitkarenabanyakcallbackdisanasinitetapikalauandasudahterbiasamemprogramsecaraasinkronpastimudahsekaliuntukmelihatkodediatas.

PenulissarankanuntukkedepannyajikadiinginkanpenulisantanpacallbackbisadipelajaritentangPromisesJavaScriptES6.

AplikasiWebNode.js

83KoneksiMySQL

PersonRESTAPIAplikasiinimerupakancontohsederhanalayananservermelaluiREST(RepresentationalStateTransfer)yaitumekanismeuntukkomunikasidenganservermelaluiprotokolHTTPyangmudahuntukdigunakandaripadamemakaimekanismeprotokollamasepetiCORBA,SOAPataupunRPC.

AplikasiRESTmemakaimetodeHTTPsepertiPOST,PUT,GETdanDELETEuntukmenambah,mengubah,mengambilataupunmenghapusresourceyangadapadaserver.SehinggadalampengembanganaplikasikhususnyadenganmemakaiNode.js,mekanismeRESTsangatmudahuntukdigunakan.

SusunanAPIBerikutsusunanAPIyangakandigunakandalamcontohaplikasiini.ContohAPIinimungkintidakmengikutibestpracticetapipenulisrasasudahcukupuntukmenggambarkanbagaimanamenyusunaplikasiRESTsecarasederhana.

AplikasiWebNode.js

84PersonRESTAPI

CaraKerjaCarakerjadariaplikasiPersonRESTinicukupmudah.HanyasajauntukantarmukadenganpenggunatidakmelaluiantarmukawebsepertihalnyakitamengakseshalamanFacebookmisalnya,karenasecaraumumaplikasiRESTfungsinyalebihkememberikanlayanandatamentahsehinggadeveloperbertanggungjawabpenuhuntukapadata-datatersebutdigunakan,apakahakanditampilkankebrowserwebataudigunakanpadaaplikasimobileandroidatauakandigunakanuntukmengaktifkandeviceelektroniksepertiArduino,RaspberryPidll.

UntukaplikasiPersonRESTini,datadisimpandidatabaseMongoDBmelaluioperasiCRUD(Create,Read,Update,Delete)yangdapatdiaksesmelaluirequestAPIyangtelahdisebutkansebelumnya.

DiagramkerjaaplikasiPersonRESTdigambarkanpadadiagramdibawahini

PengetesanoperasiCRUDuntukaplikasibisadenganmenggunakanbantuanalatCommandLineInterfaceseperticURLatauHTTPieataupuntoolyanglebihramahsepertiPostmandanbisajugaandamembangunantarmukawebdenganmemakaiAPIyangdisediakanolehserverPersonini.ContohpengetesanuntukaplikasiPersonRESTinibisalihatpadasub-babPengetesan.

AplikasiWebNode.js

85CaraKerja

ServerKodesumberdariaplikasiinidapatdidownloaddilinkberikut

https://github.com/junwatu/rest-node-mongoose-mongodb

InstalasiClonekodesumbermelaluigitdaninstaldepedensipaketmelaluinpm

$gitclonehttps://github.com/junwatu/rest-node-mongoose-mongodb.git

$cdrest-node-mongoose-mongodb

$npminstall

PastikandatabaseMongoDBsudahberjalanpadasistemandajikamenggunakanservicesystemdpadalinuxandabisamenjalankannyadenganperintahberikut

$sudoservicemongodstart

KodeUntuklingkunganproduksiadabaiknyauntukmemecahfilekodekebagianyanglebihkecilsupayalebihmudahdalamhalmaintenance.Untukkemudahandankesederhanaanaplikasiinimakakodeutamaditulisdalamsatufile.

app.js

/*

*KoneksiNodejsdenganMongoDBmenggunakanMongoose

*

*AuthorByEquanPr.

*http://equan.me

*

*License:Whateveryouwant!:D

*/

varexpress=require("express"),

app=express(),

mongoose=require('mongoose'),

AplikasiWebNode.js

86Server

path=require('path'),

engines=require('consolidate');

app.configure(function(){

app.use(express.logger());

app.use(function(req,res,next){

res.header('Access-Control-Allow-Origin','*');

res.header('Access-Control-Allow-Methods','GET,PUT,POST,DELETE');

res.header('Access-Control-Allow-Headers','Content-Type')

if('OPTIONS'==req.method){

res.send(200);

}

else{

next();

}

})

app.use(express.bodyParser());

app.use(express.methodOverride());

app.use(express.static(__dirname+'/public'));

app.engine('html',engines.handlebars);

app.set('views',__dirname+'/views');

app.set('viewengine','html');

app.set('PORT',process.env.PORT||5000);

app.set('MONGODB_URI',process.env.MONGOLAB_URI||

process.env.MONGOHQ_URL||'mongodb://localhost/persons');

});

/**

*MongoDBconnection

*/

vardb=mongoose.createConnection(app.get('MONGODB_URI'));

db.on('connected',function(){

console.log('ConnectedtoMongoDB.');

});

db.on('error',function(err){

console.error.bind(console,'ConnectiontoMongoDBerror!.');

});

db.on('close',function(){

console.log('ConnectiontoMongoDBclosed.');

});

//Schema

varPersonsSchema=newmongoose.Schema({

AplikasiWebNode.js

87Server

name:'string',

username:'string',

website:'string',

createdAt:'date',

updatedAt:'date'

}),

Persons=db.model('Persons',PersonsSchema);

//Routes

app.get("/",function(req,res){

res.render('index',{

data:'SillyRESTfulsampleappbuiltwithNode.js,Express,MongooseandMongoDB.'+

'Maybeit\'susefulforbeginners;)'

});

});

//GET/persons

app.get("/persons",function(req,res){

//FindAll

Persons.find(function(err,persons){

if(err)res.json({error:err})

if(persons)

res.json({persons:persons});

})

});

//POST/persons

app.post("/persons",function(req,res){

/**

*Getdatafrompost

*@type{Persons}

*/

varperson=newPersons({

name:req.body.name,

username:req.body.username,

website:req.body.website,

createdAt:newDate(),

updatedAt:newDate()

});

person.save(function(err,person){

if(err){

res.send({error:err});

}else{

console.log('Savedata:'+person);

res.json({message:'saveok'});

}

})

});

//GET/persons/:username

AplikasiWebNode.js

88Server

app.get('/persons/:username',function(req,res){

varparam_username=req.params.username;

Persons.find({username:param_username},function(err,person){

if(err){

res.json({

data:"Errorfindingperson."

});

}else{

res.json({

person:person

});

}

})

});

//PUT/persons/:username

app.put('/persons/:username',function(req,res){

varquery={username:req.params.username},

data_update={

name:req.body.name,

username:req.params.username,

website:req.body.website,

updatedAt:newDate()

}

Persons.update(query,data_update,{multi:false},function(err,numberAffected,rawResponse){

if(err){

res.json({

error:err

})

}else{

res.json({

numberAffected:numberAffected,

rawResponse:rawResponse

});

}

});

});

//DELETE/persons/:username

app.delete('/persons/:username',function(req,res){

varparam_username_del=req.params.username;

Persons.remove({username:param_username_del},function(err){

if(err){res.json({

error:err

})

}else{

res.json({message:"deleteok"});

}

});

AplikasiWebNode.js

89Server

});

app.listen(app.get('PORT'));

console.log("ServerPort:"+app.get('PORT'));

AplikasiWebNode.js

90Server

PengetesanUntukmenggunakanataupengetesanAPIinicaratermudahadalahdenganmemakaiPostmanataujikaandasudahterbiasamemakaitoolterminalseperticURLatauHttpiesilahkansaja.

Demoaplikasiberadapadalinkberikut,

persons-api.herokuapp.com

POST/personsUntukmembuatdataPersonbarumelaluiapi/personscukupdenganmemakairequestPOST.

GET/persons

AplikasiWebNode.js

91Pengetesan

MengambildatadenganmengaksesAPI/personsyangakanmengembalikansemuadatayangtelahtersimpansebelumnya.

PUT/persons/:usernameUpdatedatabisadilakukandenganmudahdenganmemakaiPUT.

AplikasiWebNode.js

92Pengetesan

DELETE/persons/:usernameOperasipenghapusandatahanyabisadilakukansatupersatumelaluikey:username.

AplikasiWebNode.js

93Pengetesan

AplikasiWebNode.js

94Pengetesan

ImageUploader

Aplikasiinisangatsederhana,carakerjanyayaitugambardiuploadkeserverdankemudianditampilkankembalikebrowser.

ServerPadasisiserveraplikasiinimemakaiframeworkExpressJSuntukmenanganirequestHTTPdanpaketformidableuntukmenanganifileyangdiupload.

Catatan:AplikasiinimemakaisedikitfiturES6sepertilet,const,arrowfunctionsehinggaandaperlumenginstallsetidaknyaNode.jsv4.2.1LTS

AplikasiWebNode.js

95ImageUploader

server.post('/upload',(req,res)=>{

letform=newformidable.IncomingForm()

form.uploadDir=path.join(__dirname,'uploads')

form.hash=true

form.multiples=false

form.keepExtensions=true

form.parse(req,(err,fields,files)=>{

if(!err){

console.log(files.file.name)

console.log(files.file.path)

console.log(files.file.type)

}

res.end()

})

})

Kodediatasakanmenanganifileyangakandiuploaddanmenyimpanhasiluploadpadadirektoriuploads.Formidabledapatdenganmudahdikonfigurasi,lihatGithubFormidable.

UploaderPadasisiklienuploderdibangundenganmemakaipustakaDropzoneJSyangmendukungdragndropdanpreviewthumbnail.Pustakainisangatmudahuntukdigunakandandikustomisasi

Dropzone.options.mydropzone={

init:function(){

this.on("complete",function(file){

updateImage()

})

},

maxFileSize:2,

acceptedFiles:'image/*'

}

Konfigurasidiatasmengakibatkanuploaderhanyamenerimafilebertipegambardanukuranfiletidaklebihdari2MBdanyangperludicatatyaituketikafileselesaidiuploadyaitudenganmendengarkaneventcompletemakalistviewgambaryangdibuatdenganKendoUIharusdiupdatedenganmemanggilmetodeupdateImage().

ImageList

AplikasiWebNode.js

96ImageUploader

Kendoakanmengambildatadariserverkemudiansecaraotomatisakanmengupdate#listViewsesuaidenganbanyaknyagambaryangtelahterupload.

varupdateImage=function(){

vardataSource=newkendo.data.DataSource({

transport:{

read:{

url:document.location.href+'service/images',

dataType:'json'

}

},

pageSize:21

})

$('#pager').kendoPager({

dataSource:dataSource

})

$('#listView').kendoListView({

dataSource:dataSource,

template:kendo.template($('#template').html())

})

}

KomponenKendoUIyangdipakaiadalahListViewdanframeworkUIinisepertiframeworkkebanyakanlainnyajugamemakaitemplateuntukmenghasilkanUIsecaradinamik.

<divclass="demo-sectionk-contentwide">

<divid="listView"></div>

<divid="pager"class="k-pager-wrap"></div>

</div>

<scripttype="text/x-kendo-template"id="template">

<divclass="product">

<imgsrc="/#=ImageName#"/>

<h3>#:ImageId#</h3>

</div>

</script>

DatayangakandiambildariserveryaitudatagambarharusmempunyaifieldImageNamedanImageId.

KomponenyangdisediakanolehKendocukuplengkapdanjikaandatertarikdenganKendoUIlebihlanjutsilahkanberkunjungkewebsiteresmiTelerik.

UntukmengambildaftargambaryangtelahdiuploadklienakanmengaksesURLberikut

AplikasiWebNode.js

97ImageUploader

http://localhost:5005/service/images

Serverhanyaakanmemfilterfiledengantipejpgdanpngpadafolderuploads.Filterdilakukandenganmengecektipefilemelaluipaketmimetepatnyamelaluimetodemime.lookup(image).

server.get('/service/images',(req,res)=>{

letimages=[]

fs.readdir(upload_dir,(err,files)=>{

if(!err){

for(letimageIndex=0;imageIndex<files.length;imageIndex++){

letftype=mime.lookup(path.join(upload_dir,files[imageIndex]))

if(filetypes.indexOf(ftype)!==-1){

letdata={}

data.ImageId=imageIndex

data.ImageName=files[imageIndex]

images.push(data)

}

}

res.json(images)

}else{

res.end()

}

})

})

DatayangdikembalikankeklienadalahdataJSONdenganformatsepertiberikut

[{

ImageId:1,

ImageName:'file.jpg'

}]

KodesumberdariaplikasiinibisaandadapatkanpadarepoGithubImageUploader.

AplikasiWebNode.js

98ImageUploader

ECMAScript2015atauES6MeskipunECMAScript2015atauyanglebihdikenalES6sudahdiresmikantetapiimplementasidibrowserdanplatformNode.jsmasihterjadisecaragradual.PadasaatbukuiniditulispadaplatformNode.js4.x(LTS)dan5.xsudahbanyakfitur-fiturES6yangbuilt-indanuntukfituryangbelumdidukungandabisamemakaitoolyangbernamaBabel.

UntukmempelajariES6banyaksekaliresourceonlineyangmenyediakanjadisilahkanandabereksplorasidanmencobakonsep-konsepbaruyangditawarkanolehJavaScript.AndabisamemulaidaribukuonlinegratistentangES6

ExploringJSES6

PadadasarnyaBabelberfungsiuntukmengkompilasiES6(atauES7,8)menjadiES5sehinggabisadijalankanpadabrowseratauplatformNode.jsyangbelummendukungES6.SalahsatupertanyaanterbesarkalauandamemakaiBabeladalahbagaimanamengkompilasihanyabeberapafiturES6sajajikalaubrowserataupunNode.jsyangakankitapakaisecaranativesudahmendukungsebagianataubeberapafiturES6?

BabelonTheFly

SejakdireleaseBabel6,toolinimendukungkompilasiES6berdasarkanpluginartinyaandabisamemilihfiturmanayangakandikompilasikeES5jikamisalnyapadaplatformNode.jssudahmendukungbanyakfiturES6.

Kalauandapernahmemakaibabel-nodemakesekarangdigantidenganpaketbabel-cli

$npminstall-gbabel-cli

Apakegunaannya?babel-clisangatbergunauntukmengkompilasiES6secaraontheflymisalnyabegini

lib/module.js

'usestrict'

exportfunctiontest(){

console.log('test')

}

main.js

AplikasiWebNode.js

99MemakaiES6

'usestrict'

import{test}from'./lib/module'

test()

Makauntukmengeksekusifilemain.jsbisamelaluibabel-node

$babel-nodemain.js

JikaandamemakaiprojectdenganES6selainbabel-climakapaketberikutjugaperludiinstall

$npminstall--save-devbabelbabel-corebabel-loader

danjugasettingfile.babelrc(meskipunsebenarnyaadabeberapaalternatiflaindimanaharusmenuliskansettingbabeltapicarainilebihUNIX,tergantungseleramasingmasing)

.babelrc

{

"plugins":["transform-es2015-modules-commonjs"]

}

Bisaandalihatbahwapluginsyangakankitagunakanadalahtransform-es2015-modules-commonjsjadiharusdiinstalljuga

$npminstall--save-devbabel-plugin-transform-es2015-modules-commonjs

Lalubagaimanakalaukitamenginginkansemuapluginkitapakai?jawabannyaadalahdenganmemakaipresets

$npminstall--save-devbabel-preset-es2015

dan.babelrcperluandarubahmenjadisepertidibawahini

{

"presets":["es2015"]

}

CatatanPenjelasandiatasberlakuuntukJavaScriptyangdigunakanpadasisiserveruntukclientatauJavaScriptyangberjalanpadabrowserandabisamemakaiwebpackbersamadenganbabel.

AplikasiWebNode.js

100MemakaiES6

AplikasiWebNode.js

101MemakaiES6

TentangPengarangEquanPr.adalahdeveloperNodeJSdanpeminumkopikelasberat.SelalusibukdenganyangberbauJavaScriptketikadidepankomputer,penggilafilm&musikmetaldankadang-kadangnge-twitdi@junwatuataunge-Github.

AplikasiWebNode.js

102TentangPengarang