Egy blog születése Α → Ω

írta: Jim-Y, 10 éve

Szerettem volna egy blogot csinálni magamnak, eddig az ingyenes megoldásokat használtam, mint blogspot, vagy wordpress, de igazából egyikkel sem voltam megelégedve, illetve szerettem volna gyakorolni valamin. Igy elkezdtem csinálni magamnak egy blogot.

A blognak minden részét magam tervezem implementálni, olyan mélységekben, amennyire csak lehet.

Előkészületek

Először is ki kellett találni a használandó technológiákat. Az ember egy raklap technológia közül választhat, de tényleg. Ha az ember valaki olyant kérdez meg, aki nem követi a trendeket, akkor jó eséllyel azt a tanácsot kapja, hogy PHP + HTML + (Apache, nGinx, IIS stb..). És ez nem vicc, prog.hu-n volt egy hasonló kérdés, ott az emberek 95%-a ezt ajánlotta, mert a PHP jelenleg uralkodó a neten. Ellenben a népszerűsége zuhan, és már vannak jó alternatvák. Én valami újabb technológiát szerettem volna használni, ami sokkal "maibb".

Kliens az egyértelműen JavaScript, de azon belül ezer lehetőség van választani MVC framework-ök, és client-library-k közül. Itt is valami kurrens-et akartam választani.

Végül úgy döntöttem, hogy a backend szerepét a node, a kliens szerepét a Dart fogja betölteni.

Ami kelleni fog: node, npm, yeoman

----- backend -----

A backenddel kezdtem a fejlesztést. Az elképzelés az, hogy a bloghoz szükséges adatok (bejegyzések, kommentek?, felhasználók?) kiszolgálását web szervizek fogják biztositani, amit nodejs-ben valósitok meg. Mivel az egész arra megy ki, hogy gyakoroljak, ezért minden jóval el akarom látni a backendet, és próbálok minél minőségibb kódbázist létrehozni. Emiatt lassan is haladok, hiszen a legtöbb dolog új nekem, mindennek most nézek utána.

Kezdjük el:

Scaffolding: az egész backendnek úgy álltam neki, hogy először is generáltam, egy nálam okosabb/tapasztaltabb emberek által összeállitott sémát Yeoman segtségével, majd ezt tanulmányozva magamtól is összeraktam egy hasonlót, amiben csak azt használom amire szükségem van.

megj: ez csak a példa projekt amit analizáltam

npm install -g generator-node

Csináljunk egy mappát a példa projektnek.

mkdir sampleServer
cd sampleServer
yo node

Ez a parancs egy ilyen projekt struktúrát hoz létre:

.
├── cli.js
├── example
│   └── sampleserver_example.js
├── Gruntfile.js
├── lib
│   └── sampleserver.js
├── node_modules
│   ├── grunt
│   ├── grunt-contrib-jshint
│   ├── grunt-contrib-nodeunit
│   ├── grunt-contrib-watch
│   ├── jshint-stylish
│   ├── load-grunt-tasks
│   └── time-grunt
├── package.json
├── README.md
└── test
└── sampleserver_test.js

Ez lesz a backend alapja.
package.json: Ez az npm init eredményeként létrejövő konfigurációs fájl. Bővebben
Itt azt érdemes megjegyezni, hogy a projekt entry pontja konfigurálva van a fájlban, valamint itt soroljuk fel a projektünk dependenciáit. Ha később bővteni akarjuk a projektet újabb modulok bevonásával, akkor pl:
npm install mocha --save-dev
parancs hatására bővülni fog a devDependencies egy új rekorddal.

Gruntfile.js: a projektünk build eszköze. Bővebben Ebben a fájlban tudunk taskokat definiálni. Olyan ez mint ant esetén a build.xml, csak ebben az esetben ez egy JavaScript fájl. Ebbe most nem fogok bővebben belemenni, majd ha elkészült a blog, akkor ott rok egy, vagy több blog posztot a blog születéséről. Ott ezt is kifejtem. Jelen esetben csak meg kellett értenem a grunt alapvető működését, hogy el tudjam kezdeni vele a munkát. A Gruntfile-ban definiálhatjuk a taskokat, azokat a repetitiv folyamatokat amiket automatizálni szeretnénk. A generátor készitői lintelést és unit tesztelést definiáltak nekünk. Kiindulásnak ez jó lesz.

Ahhoz, hogy kipróbáljuk, hogy hogyan működik a grunt, és, hogy hogyan tudjuk lefuttatni a taskokat, két lehetőségünk van.
Az egyik, hogy lefuttatjuk a grunt parancsot, vagy ami ezzel ekvivalens működést eredményez:
npm run test
Ahol a "test" parancs a package.json fájlban lett definiálva, a "scripts" mezőben. Ez sem csinál mást, csak kiadja a grunt parancsot.

Az eredmény ez lesz:

> sampleserver@0.0.0 test /home/jim/tmp/sampleServer
> grunt

Running "jshint:gruntfile" (jshint) task

✔ No problems


Running "jshint:lib" (jshint) task

✔ No problems


Running "jshint:test" (jshint) task

✔ No problems


Running "nodeunit:files" (nodeunit) task
Testing sampleserver_test.js.OK
>> 1 assertions passed (4ms)

Done, without errors.


Execution Time (2014-07-06 09:43:36 UTC)
loading tasks 389ms ▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇ 88%
jshint:gruntfile 31ms ▇▇▇▇ 7%
jshint:lib 6ms ▇ 1%
jshint:test 8ms ▇ 2%
nodeunit:files 8ms ▇ 2%
Total 443ms

Mi történt?

hinteltük a a lib mappában lévő *.js fájlokat, a test mappában lévő *_test.js fájlokat, valamint magát a Gruntfile.js-t is. Majd unit teszteltük a test mappában lévő test fájlokat.

Ennyit az információszerzésről, ebből már ki tudtam indulni, de például én nem a nodeunit tesztelőt akartam használni, hanem valami mást. Például jasmine, vagy ami végül bevált, a mocha. Valamint dokumentációt is akartam készteni. Mindenképp olyanra akartam megcsinálni a projektet, hogy az könnyen karbantartható legyen, és minél több olyan eszközt használjon, ami megkönnyti a munkát. Ezért van a grunt, ezért van a dokumentáció, ezért a tesztelések.

woowie

Létrehoztam a blogot tartalmazó projektstruktúrát ami hasonló az előzőhöz, csak kibővtettem:

.
├── bin
├── config
├── doc
├── Gruntfile.js
├── lib
├── package.json
├── README.md
├── test
└── woowieServer.js

Majd a szükséges dependenciákat (hint: ezek bekerülnek automatikusan a package.json-ba)

npm install grunt --save-dev
npm install grunt-jsdoc grunt-contrib-nodeunit grunt-contrib-jshint grunt-contrib-watch load-grunt-tasks time-grunt jshint-stylish grunt-mocha-test should --save-dev

grunt: már lertam, hogy ez mi :)
grunt-jsdoc: ezzel fogunk jsdoc-ot generálni. Bővebben
grunt-contrib-nodeunit: unit tesztekhez. Az én projektemben nem biztos, hogy szerepet kap, de azért nem árt ha van lehetőségünk ilyen teszteket is rni.
grunt-contrib-jshint: jshint
grunt-contrib-watch: figyeli a módostásokat egyes fájlokban, és ha módostás történt, akkor automatikus (újra)futtatja a taskokat.
load-grunt-tasks: utility
time-grunt: utility
grunt-mocha-test: Ezt fogom használni a REST szervizek tesztelésére, valamint az adatbáziskapcsolat tesztelésére is.
should: a tesztekben használom, pl response.should.have.property('statusCode', 200);

REST

Az adatbázis mongoDB, az adatbázis-kliens mongoose, a REST szervizekhez restify-t használtam.

Igy egy REST szerviz definiálása:
woowieServer.js:
function getArticles(req, res, next) {
articleProvider.findAll(req, res, next);
}
server.get('/get/articles', getArticles);

lib/ArticleProvider.js:
ArticleProvider.prototype.findAll = function(req, res, next) {
var articles = this.Article,
promise = articles.find().exec();
promise.addBack(function( err, articles ) {
if( err ) {
console.error("Could not execute findAll query");
}
res.send(articles);
return next();
});
};

A fenti /get/articles szerviz-t implementálás után tesztelni szeretném:

test/woowie_test_mocha.js:
describe('### service: /get/articles', function() {
it('should be up, and running (200 OK)', function( done ) {
client.get('/get/articles', function( err, req, res, obj ) {
assert.ifError(err);
res.should.have.property('statusCode', 200);
done();
});
});

it('should return at least 1 (initial) result', function( done ) {
client.get('/get/articles', function( err, req, res, obj ) {
assert.ifError(err);
obj.should.be.an.instanceOf(Array);
obj.length.should.be.above(0);
done();
});
});
});

Ahol a client, egy tesztelési céllal létrehozott restify JsonClient.

Teszteljük a szervizt: grunt test

Running "mochaTest:test" (mochaTest) task


Testing Database ...
testing basic commands ...
✓ should be able to remove documents
✓ should be able to save new documents (92ms)
✓ should be able to save another one
✓ should be able to create new documents
✓ should be able to count all documents
✓ document count should be equal to three
✓ should be able to remove one document

Testing REST services ...
### service: /get/articles
Woowie Blog Backend listening at http://0.0.0.0:58000
Database Client connected
✓ should be up, and running (200 OK)
✓ should return at least 1 (initial) result
### service: /count/articles
✓ should be up, and running (200 OK)
✓ should return the number of articles
✓ should return an object
✓ should return a >=0 value


13 passing (355ms)


Done, without errors.

Teszteljük élesben:
npm run deploy kimenet
curl http://localhost:58000/get/articles

JSDOC

A generált JSDoc: kép

Összegzés

- van egy nodejs-ben irt http szerverem, ami REST szervizeket definiál, és várja a bejövő kéréseket
- ha jön egy kérés, pl /get/articles, akkor azt delegálja a megfelelő *Providernek, ebben az esetben az articleProvider-nek.
- az articleProvider kapcsolatot létest a mongoDB adatbázissal, és mongoose kliens segtségével lekéri a szükséges adatokat, majd visszaküldi a response-t.
- van egy build tool, grunt, amivel hintelem a fájlokat, jsdoc-ot generálok, és teszteket futtatok
- vegyesen unit teszteket -> nodeunit, rest-teszteket -> mocha, valamint az datbázis alapvető működését is tesztelem -> mocha

----- frontend -----

Működik a backend,irjunk hozzá frontend-et. Kliens oldali tool-nak a Dart-ot fogom használni.
Aki esetleg nem hallott még a Dart projektről, annak álljon itt egy rövidebb/hosszabb ismertető. Ha hallottál már róla, akkor ezt a bekezdést ugord át.

dartlang:

A Dart projekt egy Google által 2011-ben indtott projekt, aminek célja egy új webes programozási platform elkészitése. Az első production-ready relese 2013 novemberében jelent meg, jelenleg az 1.5-ös verziónál tartanak, igy elmondható, hogy elég új dologról van szó. Sokan úgy hirdetik, vagy úgy tudják a Dart-ról, hogy a JavaScriptet hivatott leváltani webes környezetben, de ez nem igaz. Mint ahogy az sem, hogy egy sima compile-to-js toolról lenne szó mint pl a CoffeScript. A Dart ennél sokkal több, és sokkal több is szeretne lenni. Először is rendelkezik egy saját virtuális géppel, ami Dart forrást tud interpretálni. Ez a DartVM, ugye itt már meg is bukott a szimplán c-2-js rumor. Rendelkezik egy dart2js eszközzel ami a Dart forrásból képes effektv JavaScriptet generálni, igy lesz multiplatform a cucc.

Akkor mi is a Dart pontosan?

A dart projekt egy olyan programozási környezet ami rendelkezik egy saját programozási nyelvvel (dartlang) egy saját virtuális géppel (DartVM) egy saját fejlesztőkörnyezettel (Dart Editor) és saját package managerrel (PUB).

A nyelv dinamikusan tipusos, klasszikus öröklődés van benne, nyelvi szinten támogatottak a promisok (Future), kliens és szerver oldalon is használható, és szintaktikában hasonlit a Java-ra.

Bevezetőnek elég ennyi, majd lehet irok a nyelvről egy hosszabb cikket.

Előkészületek

Ami kell: dart (DartEditor + SDK)

Kliens oldali könyvtárak ide nem kellenek, igen rád gondolok jQuery, mivel a nyelv alapból hasonló szintaktikával, és html API-val rendelkezik.

Terv: reszponziv design (Adam Kaplan grid alapján), aszinkron kommunikáció a backenddel (http req + Futures), markdown bejegyzésmegjelentő, AngularDart használata, saját web-komponens a bejegyzéseknek.

A kliens még bőven nincs kész, de már elkezdtem, A következő részben bemutatom a kliens oldali kódot ...

Folytatás ...