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:
__dirname, to zmienna globalna która jako wartość przyjmuje ściężkę do katalogu w których uruchamiamy skrypt.- metoda
readFileSyncwczytuje 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' }, { 'title': 'Wpis nr 3', 'lead' : 'this is my lead post no. 3', 'full' : 'this is my full post no. 3 and some stuffffff' } ];
- jakaś
- lists ;)
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ądarcereq.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/404i 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.
Komentarze
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