jPortal.pl, to serwis dla miłośników JavaScript. Znajdziesz tutaj ciekawe porady oraz tutoriale, czyli porady "za rączkę", aby zrobić fajne efekty. Dowiesz się też jak tworzyć dobrej jakości kod.
Skoro J ("dżej" - ten gość po lewej) umie, to Ty też podołasz temu wyzwaniu :).

Prosty blog w node.js

Opublikowany: 27.05.2011 23:17:13 | Komentarzy 2

Dzisiaj pokażę Wam co udało się nam zrobić na workshopie z node.js. Może to nie jest coś wielkiego i niesamowitego czy nawet rocket science, ale pokazuje dobrze jak działa i fukcjonuje node wraz z innymi bibliotekami.

Do stworzenia prostego bloga będziemy potrzebować:

  • systemu szablonów w JS - na workshopie wybraliśmy EJS (Embedded JavaScript Templates).
  • Routing aby usłużyć adresy URL i przypisać do nich poszczególne zdarzenia - do tego użyjemy expressJS (framework do node.js, który ułatwia korzystanie z niego oraz rozszerza możliwości).
  • Obsługę plików - musimy w jakiś sposób wczytać pliki z szablonami.
  • Ponadto będziemy sprawdzać czy dany wpis istnieje i w zależności od tego będzie pokazywać odpowiednią stronę.

Co do bazy danych, posłużymy się małą sztuczką. Nie będziemy podłączać się do np. do mySQL tylko zastąpimy ją prostą, odpowiednio przygotowaną tablicą w formie zmiennej. O kontrolerach baz danych w node.js będzie później.

Inicjalizacja bibliotek

Na początek tworzymy komponenty, które będą nam potrzebne do działania całej "aplikacji".

var express = require('express'), // dołączamy expressJS
   app = express.createServer(), // tworzymy serwer
   ejs = require('ejs'), // dołączamy system szablonów
   fs = require('fs'), // dołączamy filestream - do odczytu plików
   // otwieramy pliki z szablonami
   tpl_main = fs.readFileSync(__dirname + '/views/index.ejs', 'utf8'),
   tpl_entry = fs.readFileSync(__dirname + '/views/entry.ejs', 'utf8'),
   tpl_error = fs.readFileSync(__dirname + '/views/error.ejs', 'utf8');

Tutaj na szczególną uwagę zasługują dwie rzeczy:

  1. __dirname, to zmienna globalna która jako wartość przyjmuje ściężkę do katalogu w których uruchamiamy skrypt.
  2. metoda readFileSync wczytuje zawartość pliku.

Tworzymy prostą "bazę danych" :)

Filozofi tutaj nie ma:

var entries = [
   {
      'title': 'Wpis nr 1',
      'lead' : 'Wprowadzenie do 1',
      'full' : 'Pełny wpis do 1'
   },

   {
      'title': 'Wpis nr 2',
      'lead' : 'Zajawka wpisu nr 2',
      'full' : 'Pełna treść dla 2 oraz trochę HTML: 

paragraf

i
  • jakaś
  • lists ;)
'
}, { 'title': 'Wpis nr 3', 'lead' : 'this is my lead post no. 3', 'full' : 'this is my full post no. 3 and some stuffffff' } ];

Oczywiście zdaję sobie sprawę, że nie ma w tej bazie pola "id", po którym może być indentyfikowany wpis. Na szczęście jest prosty przykład.

Routing w expressJS

Dalej zaczyna się już to co tygryski lubią najbardziej. Poniższe instrukcje będą opisywały obsługę tak zwanego routingu. Framework expressJS udostępnia bardzo przydatne API do obsługi routingu. Definiujemy URL i do niego możemy przypisać konkretną funkcję. Na przykład gdy chcemy pokazać szczegóły produktu /produkt/783 to możemy to zrobić w następujący sposób:

app.get('/produkt/:id', function(req, res){
   res.send('produkt o numerze: ' + req.params.id);
});

Tak na prawdę jest to wyrażenie regularne. Dla powyższego przykładu chcemy zawęzić zakres parametru id do liczb. Możemy to zrobić w następujący sposób:

app.get('/produkt/:id(\\d+)', function(req, res){
   res.send('produkt o numerze: ' + req.params.id);
});

Skoro już wiemy jak obsługiwać adresy możemy napisać routing dla naszego bloga.

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

   var d = ejs.render( tpl_main, {
      locals: { posts : entries }
   });

   res.send(d);

});

// blog entry
app.get('/blog/:id(\\d+)', function(req, res, next) {

   if( entries[req.params.id] ) {

      var d = ejs.render( tpl_entry, {
         locals : { post : entries[req.params.id] }
      });

      res.send(d);

   } else {

      next();

   }

});

// error
app.get('/blog/:id(\\d+)', function(req, res) {

   var d = ejs.render( tpl_error, {} );
   res.send(d);

});

req, res, next

  • req (request) - czyli to co my dostajemy. Może to być na przykłąd informacja o używanej przez użytkownika przeglądarce req.headers['user-agent'].
  • res (response) - czyli informacje, które będziemy wysyłać jako wiadomość z serwera np. zwykły tekst: res.send('hello world').
  • next - jest to metoda (callback), która przeskakuje do następnego routingu, jeżeli nie udało się dopasować do "wzoru". W naszym przypadku przeskakujemy do następnego "wzoru" jeżeli wpis o danym ID nie istnieje w "bazie". Równie dobrze można byłoby zrobić przekierowanie np. na adres /404 i stworzyć dodatkowy routing. Przekierowanie można zrobić tak: res.redirect('/404', 301); (tworzymy natychmiastowe przekierowanie 301).

Szablony

W naszym blogu szablony znajdują się w katalogu /views.

Teraz aby skorzystać z danego szablonu należy jeszcze przypisać zmienne do niego. W naszych plikach *.ejs znajduje się mniej więcej taki kod:

<% if (user) { %>
    Witaj <%= user.name %>
<% } %>

Czyli jeżeli zmienna user istnieje, to wyświetlamy imię użytkownika. Szablon renderuje się w następujący sposób:

ejs.render(szablon, {
   locals: {
      user:
         { name: 'shpyo' }
   }
});

Na koniec aplikacji ustawiamy port, na którym będziemy nasłuchiwać.

app.listen('3000');

Uruchamiamy naszą aplikację poleceniem node blog.js i w przeglądarce wpisujemy adres http://localhost:3000 dostajemy listę wpisów. Po kliknięciu w tytuł wpisu np. http://localhost:3000/blog/1 dostaniemy całość. Jeżeli wpis nie będzie istniał w naszej, to dostaniemy komunikat o błędzie.

Źródło jest tutaj.

Tagi: ejs temaplates embeddedJS expressJS node.js tutorial node.js

Komentarze

Gavatar wszerad
01.06.2011, wszerad napisał/-a: Cienkie te workshopy, node.js ma na tyle łatwe API, że powinno się uczyć ludzi jak pisać moduły bo do korzystania z gotowych wystarczą podstawy JS. Trochę głupio też bawić się w szablony ala PHP, bo wtedy to żadna różnica PHP czy JS(trzeba korzystać z płynnego przejścia danych z serwera do klienta JSON i minimalizować komunikację jedynie do przesyłania czystych danych - np. sama treść wpisu na blogu bo to czysta oszczędność transferu i wydajności). Napisanie własnego modułu(na moich doświadczeniach) obsługującego sesje, ciastka, transmisje GET, POST, multiwątkowość z synchronizacją danych, routing plików wraz z ewentualnym ich przeładowaniem to tylko 500 linii kodu.
Gavatar Piotrek Reinmar Koszuliński
25.08.2011, Piotrek Reinmar Koszuliński napisał/-a: Workshopy nie są cienkie, zaś Twoje podejście nazwałbym dziecinnym. Jeśli chcesz, trać kilka godzin czasu (chyba, że szybciej potrafisz napisać i przetestować 500 linii kodu) pisząc od nowa to co napisali inni, to proszę bardzo. Do tego, jakoś ciężko mi sobie wyobrazić, byś potrafił to napisać tak dobrze jak ludzie od connecta (na nim bazuje express), ale może Cię nie doceniam.
Jeśli chodzi o template'y - nie zgodzę się tylko częściowo. Owszem - JS i Node dają genialne możliwości użycia tych samych silników renderowania po stronie klienta i serwera, ale o tym w ogóle nie wspomniałeś. Jeśli chcesz wysyłać czyste dane do każdego browsera, to nie chciałbym z komórki korzystać z jakiegoś dużego portalu, który tak stworzyłeś. Dlatego nie ma niczego głupiego w "szablonach a la PHP", bo zaraz nie będą "a la PHP" jeśli dopiszemy moduł middle-endu (nie myl z middlewarem).

Dodaj komentarz