JavaScript na serveru: nástroje a dokumentace

node.js logo

Dnešní díl bude věnován několika různým oblastem. Podíváme se na nástroje, které zpříjemní práci v Node.js, na profilování, debugování, logování či buildování a také na dokumentaci projektu a coding standards.

Seriál: Node.js - s JavaScriptem na serveru (13 dílů)

  1. JavaScript na serveru: Začínáme s Node.js 23.11.2010
  2. JavaScript na serveru: Patří budoucnost Node.js? 21.9.2012
  3. JavaScript na serveru: Architektura a první Hello World 5.10.2012
  4. JavaScript na serveru: moduly a npm 12.10.2012
  5. JavaScript na serveru: začínáme programovat e-shop 19.10.2012
  6. JavaScript na serveru: MongoDB, Mongoose a AngularJS 26.10.2012
  7. JavaScript na serveru: Testování a kontinuální integrace 2.11.2012
  8. JavaScript na serveru: REST API 9.11.2012
  9. JavaScript na serveru: implementace REST API 16.11.2012
  10. JavaScript na serveru: nástroje a dokumentace 23.11.2012
  11. Začínáme s AngularJS 30.11.2012
  12. AngularJS direktivy a testování 7.12.2012
  13. JavaScript na serveru: CoffeeScript a šablonovací systémy 14.12.2012

Restartování aplikace po editaci souboru

Pokud se změní zdrojové kódy a chceme vidět, jak se změny projevily v aplikaci, je potřeba restartovat aplikaci. Abychom tento krok nemuseli neustále opakovat, může se nám hodit modul supervisor, který aplikaci restartuje pokaždé, když změníme nějaký soubor. 

Jestliže při psaní aplikace píšeme i testy, supervisor pravděpodobně nebudeme využívat tak často. V ideálním případě nespouštíme ručně ani testy, ty se spouští automaticky při každé změně souboru a výstup z testování je dostupný přímo v editoru. Díky tomu může  programátor zůstat po celou dobu psaní kódu uvnitř editoru a nemusí třeba i několik dní aplikaci vůbec v prohlížeči zobrazit. Jak toho docílit si ukážeme v jednom z následujících dílů.

Řízení asynchronního zpracování

Někdy se může stát, že potřebujeme zpracovat několik různých asynchronních operací. U těch obvykle nevíme, kdy a v jakém pořadí budou dokončeny. Může to vést k tomu, že vzniká jakási pyramida callbacků, která pak ovšem dělá program méně přehledným.

Abychom se tomu vyhnuli, existují knihovny pro kontrolu běhu asynchronních operací. Jednou z nich, pravděpodobně nejpoužívanější, je modul async. Ten používáme i u integračních testů v naší aplikaci (pull request níže uvedeného kódu zaslal Jiří Prokop). Slouží nám pro vyčištění databáze a naplnění vzorových dat před spuštěním testů.

Zde máme nejprve funkci save(), která vloží novou stránku do databáze:

var async = require(‘async’);
function save(doc, cb) {
  var page = new Page();
  for (var field in doc) {
    page[field] = doc[field];
  }
  page.save(cb);
}

dále vzorová testovací data:

var data = [
  {title: 'Stranka 1', url: 'stranka-1', content: 'lorem ipsum'},
  {title: 'Stranka 2', url: 'stranka-2', content: 'lorem ipsum 2'},
  {title: 'Stranka 3', url: 'stranka-3', content: 'lorem ipsum 3'}
];

a nakonec událost beforeEach(), která nastane před každým testem:

beforeEach(function(done) {
  Page.remove({}, function(err){
    if (err) return done(err);
    async.forEach(data, save, done);
  });
});

Balíček async obsahuje několik metod (jejich přehled je v dokumentaci). Jednou z nich je i metoda  forEach(), která přijímá tři parametry: pole, iterátor a callback. Metoda projde všechny prvky pole a na každém z nich zavolá iterátor, který něco zpracuje (v našem případě vložení jednoho dokumentu do databáze). Jakmile budou vráceny výsledky po zpracování všech prvků pole, bude zavolán callback.

Pokud bychom forEach() nepoužili, zpracování úkolu by vypadalo třeba takto:

beforeEach(function(done) {
  Page.remove({}, function(err){
    if (err) return done(err);
    save(data[0], function(err){
      if (err) return done(err);
      save(data[1], function(err){
        if (err) return done(err);
        save(data[2], done);
      });
    });
  });
});

Doporučuji si podrobněji projít možnosti, které async nabízí, může to významně ušetřit práci.

Profilování

Pro profilování je nesmírně užitečný modul nodetime. Po jeho instalaci je potřeba jako první příkaz zavolat 

require('nodetime').profile()

Po spuštění aplikace se vygeneruje adresa nodetime.com/xxx, kde xxx je unikátní hash pro relaci. Pokud adresu zkopírujete do prohlížeče, dostanete se do webového rozhraní, kde máte k dispozici celou řadu statistik. Každý další požadavek na aplikaci pošle informace o zpracování do webového rozhraní a vy si můžete podrobně prohlédnout, jak celé zpracování proběhlo.

V níže uvedené ukázce se můžeme podívat na podrobné zpracování dotazu na MongoDB z modulu Mongoose. Tímto způsobem je možné snadno odchytit dlouhotrvající operace, podívat se přesně kudy zpracování požadavku šlo a jak náročné na paměť zpracování bylo.

Debugování

Pro debugování lze využít Node Inspector. Nástroj byl podrobně představen v prvním díle seriálu. K dispozici je screencast.

Jednoduchý debugger je také dodáván přímo s V8 a je dostupný i v Node.js. Můžeme ho používat, pokud spustíme soubor server.js s příkazem  debug:

node debug server.js

Kompletní přehled příkazů a možností debugeru je dostupný v dokumentaci.

K dispozici je také modul debug, který se v Node.js používá poměrně často. Používá ho i Express a Connect, jeho výstup lze získat pomocí proměnné prostředí DEBUG=„*“. Po spuštění program začne vypisovat různé zprávy do konzole podle masky v proměnné DEBUG. Pokud si občas něco vypíšete do konzole a pak pracně hledáte, který řádek že to vlastně musíte smazat, možná je čas začít používat modul debug.

Logování

Pro logování HTTP požadavků se může hodit middleware logger, který je dodáván v rámci modulu Connect (a je tedy i součástí Expressu). Ve výchozí podobě jsou všechny požadavky odesílány do konzole.

Middleware přijímá jako první řetězec formát, v jakém chceme informace o požadavcích logovat. K dispozici je několik zkratek nastavení, mimo jiné i “dev” pro prostředí, které se hodí při vývoji.

Middleware aktivujeme jako všechny ostatní v souboru config.js takto:

app.use(express.logger('dev'));

Nyní můžeme spustit aplikaci a každý HTTP požadavek bude nyní logován. Výstup v konzoli pak může vypadat třeba takto:

Pro sofistikovanější řešení logování Node.js aplikací se nejčastěji používá balíček winston. Za zmínku také stojí projekt log.io pro real-time přenášení obsahu logu do prohlížeče.

Buildování

Pro sestavení projektu (operace, které předcházejí odesílání projektu do produkce) se nejčastěji používá modul Grunt. V základu obsahuje podporu pro nejčastější operace, např.:

  • sloučení souborů do jednoho (aby uživatel místo x javascriptových či CSS souborů stahoval třeba jen jeden),
  • validace coding standards,
  • minifikaci souborů pomocí UglifyJS,
  • spouštění testů.

Jak už to tak v Node.js bývá, modul je udělán tak, aby uživatelé mohli psát vlastní rozšíření, takže na úvodní stránce můžeme nalézt několik set dalších rozšíření, např. pro kompilaci CoffeeScriptu, kontrolu syntaxe CoffeScriptu, generování dokumentace nebo třeba vygenerování počáteční struktury projektu v AngularJS.

Balíček grunt pro svůj běh potřebuje soubor, který obsahuje konfigurační nastavení. Např. pro použití nástroje jslint, který kontroluje coding standards, může nastavení vypadat takto:

module.exports = function (grunt) {
  grunt.initConfig({
    lint: {
      all: ['app/**/*.js', 'lib/**/*.js', 'test/**/*.js', '*.js']
    },
    jshint: {
      options: {
        node: true,
        camelcase: true
      }
    }
  });
  grunt.registerTask('default', 'lint');
};

Zde říkáme, že kontrolu coding standards chceme provádět na všech souborech s koncovkou .js v adresářích app, lib, test a v rootu projektu. V části jshint říkáme, jaké volby se mají pro kontrolu použít, v tomto případě nás zajímá prostředí Node.js a chceme dodržovat zápis “camelCase”. Příkazů pro jshint je celá řada, takže lze přesně říci, jak mají zdrojáky projektu vypadat.

Příkaz grunt.registerTask() registruje kontrolu coding standards jako výchozí příkaz, takže stačí zadat jen příkaz grunt a hned se dozvíme, zda projekt odpovídá standardům.

Můžete si sami vyzkoušet, že pokud proměnnou pojmenujete třeba jako “snake_case”, jslint oznámí chybu a bude požadovat opravu.

Ošetření coding standards by mělo probíhat v rámci kontinuální integrace automaticky. 

Coding standards

V JavaScriptu na serveru platí stejné konvence pro psaní kódu jako v klasickém JavaScriptu. Z toho jsou odvozeny tři základní styly (ukážeme si dále), které se odlišují v mírných detailech. Nicméně pro všechny platí následující:

  • používá se notace camel case (tzv. velbloudí notace),
  • názvy tříd začínají velkým písmenem,
  • konstanty mají všechna písmena velká a pro oddělení slov se použije podtržítko,
  • řádek má mít maximálně 80 znaků,
  • pro odsazení se používají dvě mezery,
  • preferují se jednoduché uvozovky před dvojitými, 
  • pro dokumentaci se používá JsDoc.

Nejčastěji se v Node.js používá styl, který zavedl jeho autor Ryan Dahl a které popsal Felix Geisendörfer v jeho Style Guide.

Druhý styl, mírně radikálnější (např. v ukončování řádků středníkem), preferuje současný hlavní vývojář Node.js a autor npm, Isaac Z. Schlueter. I v tomto případě jsou ukázky dostupné v npm coding style.

Třetí styl zavedl TJ Holowaychuk a jedná se o mix obou předchozích stylů. Mírné rozdíly jsou v deklaraci použitých modulů a mezer za klíčovým slovem function a následujícími závorkami.

Mimochodem, TJ Holowaychuk je pojem, který je dobré se naučit a zapamatovat. Je to zdaleka nejproduktivnější autor balíčků v Node.js. Za 4 roky existence Node.js jich publikoval neskutečných 231 a je mimochodem autorem nejpoužívanějších frameworku Connect i Express (používá ho i LinkedIn), testovacích nástrojů Mocha, Supertest, Should.js, jednoho ze tří nejpopulárnějších CSS preprocesorů Stylus, šablonovacích systému Jade či Ejs a celé řady dalších výborných modulů. Kromě toho je tvůrcem mnoha dalších projektů v jiných jazycích (populární je třeba git-extras), v Pythonu, Ruby, C, C++ a dokonce i v PHP, zabývá se grafikou, píše knihy a publikuje screencasty. Pro dokreslení jeho produktivity si je potřeba ještě uvědomit, že pro každý projekt udržuje dokumentaci a stará se o opravu a rozbor reportovaných chyb.

Ještě by bylo dobré zmínit konvence pro pojmenování souborů a modulů. Zde platí, že se víceslovné názvy souborů i modulů oddělují vždy pomlčkou, tedy preferovaná varianta je “contact-form.js” a nikoliv třeba “contactForm.js” či “contact_form.js”. Výjimkou jsou názvy modulů, které jsou dostupné přímo v jádře Node.js, ty používají pro oddělení podtržítko (např. child_process). Je to z toho důvodu, že se názvy mapují na proměnné v jazyce C, který pomlčku pro název proměnné nepovoluje.

Dokumentace

Pro vygenerování dokumentace z kódu se často používá Docco nebo dox (autorem je TJ) s šablonou dox-foundation, která vygeneruje dokumentaci do CSS frameworku Foundation. Vygenerovat dokumentaci z našeho projektu je možné (po instalaci dox-foundation s příznakem -g) takto:

dox-foundation --source ./ --target docs --ignore node_modules,docs,public,test --title "Zdrojak shop"

Co dále

Následující dva díly budou věnovány frameworku AngularJS a nástroji Testacular, který slouží pro testování klientského JavaScriptu. Tím uzavřeme jednu velkou část seriálu, během které jsme vytvářeli vývojové prostředí a vrhneme se pořádně na programování vzorové aplikace.

Na tvorbě tohoto článku se svými připomínkami podílel také Pavel Lang (skolajs.cz). Díky!

Jakub pracoval na několika zajímavých projektech, za nejvýznamnější považuje vytvoření e-commerce řešení Shopio.cz. Poslední rok se plně věnuje Node.js, frameworku AngularJS a NoSQL databázím.

Zatím nebyl přidán žádný komentář, buďte první!

Přidat komentář
Zdroj: http://www.zdrojak.cz/?p=3743