MEAN Stack - Node.js, express
Transkrypt
MEAN Stack - Node.js, express
MEAN Stack - Node.js, express MEAN Stack - Node.js, express Tworzenie serwisów Web 2.0 dr inż. Robert Perliński [email protected] Politechnika Częstochowska Instytut Informatyki Teoretycznej i Stosowanej 27 lutego 2017 1/78 Plan prezentacji 1 Wprowadzenie do MEAN Stack 2 Node.js npm Wywołania zwrotne 3 Express.js Obsługa formularzy, GET i POST Przesyłanie plików REST API express-generator Silniki szablonów mongoose 4 Tutoriale 5 Źródła MEAN Stack - Node.js, express 2/78 MEAN Stack MEAN Stack - Node.js, express 3/78 MEAN Stack MongoDB – darmowa, otwarta baza NoSQL, przechowuje dokumenty w formacie JSON (BSON), dostarcza wsłasny język zapytań, Express.js – framework JavaScript wspierający tworzenie aplikacji MVC po stronie serwera, pozwala użytkownikom tworzyć trasy (routes) i wykorzystywać szablony, Angular.js – otwarty framework JavsScript wykorzystujący MVC do tworzenia aplikacji internetowych działających po stronie klienta w technologi SPA, wspierany i firmowany przez Google, obecnie występuje w dwóch zupełnie odmiennych wersjach (1.5 i 2.0), Node.js – środowisko JavaScript obsługujące operacje wejścia/wyjścia sterowane zdarzeniami, działające po stronie serwera, bazujące na silniku Google V8. MEAN Stack - Node.js, express 4/78 MEAN Stack MEAN Stack - Node.js, express 5/78 Zalety MEAN Stack Jeden język do wszystkiego - cały zespół używa tylko JavaScript (na serwerze jak i po stronie klienta), obiekty JavaScript po prostu zapisujemy w MongoDB. Można uruchomić niemal na każdym urządzeniu czy platformie - duża przenośność kodu. Technologia ta jest prawie zupełnie darmowa. Bardzo dobre wsparcie dla przetwarzania w chmurze czy pojedynczych funkcjonalności jako usług sieciowych, np. baz danych NoSQL (compose.io czy mongolab.com). Można łatwo wykorzystać dostępne usługi hostingowe, np. https://www.heroku.com. MEAN Stack - Node.js, express 6/78 Node.js https://nodejs.org/en/ platforma działająca po stronie serwera na bazie silnika Google Chrome V8, zaprojektowany przez Ryana Dahl w 2009 roku, ma służyć prostemu tworzeniu szybkich i skalowalnych aplikacji internetowych, open source, całkowicie darmowe, aplikacje napisane w Node.js działają na OS X, MS Windows i Linux’ie, używane przez tysiące programistów na całym świecie. /* Program Hello World w Node.js */ console.log("Hello World!"); MEAN Stack - Node.js, express 7/78 Node.js zalecany do tworzenia aplikacji: z dużą liczbą operacji wejścia/wyjścia, strumieniowania danych, np. video, Single Page Applications (SPA), udostępniających API w formacie JSON, z intensywną wymianą danych w czasie rzeczywistym na wielu urządzeniach, np. portale społecznościowe, nie zalecany przy aplikacjach intensywnie wykorzystujących procesor (CPU), npm - system pakietów Node.js - największy zbiór bibliotek open source na świecie (260 000) → łatwa produkcja aplikacji internetowych, Node.js = środowisko uruchomieniowe + biblioteki JavaScript wykorzystuje biblioteki libuv MEAN Stack - Node.js, express 8/78 Cechy Node.js Asynchroniczność i sterowanie zdarzeniami Serwer wywołuje kolejne API, jedno po drugim. Nie czeka na zakończenie wywołanej funkcji aby zwrócić dane. Za wszystko odpowiada mechanizm obsługi zdarzeń. Duża szybkość - silnik Chrome V8 zapewnia dużą szybkość w wykonywaniu kodu. Jednowątkowość z zachowaniem dużej skalowalności Node.js używa modelu jednowątkowego z pętlą zdarzeń. Potrafi obsłużyć znacznie więcej żądań niż tradycyjne serwery (np. Apache). Mechanizm zdarzeń pomaga serwerowi na udzielanie odpowiedzi w sposób nieblokujący, pozwala to na wysoką skalowalność. W klasycznych serwerach jest tworzona ograniczona liczba wątków obsługujących żądania. Licencja - Node.js jest tworzony na licencji MIT. Projekty, aplikacjie, firmy - długa lista wykorzystywania Node.js: eBay, General Electric, GoDaddy, Microsoft, PayPal, Uber, Wikipins, Yahoo, Yammer... MEAN Stack - Node.js, express 9/78 libUV https://github.com/libuv/libuv międzyplatformowa biblioteka skupiająca się na asynchronicznych operacjach wejścia/wyjścia, stworzona pierwotnie dla Node.js, używana obecnie przez: Luvit, Julia, pyuv i inne, niektóre cechy: wydajna pętla obsługująca zdarzenia, asynchroniczna obsługa gniazd TCP i UDP, asynchroniczna obsługa plików i systemu plików, obsługa sygnałów, obsługa zdarzeń systemu plików, zegar wysokiej rozdzielczości MEAN Stack - Node.js, express 10/78 Najważniejsze części Node.js Najważniejsze części Node.js przedstawiono na rysunku: MEAN Stack - Node.js, express 11/78 Pełna lista modułów Node.js Dokumentacja Node.js, v5.10.0 Assertion Testing Child Processes Console DNS Events HTTP Net Process Readline String Decoder TTY Utilities MEAN Stack - Node.js, express Buffer Cluster Crypto Domain File System HTTPS OS Punycode REPL Timers UDP/Datagram V8 C/C++ Addons Command Line Options Debugger Errors Globals Modules Path Query Strings Stream TLS/SSL URL VM ZLIB 12/78 Obiekty globalne w Node.js Obiekty globalne w Node.js są dostępne we wszystkich modułach, nie trzeba ich w żaden sposób dołączać. filename - nazwa pliku, którego kod jest wykonywany, zawra całą ścieżkę, dirname - nazwa katalogu wraz z całą ścieżką, w którym znajduje się wykonywany plik, setTimeout(cb, ms) - uruchamianie funkcji zwrotniej po określonej liczbie ms, clearTimeout(t) - zatrzymywanie licznika czasu utworzonego wcześniej funkcją setTimeout(), setInterval(cb, ms) -uruchamianie funkcji zwrotnej co określoną liczbę ms. function printHello(){ console.log( "Hello, World!"); } // Wywołanie funkcji po upływie 2 s var t = setTimeout(printHello, 2000); // Usunięcie licznika czasu clearTimeout(t); MEAN Stack - Node.js, express 13/78 Obiekty globalne w Node.js Inne często wykorzystywane obiekty globalne to: console - drukowanie wiadomości w różnych poziomach błędu na stdout albo stderr, zawiera metody: log(), info(), warn(), error(), dir(), trace(), assert() - wyświetlanie wiadomości informacyjnych w różny sposób, console.time(label) - zapamiętuje punkt czasowy związany z etykietą, console.timeEnd(label) - koniec przedziału czasowego z wiązanego z podaną etykietą, wyświetla przedział czasu, process - obiekt może emitować następujące zdarzenia: exit - emitowane tuż przed zakończeniem procesu, beforeExit - emitowane kiedy Node opróżnił już pętle zdarzeń i nie ma innych zadań, uncaughtException - emitowane, kiedy eskalacja wyjątków wróci aż do pętli zdarzeń, zdarzenia konkretnych sygnałów - emitowane, kiedy system otrzyma konkretne zdarzenia, np. SIGINT, SIGHUP, ... Procesy mają też szereg użytecznych właściwości: stdout, stderr, stdin, argv, execPath, execArgv, env, exitCode, version, versions, config, pid, title, arch, platform, mainModule, metod: abort(), chdir(directory), cwd(), exit([code]), getgid(), setgid(id), getuid(), setuid(id), getgroups(), setgroups(groups), initgroups(user, extra group), kill(pid[, signal]), memoryUsage(), nextTick(callback), umask([mask]), uptime(), hrtime(). MEAN Stack - Node.js, express 14/78 Użyteczne moduły w Node.js Najbardziej powszechnie i często używane moduły Node.js: moduł os (Operating System) - podstawowe infomacje związane z systemem operacyjnym (pamięć, procesor, ...) moduł path - przechowywanie i przetwarzanie ścieżek plików i katalogów, moduł net - pozwala na tworzenie zarówno serwerów jak i klientów, łączenie się, przesyłanie informacji w postaci strumieniowej, moduł dns - pozwala na obsługę DNS (sprawdanie adresów, różne typy adresów DNS, kody błędów), moduł domain - pozwala na wychwytywanie nieobsłużonych błędów. var os = require("os"); console.log('endianness : ' + os.endianness()); console.log('type : ' + os.type()); console.log('platform : ' + os.platform()); console.log('total memory : ' + os.totalmem() + " bytes."); console.log('free memory : ' + os.freemem() + " bytes."); endianness : LE type : Linux platform : linux total memory : 8110882816 bytes. free memory : 4815204352 bytes. MEAN Stack - Node.js, express 15/78 REPL Terminal Read Eval Print Loop (REPL) - środowisko komputerowe, np. Linux Shell, w którym polecenia są automatycznie przetwarzane i wyniki są wyświetlane w trybi interakcyjnym. Node.js też ma takie środowisko: Read - wczytuje dane od użytkownika, parsuje do struktur JavaScript i przechowuje w pamięci, Eval - bierze wprowadzone dane i je oblicza, wyznacza wartości, Print - wyświetla wyniki, Loop - trzy powyższe przetwarza w pęltli aż do dwukrotnego nacieśnięcia Ctrl+c. $ node > 1 + ( 2 * 3 ) - 4 3 > a = 12 // zachowane w zmiennej i wyswietlone 12 > var b = 12 // zachowane w zmiennej ale nie wyswietlone (var) undefined > (a+b)*2 48 > console.log(a+b) 24 undefined MEAN Stack - Node.js, express 16/78 REPL Terminal - wiele linii i mamy możliwość pisania wyrażeń składających się z wielu linii, symbol podkreślenia ( ) zwraca ostatni wynik: > x = 5 5 > while(x>0) { ... --x; ... console.log(x); ... } 4 3 2 1 0 undefined > x+8 8 > _ 8 MEAN Stack - Node.js, express 17/78 REPL Terminal - polecenia Ctrl+c - przerywanie aktualnego polecenia, Ctrl+c dwa razy - zamykanie Node REPL, Ctrl+d - zamykanie Node REPL, Klawisze Góra/Dół - historia polecenie, potrzednie/następne polecenie, klawisz Tab - lista aktualnych komend, .help - lista wszystkich komend, .break albo .clear - wyjście z wieloliniowego wyrażenia, .save nazwaPliku - zapis sesji Node REPL do pliku, .load nazwaPliku - wczytanie zawartości pliku do bieżącej sesji. MEAN Stack - Node.js, express 18/78 npm npm - menadżer pakietów dla node.js (dla JavaScript). zbiór pakietów/modułów dla Node.js dostępnych online: https://www.npmjs.com/ narzędzie do instalacji pakietów Node.js, zarządza wersjami i zależnościami pakietów Node.js dokumnetacja - https://docs.npmjs.com/ najczęściej instalowane pakiety: npm, express, less, browserify, pm2, ... $ $ $ $ npm --version sudo npm install npm -g npm install <Nazwa Modułu> npm install express MEAN Stack - Node.js, express 19/78 npm - globalna i lokalna instalacja modułów Pakiety lokalne: domyślnie pakiety instalowane są lokalnie w katalogu node modules w folderze, w którym jest aplikacja Node.js, lokalne pakiety są dostępne poprzez metodę require(), lista lokalnych pakietów/modułów: npm ls. Pakiety globalne: globalne pakiety znajdują się w strukturze systemu plików komputera, nie można ich wczytać używając require(), instalacja pakietu globalnie: npm install express -g, lista globalnych pakietów: npm ls -g. MEAN Stack - Node.js, express 20/78 Tworzenie pakietu Tworzenie pakietu: npm init polecenie pyta o najważniejsze dane pakietu (proponując domyślne wartości), tworzony jest plik package.json, np.: { "name": "rest", "version": "1.0.0", "description": "hello world restfull api", "main": "server.js", "scripts": { "test": "echo \"Error: no test specified\" && exit 1" }, "keywords": [ "restfull" ], "author": "rperlinski", "license": "ISC" } MEAN Stack - Node.js, express 21/78 Plik package.json package.json - plik odpowiedzialny za zarządzanie lokalnie zainstalowanymi pakietami: przechowuje informacje o zależnościach w naszym projekcie, pozwala określić wersje pakietów, których używa nasz projekt, pozwala na odtworzenie naszej aplikacji - łatwość w dzieleniu się naszym projektem Minimum pliku package.json to nazwa i wersja: { "name": "moj-pakiet", "version": "1.0.0" } MEAN Stack - Node.js, express 22/78 Tworzenie pakietu, instalacja Instalacja pakietów mkdir rest; cd rest npm init - inicjalizacja, tworzy plik package.json npm install express, albo lepiej npm install --save express - dodaje zależności do pliku package.json: ... "license": "ISC", "dependencies": { "express": "^4.13.4" } } MEAN Stack - Node.js, express 23/78 Atrybuty w pliku package.json name - nazwa pakietu, atrybut obowiązkowy, tylko małe litery, jedno słowo - nie ma spacji, dopuszczalne myślniki (-) i podkreślenia ( ), version - wersja pakietu, atrybut obowiązkowy, description - opis pakietu, homepage - strona domowa pakietum, author - autor pakietu, contributors - współautorzy pakietu, dependencies - lista zależności, npm automatycznie instaluje wszystkie podane zależności w katalogu node modules naszego pakietu, repository - typ repozytorium i URL pakietu, main - punkt wejściowy pakietu, keywords - słowa kluczowe. MEAN Stack - Node.js, express 24/78 Inne polecenia npm npm uninstall express - odinstalowanie modułu express, npm update express - wywoływane po zmianach w pliku package.json, autoamtycznie aktualizuje zależności, npm search express - wyszukiwanie pakietów korzystając z polecenia npm, npm init - generowanie pliku package.json co tworzy nowy moduł/pakiet, npm adduser - dodanie użytkownika do repozytorium npm (nazwa i poprawny email) i następnie można npm publish - publikowanie naszego pakietu, będzie można go instalować poleceniem npm install :) MEAN Stack - Node.js, express 25/78 Podwójne API Node.js File System - metody asynchroniczne fs.access(path[, mode], callback) fs.close(fd, callback) fs.exists(path, callback) fs.read(fd, buffer, offset, length, position, callback) fs.unlink(path, callback) ... File System - metody synchroniczne fs.accessSync(path[, mode]) fs.closeSync(fd) fs.existsSync(path) fs.readSync(fd, buffer, offset, length, position) fs.unlinkSync(path) ... MEAN Stack - Node.js, express 26/78 Wywołania zwrotne - odczyt z pliku, przykład wywołanie synchroniczne var fs = require("fs"); var data = fs.readFileSync('dane.txt'); console.log(data.toString()); console.log("Koniec programu"); Litwo, Ojczyzno moja! ty jesteś jak zdrowie; Ile cię trzeba cenić, ten tylko się dowie, ... Koniec programu wywołanie asynchroniczne var fs = require("fs"); fs.readFile('dane.txt', function (err, data) { if (err) return console.error(err); console.log(data.toString()); }); console.log("Koniec programu"); Koniec programu Litwo, Ojczyzno moja! ty jesteś jak zdrowie; Ile cię trzeba cenić, ten tylko się dowie, ... MEAN Stack - Node.js, express 27/78 Wywołania zwrotne I Wywołanie zwrotne (ang. callback) - technika programowania będąca odwrotnością wywołania funkcji. Użytkownik rejestruje funkcję do późniejszego wywołania. Funkcje biblioteki wywołają ją w stosownym czasie. Zwykle to programista sam wywołuje funkcje dostarczane przez bibliotekę. Wywołanie zwrotnie: asynchroniczny odpowiednik funkcji, jest wykonywane kiedy zakończy się pewne zadanie, kawałek wykonywalnego kodu, który przekazywany jako argument do innego kodu, od którego oczekujemy, że wywoła przekazany kod w odpowiednim czasie. Node używa tego bardzo intensywnie. Duża część API do Node jest tak napisana, aby wspierać wywołania zwrotne. MEAN Stack - Node.js, express 28/78 Wywołania zwrotne II Programy z funkcjami synchronicznymi: wykonują się sekwencyjnie, z punktu widzenia programisty łatwiej implementować logikę aplikacji. Programy działające asynchronicznie: nie wykonują się sekwencyjnie, jeśli fragment kodu potrzebuje określonych danych powinien być umieszczony w tym samym bloku kodu, żeby wykonanie tych zależnych od siebie instrukcji było sekwencyjne. MEAN Stack - Node.js, express 29/78 Wywołania zwrotne na przykładzie Odczyt z pliku może być: synchroniczny - czekamy na zwrócenie danych zawartych w pliku, asynchroniczny: funkcja zaczyna czytać plik ale ... od razu zwraca sterowanie, wykonywane są kolejne instrukcje; zakończenie odczytywania danych z pliku wykonuje wywołanie zwrotne, jako parametr przekazywana jest zawartość pliku, nie ma tutaj blokowania. Wniosek: wysoka skalowalność Node.js, przetwarzanie dużej liczby żądań bez oczekiwania na zwrócone wyniki. MEAN Stack - Node.js, express 30/78 Pierwszy projekt w Node.js Większość aplikacji Node.js składa się z 3 części: import wymaganych modułów - używa się dyrektywy require, utworzenie serwera - serwer będzie oczekiwał na żadania klientów i zwracał odpowiedzi, odczytywanie żądań i zwracanie odpowiedzi - podstawowe działanie serwera. var http = require("http"); var server = http.createServer(function (request, response) { // Wysyłanie nagłówków protokołu HTTP // Status HTTP: 200 : OK, Content Type: text/plain response.writeHead(200, {'Content-Type': 'text/plain'}); // Wysyłanie ciała odpowiedzi, niezależnie od rodzaju żądania response.end('Pierwszy projekt w Node.js\n'); }); server.listen(5000); console.log('Server działa na http://127.0.0.1:5000/'); MEAN Stack - Node.js, express 31/78 Serwer sieciowy Serwer sieciowy: aplikacja obsługująca żądania HTTP przesyłane od klientów, np. przeglądarki, w odpowiedzi zwracająca strony internetowe, zwykle dostarczane są dokumenty HTML razem z obrazkami, stylami CSS i skryptami, większość serwerów obsługuje skrypty po stronie serwera w jednym z wielu języków, serwery wykonują określone zadania, pobierają dane z bazy, przetwarzają skomplikowaną logikę ... przykładem może być serwer Apache. MEAN Stack - Node.js, express 32/78 Architektura aplikacji internetowej Klasyczny podział aplikacji internetowej na cztery warstwy: Klient - przeglądarki internetowe (w tym z urządzeń mobilnych) i aplikacje wykonujące żądania HTTP, Serwer internetowy - przechwytuje żadania od klientów i zwraca im odpowiedzi, Warstwa biznesowa - zawiera aplikację serwerową wykorzystywaną przez serwer internetowy; komunikuje się z warstwą danych, Dane - zawiera dane w bazie danych albo dostępnych z innego źródła. MEAN Stack - Node.js, express 33/78 Tworzenie serwera z użyciem Node.js i http var http = require('http'); var fs = require('fs'); var url = require('url'); http.createServer( function (request, response) { // Parsuje żądanie zawierające nazwę pliku var pathname = url.parse(request.url).pathname; // Wyświetlanie nazwy pliku, którego dotyczyło żądanie console.log("Request for " + pathname + " received."); fs.readFile(pathname.substr(1), function (err, data) { if (err) { console.log(err); response.writeHead(404, {'Content-Type': 'text/html'}); } else { response.writeHead(200, {'Content-Type': 'text/html'}); response.write(data.toString()); // zwracanie treści wybranego pliku } response.end(); // wysyłanie odpowiedzi }); }).listen(5000); console.log('Serwer uruchomiony na http://127.0.0.1:5000/'); MEAN Stack - Node.js, express 34/78 Tworzenie serwera z użyciem Node.js index.html <html> <head> <title>Pierwszy projekt</title> </head> <body> Pierwszy projekt w Node.js </body> </html> $ node server.js Serwer uruchomiony na http://127.0.0.1:5000/ Otwieramy w przeglądarce: http://localhost:5000/index.html Narzędzie nodemon pozwala na wygodniejszą pracę, automatycznie przeładowuje serwer po zmianach, instalacja: sudo npm install -g nodemon Uruchomienie serwera: nodemon server.js MEAN Stack - Node.js, express 35/78 Tworzenie klienta z użyciem Node.js i http var http = require('http'); // Opcje użyte w żądaniu var options = { host: 'localhost', port: '5000', path: '/index.html' }; // Funkcja zwrotna obsługująca zwrócone dane var callback = function(response){ // Dopisywanie napływających danych do strunienia var body = ''; response.on('data', function(data) { body += data; }); response.on('end', function() { // Wypisanie danych po ich otrzymaniu w pełni console.log(body); }); } // Wysłanie żądania do seerwera var req = http.request(options, callback); req.end(); MEAN Stack - Node.js, express 36/78 Tworzenie klienta z użyciem Node.js Wywołanie aplikacji klienta w innym terminalu, wynik działania: $ node client.js <html> <head> <title>Pierwszy projekt</title> </head> <body> Pierwszy projekt w Node.js </body> </html> MEAN Stack - Node.js, express 37/78 Express http://expressjs.com/ Express to szybki, elastyczny (nie wymuszający konkretnych rozwiązań), minimalistyczny szablon aplikacji internetowych i mobilnych dla Node.js. Express: udostępnia solidną funkcjonalność do budowania aplikacji, pozwala na szybkie budowanie aplikacji bazujących na Node.js, pozwala na utworzenie warstw pośredniczących odpowiadających na żądania HTTP, dostarcza mechanizm trasowania (ang. routing) - różne akcje dla różnych metod i adresów URL, pozwala na dynamiczne renderowanie stron HTML poprzez przekazywanie argumentów do szablonów. MEAN Stack - Node.js, express 38/78 Express.js i warstwy pośrednie Instalacja: npm install express ExpressJS to komplenty framework. Działa z szablonami (jade, ejs, handlebars, hogan.js) i kompilatorami CSS (less, stylus, compass). Dzięki wartstwom pośredniczącym (oprogramowanie pośredniczące) obsługuje również: ciasteczka, sesje, buforowanie, CSRF, kompresję i wiele innych. Oprogramowanie pośredniczące: łańcuch/stos programów przetwarzających każde żądanie do serwera. Takich programów w stosie może być dowolna liczba, przetwarzanie odbywa się jeden po drugim. Niektóre z nich mogą zmieniać żądanie, tworzyć logi czy inne dane, przekazywać je do następnych (next()) programów w strumieniu. MEAN Stack - Node.js, express 39/78 Express-middlewares Warstwy pośredniczące dodajemy do ExpressJS używając app.use dla dowolnej metody albo app.VERB (np. app.get, app.delete, app.post, app.update, ...) MEAN Stack - Node.js, express 40/78 Express - instalacja $ npm install express --save Inne ważne moduły, które warto od razu zainstalować: body-parser - warstwa pośrednia obsługująca JSON, Raw, Text i dane formularza przekazane w URL, cookie-parser - przetwarza nagłówki ciasteczek (cookie header) i dodaje obiekt do req.cookies, w którym klucze to nazwy przesłanych ciasteczek, multer - warstwa pośrednia w Node.js do obsługi multipart/form-data (kodowanie danych z formularza), mongoose - połączenie z bazą MongoDB, praca na schematach i obiektach. MEAN Stack - Node.js, express 41/78 Express, Hello World hello.js var express = require('express'); var app = express(); app.get('/', function (req, res) { res.send('Hello World'); }) var server = app.listen(5000, function () { var host = server.address().address var port = server.address().port console.log("Przykładowa aplikacja nasłuchuje na http://%s:%s", host, port) }) Wynik: $ node hello.js Otwieramy w przeglądarce: http://localhost:5000/ Przykładowa aplikacja nasłuchuje na http://0.0.0.0:5000 Express używa funkcji zwrotnych z argumentami req i res (obiekty request i response), które zawierają bardzo dużo informacji i żądaniu i odpowiedzi. MEAN Stack - Node.js, express 42/78 Express, trasowanie I Reakcje na żądania użytkowników w punktach końcowych (URI, metody protokołu HTTP). var express = require('express'); var app = express(); app.get('/', function (req, res) { console.log("Otrzymano żądanie GET dla strony głównej"); res.send('Hello GET'); }) app.post('/', function (req, res) { console.log("Otrzymano żądanie POST dla strony głównej"); res.send('Hello POST'); }) app.delete('/usun', function (req, res) { console.log("Otrzymano żądanie DELETE dla strony /usun"); res.send('Hello DELETE'); }) app.get('/user_list', function (req, res) { console.log("Otrzymano żądanie GET dla strony /user_list"); res.send('Lista użytkowników'); }) app.get('/ab*cd', function(req, res) { // wzorzec strony: abcd, abxcd, ab123cd, ... console.log("Otrzymano żądanie GET dla strony /ab*cd"); res.send('Wzorzec strony dopasowany'); }) var server = app.listen(5000, function () { var host = server.address().address var port = server.address().port console.log("Przykładowa aplikacja nasłuchuje na http://%s:%s", host, port) }) MEAN Stack - Node.js, express 43/78 Express, trasowanie II Kolejne żądania: GET POST DELETE GET GET GET GET GET - http://localhost:5000/ http://localhost:5000 http://localhost:5000/usun http://localhost:5000/user_list http://localhost:5000/abcd http://localhost:5000/ab123cd http://localhost:5000/abXXcd http://localhost:5000/abcdef // // // // // // // // Hello GET Hello POST Hello DELETE Lista użytkowników Wzorzec strony dopasowany Wzorzec strony dopasowany Wzorzec strony dopasowany Cannot GET /abcdef Reakcja serwera: http://localhost:5000/ Przykładowa aplikacja nasłuchuje na http://0.0.0.0:5000 Otrzymano żądanie GET dla strony głównej Otrzymano żądanie POST dla strony głównej Otrzymano żądanie DELETE dla strony /usun Otrzymano żądanie GET dla strony /user_list Otrzymano żądanie GET dla strony /ab*cd Otrzymano żądanie GET dla strony /ab*cd Otrzymano żądanie GET dla strony /ab*cd MEAN Stack - Node.js, express 44/78 Express, statyczne pliki Express posiada wbudowaną warstwę pośrednią express.static, która pozwala na udostępnianie statycznych plików (obrazy, CSS, HTML, JavaScript, ...) Wystarczy przekazać nazwę katalogu, z którego pliki będą dostępnę poprzez serwer: app.use(express.static(’public’)); var express = require('express'); var app = express(); app.use(express.static('public')); app.get('/', function (req, res) { res.send('Hello World'); }) var server = app.listen(5000, function () { var host = server.address().address var port = server.address().port console.log("Przykładowa aplikacja nasłuchuje na http://%s:%s", host, port) }) Wywołanie: http://localhost:5000/npmLogo.png wyświetli odpowiedni plik znajdujący się w katalogu public. MEAN Stack - Node.js, express 45/78 Formularze, metoda GET form get.js var express = require('express'); var app = express(); app.get('/get.html', function (req, res) { res.sendFile( __dirname + "/" + "get.html" ); }) app.get('/form_get', function (req, res) { response = { imie:req.query.imie, nazwisko:req.query.nazwisko }; console.log(response); res.end(JSON.stringify(response)); }) app.listen(5000); get.html <html> <body> <form action="http://127.0.0.1:5000/form_get" method="GET"> Imie: <input type="text" name="imie"> <br> Nazwisko: <input type="text" name="nazwisko"> <input type="submit" value="Wyślij"> </form> </body> </html> MEAN Stack - Node.js, express 46/78 Formularze, metoda POST form post.js var express = require('express'); var app = express(); var bodyParser = require('body-parser'); var urlencodedParser = bodyParser.urlencoded({ extended: false }) // application/x-www-form-urlencoded app.use(express.static('public')); app.post('/form_post', urlencodedParser, function (req, res) { response = { imie:req.body.imie, nazwisko:req.body.nazwisko }; console.log(response); res.end(JSON.stringify(response)); }) app.listen(5000); post.html <html> <body> <form action="http://127.0.0.1:5000/form_post" method="POST"> Imie: <input type="text" name="imie"> <br> Nazwisko: <input type="text" name="nazwisko"> <input type="submit" value="Wyślij"> </form> </body> </html> MEAN Stack - Node.js, express 47/78 Formularze, przesyłanie plików I file upload.js var express = require('express'); var bodyParser = require('body-parser'); var multer = require('multer'); var app = express(); app.use(express.static('public')); app.use(bodyParser.urlencoded({ extended: false })); var upload = multer({ dest: 'uploads/' }).single('file'); app.post('/file_upload', function(req, res) { upload(req, res, function (err) { if (err) { // błąd przy wczytywaniu/przesyłaniu pliku return } // wszystko poszło dobrze console.log(req.file); // req.file zawiera opis przesyłanego pliku console.log(req.body); // req.body przechowuje pola tekstowe, jeśli takie były response = { message:'Plik wczytany poprawnie', filename:req.file.filename, originalname:req.file.originalname, mimetype:req.file.mimetype, size:req.file.size }; res.end( JSON.stringify( response ) ); }) }) var server = app.listen(5000); MEAN Stack - Node.js, express 48/78 Formularze, przesyłanie plików II file.html <html> <head> </head> <body> Wybierz plik do wysłania: <br /> <form action="http://127.0.0.1:5000/file_upload" method="POST" enctype="multipart/form-data"> <input type="file" name="file" size="50" /> <br> <input type="submit" value="Wyślij plik" /> </form> </body> </html> MEAN Stack - Node.js, express 49/78 Express, cookie-parser https://github.com/expressjs/cookie-parser $ npm install cookie-parser cookies.js var express = require('express') var cookieParser = require('cookie-parser') var app = express() app.use(cookieParser()) app.get('/', function(req, res) { console.log("Cookies: ", req.cookies) }) app.listen(5000); Wynik: $ curl http://127.0.0.1:5000 --cookie "name=Jan;pozd=Hello" Cookies: { name: 'Jan', pozd: 'Hello' } MEAN Stack - Node.js, express 50/78 API, metoda GET server.js var express = require('express'); var app = express(); var fs = require("fs"); app.get('/listUsers', function (req, res) { fs.readFile( __dirname + "/" + "users.json", 'utf8', function (err, data) { console.log( data ); res.end( data ); }); }) app.listen(5000); Żądanie: http://localhost:5000/listUsers { "user1" : { "name" : "johnw", "password" : "dogville321", "profession" : "film_director", "id": 1 }, "user2" : { "name" : "Halina", "password" : "MojeHaslo123", "profession" : "pisarka", "id": 2 }, "user3" : { "name" : "jnowak", "password" : "wiosna2016", "profession" : "malarz", "id": 3 } } MEAN Stack - Node.js, express 51/78 API, metoda GET, konkretny użytkownik server.js var express = require('express'); var app = express(); var fs = require("fs"); app.get('/:id', function (req, res) { fs.readFile( __dirname + "/" + "users.json", 'utf8', function (err, data) { users = JSON.parse( data ); var user = users["user" + req.params.id] console.log( user ); res.end( JSON.stringify(user)); }); }) app.listen(5000); Żądanie: http://localhost:5000/1 { "name":"johnw", "password":"dogville321", "profession":"film_director", "id":1 } MEAN Stack - Node.js, express 52/78 API, metoda POST server.js ... var user = { "user4" : { "name" : "kim2l", "password" : "a2vxZH45Xr", "profession" : "programmer", "id": 4 } } app.get('/addUser', function (req, res) { fs.readFile( __dirname + "/" + "users.json", 'utf8', function (err, data) { data = JSON.parse( data ); data["user4"] = user["user4"]; console.log( data ); res.end( JSON.stringify(data)); }); }) ... Żądanie: http://localhost:5000/addUser { ... "user4" : { "name" : "kim2l", "password" : "a2vxZH45Xr", "profession" : "programmer", "id": 4 } } MEAN Stack - Node.js, express 53/78 API, metoda DELETE server.js ... var id = 2; app.get('/deleteUser', function (req, res) { fs.readFile( __dirname + "/" + "users.json", 'utf8', function (err, data) { data = JSON.parse( data ); delete data["user" + id]; console.log( data ); res.end( JSON.stringify(data)); }); }) ... Żądanie: http://localhost:5000/deleteUser { "user1" : { "name" : "johnw", "password" : "dogville321", "profession" : "film_director", "id": 1 }, "user3" : { "name" : "jnowak", "password" : "wiosna2016", "profession" : "malarz", "id": 3 } } MEAN Stack - Node.js, express 54/78 express-generator express-generator narzędzie generujące szkielet aplikacji do frameworka express. instalacja: npm install express-generator -g Użycie: express [opcje] [katalog], opcje: -V, --version - sprawdzenie wersji Domyślny silnik szablonów to jade -e, --ejs - silnik szablonów ejs --hbs - silnik szablonów handlebars -H, --hogan - silnik szablonów hogan.js Domyślnie style css wprowadzamy bezpośrednio w plikach CSS, -c, --css <silnik> - wsparcie dla silnika stylów (less, stylus, compass, sass) --git - tworzy plik .gitignore -f, --force - wymusza działanie na niepustym katalogu MEAN Stack - Node.js, express 55/78 express-generator Tworzenie struktury aplikacji: express hello Następnie: instalacja zależności: cd hello && npm install uruchimienie aplikacji: DEBUG=hello:* npm start MEAN Stack - Node.js, express 56/78 express-generator, silniki CSS Inne silniki szablonów: hello/views/index.ejs hello/views/error.ejs ("ejs": "2.5.5") hello/views/index.hbs hello/views/layout.hbs hello/views/error.hbs (handlebars - "hbs": "4.0.1") hello/views/index.hjs hello/views/error.hjs (hogan.js - "hjs": "0.0.6") Inne silniki do obsługi stylów: hello/public/stylesheets/style.styl hello/public/stylesheets/style.sass hello/public/stylesheets/style.less hello/public/stylesheets/style.scss MEAN Stack - Node.js, express ("stylus": "0.54.5") ("node-sass-middleware": "0.9.8") ("less-middleware": "2.2.0") ("node-compass": "0.2.3") 57/78 express-generator, jak to działa? Plik wejściowy jest w bin/www. DEBUG=hello:* npm start - uruchamia skrypt start z pliku package.json czyli: ... "scripts": { "start": "node ./bin/www" }, W pliku bin/www jest: obsługa całej aplikacji w ../app.js wczytanie modułu http uruchomienie serwera na porcie 3000, rejestracja dwóch funkcji: do obsugi błędów i nasłuchiwania W app.js mamy 6 innych modułów: express, path, serve-favicon, morgan, cookie-parser, body-parser. Mamy też użycie dwóch plików JS: var routes = require('./routes/index'); var users = require('./routes/users'); Dokładnie tak samo jest generowany projekt przez WebStorm. MEAN Stack - Node.js, express 58/78 express-generator, jak to działa? II Rooting ze strony głównej i dla adresu /users: app.use('/', index); app.use('/users', users); // ten jest dla stron // ten jest pod API W pliku app.js jest podpięcie trasowania z index.js i users.js. Ścieżki trasowania są podzielone na dwa pliki, najpierw początek adresu jest ustalony w app.js, reszta jest w index.js i users.js. Następnie jest sporo warstw pośredniczących (matoda app.use()) do obsługi JSONa, wysyłania formularzy metodą POST, obsługi ciasteczek, dostarczania statycznych stron,... Jest też obsługa błędów, przekazywanie ich do wyświetlenia. Trochę powyżej jest obsługa widoków: // view engine setup app.set('views', path.join(__dirname, 'views')); app.set('view engine', 'jade'); MEAN Stack - Node.js, express 59/78 Node.js - eksportowanie modułów Moduły w Node.js są związane z plikami - jeden plik to jeden moduł. Wczytywanie modułów odbywa się za pomocą polecenia require(), np.: kolo.js var PI = Math.PI; exports.pole = function (r) { return PI * r * r; }; module.exports.obwod = function (r) { return 2 * PI * r; }; main.js var kolo = require('./kolo.js'); console.log('Pole koła wynosi ' + kolo.pole(2)); console.log('Obwód koła wynosi ' + kolo.obwod(3)); Pole koła wynosi 12.566370614359172 Obwód koła wynosi 18.84955592153876 Zmienna PI jest prywatna, widoczna tylko w zakresie modułu. MEAN Stack - Node.js, express 60/78 Node.js - eksportowanie modułów Moduł jako funkcja (np. konstruktor) albo kompletny obiekt: kwadrat.js // przypisanie do exports nie zmieni modułu, trzeba użyć module.exports module.exports = function(a) { return { pole: function() { return a * a; } }; } main.js var kwadrat = require('./kwadrat.js'); var mojKwadrat = kwadrat(4); console.log('Pole kwadratu wynosi ' + mojKwadrat.pole()); Pole kwadratu wynosi 16 MEAN Stack - Node.js, express 61/78 Ustawienia aplikacji Tworzymy właściwości przypisując wartości do nazw zmiennych (nazwa, wartość), których nazwy są ustalone przez express. Można tworzyć też własne zmienne, np.: app.set('tytul', 'Moja stronka'); // utworzenie zmiennej tytul var zmienna = app.get('tytul'); // odczyt zmiennej console.log(zmienna); // wypisanie wartość, Moja stronka Niektóre zmienne pozwalające ustawić działanie aplikacji express: view - nazwa katalogu (String) albo tablicy katalogów (Array) gdzie mieszczą się szablony widoków. W przypadku tablicy katalogi są przeglądanie w kolejności występowania w tablicy. Domyślna wartość to: process.cwd() + ’/views’ view engine - nazwa określa domyślny silnik, który będzie użyty jeśli nie określono jawnie później. // ustawienie silnika dla widoków app.set('views', path.join(__dirname, 'views')); app.set('view engine', 'jade'); MEAN Stack - Node.js, express 62/78 Silniki szablonów Zarówno express-generator jak i WebStorm oferują do wyboru jeden z kilku silników szablonów: ejs|hbs|hjs|jade|pug|twig|vash Domyślnym silnikiem szablonów jest Jade. Jade, obecnie Pug - https://pugjs.org EJS - http://ejs.co/ Handlebars - http://handlebarsjs.com/ Hogan.js - http://twitter.github.io/hogan.js/ MEAN Stack - Node.js, express 63/78 Silniki szablonów - Jade (Pug) Pug, wcześniej Jade (zastrzeżony znak towarowy) https://pugjs.org tutorial - http://learnjade.com/tour/intro/ Cechy Pug/Jade: słowo Pug to mops :) silnik szablonów wysokiej wydajności, zaimplementowany w JavaScript dla Node.js i dla przeglądarek, pełna integracja z Express.js jako jeden z wspieranych silników szablonów, zespół pracował nad niekompatybilną wersją Jade 2.0.0 kiedy zmieniono nazwę na Pug, instalacja Pug oznacza używanie nowej wersji 2.0.0 (ciągle jeszcze beta), nazwa jade jest ciągle wspierana w repozytoriach npm. MEAN Stack - Node.js, express 64/78 Silniki szablonów - Pug/Jade Możliwości szablonów Jade/Pug: są wrażliwe na liczbę spacji określających wcięcia dla zagnieżdżonych znaczników, pozwalają na różne rodzaje dołączania treści ze zmiennych czy obiektów do szablonu, zawierają: instrukcje warunkowe, instrukcję case, obsługę pętli (each, while), do szablonów można dołączać kod JavaScript, posiadają komentarze jednoliniowe i blokowe, przenoszące się lub nie do wynikowego kodu HTML, można dołączyć jeden szablon wewnątrz innego - include, wsparcie dla dziedziczenia poprzez bloki (block) albo zwyczajne dziedziczenie (extends), można tworzyć bloki z określoną nazwą i wielokrotnie ich używać. MEAN Stack - Node.js, express 65/78 Silniki szablonów - EJS EJS - <% Effective JavaScript %> http://ejs.co/ Cechy: wyrażenia umieszczanie w znacznikach <% %> modyfikacja znaczników HTML: <%= %> (możliwość konfiguracji funkcji zastępowania znaczników) brak modyfikacji znaczników, wyjście nieprzetworzone: <%- %> tryb usuwania znaków nowej linii, kończy się znacznikiem -%> tryb usuwania białych znaków, oganieczniki: <%_ _%> dwolne ograniczniki, np. użycie <? ?> zamiast <% %> wspiera dziedziczenie szablonów, wsparcie szablonów po stronie serwera i klienta (przeglądarka), statyczne buforowanie pośredniego JavaScriptu, statyczne buforowanie szablonów, kompiluje się z systemem widoków Expressa. MEAN Stack - Node.js, express 66/78 Silniki szablonów - Handlebars Handlebars - http://handlebarsjs.com/ Cechy: w dużej mierze kompatybilny z Mustache (http://mustache.github.io/), zawiera dodatkową funkcjonalność wyrażenia umieszczamy w parze znaków {{ ... }} komentarze w szablonie: {{!-- --}} albo {{! }} kompilacja szablonu w przeglądarce albo wcześniejsza prekompilacja (szybsze działanie strony) zawiera przekształcanie znaczników HTML (dla bezpieczeństwa, {{napis}}), można je wyłączyć korzystając z zapisu {{{napis}}}, przy użyciu bloku rozszerzeń można dodać obsługę pętli, instrukcji warunkowych, itp. w znaczniku szablonu można używać ścieżek, dostępu do zagnieżdżonych pól obiektu, pozwala na używanie literałów, pozwala na tworzenie szablonów cześciowych wielokrotnego użytku. MEAN Stack - Node.js, express 67/78 Silniki szablonów - Hogan.js http://twitter.github.io/hogan.js/ Cechy: kompilator dla silnika szablonów Mustache (http://mustache.github.io/), zintegrowany z Express - pakiet hogan-express, wspiera podział szablonów na cześci (działa podobnie do include), pozwala na tworzenie układów (layout) często występujących na stronie coś jak szablon rodzica, wspiera buforowanie - aplikacja działa szybciej unikając niepotrzebnego renderowania, inaczej niż Handlebars, Hogan.js nie zawiera dodatkowych funkcjonalności, np. pętli czy instrukcji warunkowych, pozwala na tworzenie własnych filtrów. MEAN Stack - Node.js, express 68/78 mongoose http://mongoosejs.com/ Mongoose: biblioteka dla Node.js udostępniająca mapowanie obiektowe (podobne do ORM) z interfejsem znanym z Node.js, opiera się na Object Data Mapping (ODM) - zmiana danych z bazy do obiektów JavaScript, którch można użyć w aplikacji, dostarcza gotowe rozwiązanie do modelowania danych aplikacji, zawiera wbudowane rzutowanie typów, walidację, budowanie zapytań, gotowe, praktyczne rozwiązania dla logiki biznesowej i wiele innych. MEAN Stack - Node.js, express 69/78 mongoose - sposób działania I Trzeba zainstalować mongoose w projekcie: npm install mongoose Dołączamy mongoose do projektu i łączymy się z bazą danych, np. test (zostanie utworzona jeśli takiej nie było): var mongoose = require('mongoose'); mongoose.connect('mongodb://localhost/test'); Sprawdzamy czy połączenie się udało: var db = mongoose.connection; db.on('error', console.error.bind(console, 'błąd połączenia...')); db.once('open', function() { // połączenie udane! }); W mongoose wszystko zaczyna się od schematu: var friendSchema = mongoose.Schema({ nazwa: String }); Mając schemat, na jego bazie tworzymy model var Friend = mongoose.model('Friend', friendSchema); MEAN Stack - Node.js, express 70/78 mongoose - sposób działania II Na bazie modelu tworzymy dokumenty (zawierają pola i typy jak w schemacie): var franek = new Friend({ nazwa: 'Franek' }); console.log(franek.nazwa); // 'Franek' Przyjaciele mogą się witać - zobaczmy, jak dodać funkcjonalność do naszych dokumentów: // metody należy dodać do schematu ZANIM utworzy się z niego model friendSchema.methods.sayHello = function () { var powitanie = this.nazwa ? "Cześć, mam na imię " + this.nazwa : "Witaj, nie wiem jak się nazywam ..."; console.log(powitanie); } Funkcja dodana do pola methods schematu i wykorzystana w modelu jest dostępna w każdym utworzonym dokumencie var jola = new Friend({ nazwa: 'Jolanta' }); jola.sayHello(); // "Cześć, mam na imię Jolanta" MEAN Stack - Node.js, express 71/78 mongoose - sposób działania III Zapis dokumentów w bazie odbywa się dzięki metodzie save(): // pierwszy argument odpowiada za błędy jola.save(function (err, jola) { if (err) return console.error(err); jola.sayHello(); }); Odczyt dokumentów zapisanych w bazie, metoda find(): Friend.find(function (err, przyjaciele) { if (err) return console.error(err); for(var i=0; i<przyjaciele.length; i++) { console.log('%s', przyjaciele[i].nazwa); } }) Wyszukiwanie można prowadzić, np. po nazwie: find({ nazwa: /ˆJol/ } Friend.find({ nazwa: /^Jol/ }, function (err, przyjaciele) { if (err) return console.error(err); console.log("====================\n"); for(var i=0; i<przyjaciele.length; i++) { console.log('%s', przyjaciele[i].nazwa); } }); // lista przyjaciół nazywających sie Jol* MEAN Stack - Node.js, express 72/78 mongoose - schematy Jak tego używać? mongoose - http://mongoosejs.com/index.html Resource (URI) /dokument /dokument/:id POST (create) nowy dok. błąd GET (read) lista dok. dok. o :id PUT (update) błąd aktualizacja :id DELETE (destroy) błąd usuń 1 dok. o ID server.js var mongoose = require('mongoose'); var TodoSchema = new mongoose.Schema({ name: String, completed: Boolean, note: String, updated_at: { type: Date, default: Date.now }, }); module.exports = mongoose.model('Todo', TodoSchema); Typy danych w mongoose: String, Boolean, Date, Array, Number, ObjectId, Mixed, Buffer. MEAN Stack - Node.js, express 73/78 Tutoriale I Creating RESTful APIs With NodeJS and MongoDB Tutorial (Part II) Dobry tutorial, jest wprowadzenie teoretyczne, dalej jest instalacja (express-generator), następnie jest dość dużo o Mongoose CRUD i dalej dobra i ważna teoria, na koniec jest konkretnie działający przykład z listą TODO (jest generowanie wnętrza aplikacji na serwerze z express), obsługa CRUD - każda funkcja obsługiwała inną metodę HTTP. MEAN Tutorial (Part 3) : Build REST API’s with node express and mongo. Tutaj widzę, że w każdej funkcji obsługującej CRUD są zapisane konkretne, szczegółowe zapytania do mongoDB. Czyli jest to bardzo szczegółowe podejście chyba w dużej części przypadków nie potrzebne. Tutaj nie ma mongoose, wszystko robimy ręcznie, na kolekcjach! Nie będę przerabiał ale ważny tutorial! MEAN Stack - Node.js, express 74/78 Tutoriale II Express.js 4, Node.js and MongoDB REST API Tutorial Mamy tutaj takie technologie: Node.js, MongoDB poprzez Mongoskin, Express.js. Biblioteki: express, body-parser, mongoskin (obsługa MongoDB), expect.js, mocha i superagent (do testowania). Testowanie odbywa się z Mocha i Superagent. Robimy zwykłe REST API z JSON. Tutorial ma strukturę: 1. 2. 3. 4. 5. 6. 7. Node.js and MongoDB REST API Overview REST API Tests with Mocha and Superagent - trochę o pisaniu automatycznych testów NPM-ing Node.js Server Dependencies - o mongoskin (lżejszy niż mongoose i bez schematów) Express.js 4.x Middleware Caveat Express.js and MongoDB (Mongoskin) Implementation - podłączenie MongoDB, użycie API Running The Express.js 4 App and Testing MongoDB Data with Mocha - testowanie Conclusion and Further Express.js and Node.js Reading - podsumowanie Wartościowy tutorial ze względu na użycie innej biblioteki do mongo: mongoskin. Instalacja express jest wewnątrz katalogu, nie ma tworzenia struktry frameworka poleceniem express-generator. Czyli to prostsze podejście. Każda z metod HTTP obsługiwana w osobnej funkcji. Generalnie bardzo podobnie sie używa jak mongoose. MEAN Stack - Node.js, express 75/78 Tutoriale III Build a RESTful API using Node and MongoDB Standard: Node.js, mongoDB, express, mongoose, body-parser. Każda metoda HTTP obsługiwana oddzielnie. Schemat zawiera dwa pola: mail i zakodowane hasło. To ostanie warto wykorzystać. API: GET /users – Return all Users from MongoDB POST /users – Add new user in MongoDB GET /users/:id – Return User with matched ID PUT /users/:id – Update users information DELETE /users/:id – Delete particular user Nie ma tutaj jednak uwierzytelnienia. Nie ma też wcale teroii. Jest też bliźniaczy tutorial do zrobienia takiego API na MySQLu. MEAN Stack - Node.js, express 76/78 Tutoriale IV CREATING A SIMPLE RESTFUL WEB APP WITH NODE.JS, EXPRESS, AND MONGODB Jest mongoDB i Node.js. Jest express, łącznie ze strukturą wewnętrzną. Użyto biblioteki JADE do tworzeina i zarządzania szablonami (http://jade-lang.com/) oraz biblioteki monk (https://github.com/Automattic/monk) do obsługi MongoDB. monk jest malutką biblioteką, prostszą niż mongoose i mongoskin. Wykorzystano AJAX i jQuery do działania w HTMLu... Jak dla mnie to chyba za duże wchodzenie w szczegóły... Building your first application with MongoDB: Creating a REST API using the MEAN Stack - Part 2 Jest MEAN Stack, standardowo. W pierwszej części tutoriala jest trochę teori. Są cztery kolekcje: użytkowników, kanałów RSS, przeczytanych kanałów RSS oraz kanałów RSS przypisanych do konkretnych użytkowników. To jest w takim razie chyba najbardziej rozbudowany tutorial... Tutaj jest uwierzytelnienie ale dużo tego i skomplikowane ... zostawiam na razie uwierzytelnienie. MEAN Stack - Node.js, express 77/78 Źródła https://nodejs.org/en/ https://en.wikipedia.org/wiki/Node.js http://expressjs.com/ https://en.wikipedia.org/wiki/Express.js http://www.tutorialspoint.com/nodejs/index.htm https://www.npmjs.com/ https://github.com/libuv/libuv https://en.wikipedia.org/wiki/Callback_(computer_programming) http://jade-lang.com/ http://mongoosejs.com/ MEAN Stack - Node.js, express 78/78