w Praktyce
10 godz. 44 min · Node.js · Full-stack i Programowanie
Piotr PalarzWeb DeveloperW kursie tym poznasz platformę Node.js od podstaw, aż po bardziej zaawansowane koncepcje. Zaczniemy od omówienia czym jest Node, a także jakie może być zastosowanie tej technologii. Następnie przejdziemy przez proces instalacji i napisanie swojego pierwszego skryptu. Już na samym początku dokładnie omówimy tworzenie własnych modułów, gdyż jest to wiedza niezbędna, by dobrze zrozumieć funkcjonowanie Node. Następnie dowiesz się czym są zdarzenia, jak działa model “publish / subscribe”, a także czym jest “event-driven development”. Chwilę później omówimy pracę z buforami, stream’ami, a także ze standardowym wejściem i wyjściem. Ta wiedza pozwoli Ci zrozumieć jak tworzone aplikacje mogą otrzymywać od użytkownika dane oraz jak je wyświetlają.
Niezwykle ważnym rozdziałem będzie ten, poświęcony pracy z systemem plików. Szczególnie dla dewelopera, pracującego dotychczas z językiem JavaScript wyłącznie w środowisku przeglądarki internetowej. Node pozwala bowiem tworzyć nowe pliki, zapisywać w nich dane oraz odczytywać i usuwać pliki i katalogi. Przy wszystkich tych operacjach, niezwykle ważna jest jednak asynchroniczna natura Node. Dowiesz się jak działa, a także jakie są jej zalety. Na tym etapie nie zabraknie oczywiście praktycznego projektu, którym będzie aplikacja typu CLI (Command Line Interface). Pozwoli nam ona grupowo zmienić nazwy wielu plików, według podanego wzorca.
W kolejnym rozdziale poruszymy fundamentalną dla Node kwestię, mianowicie tworzenie serwerów sieciowych. Zaczniemy od najniższego poziomu, tworząc prosty serwer bazujący na protokole TCP/IP. Wiedza w jaki sposób Node radzi sobie z takim zadaniem, pozwoli później lepiej zrozumieć wyższe warstwy, takie jak np. HTTP czy WebSockets. Chwilę później stworzymy swój pierwszy serwer HTTP, do którego będzie można wysyłać zapytania wprost z przeglądarki internetowej. Omówimy również jak w Node wykorzystać bezpieczne szyfrowanie HTTPS.Na tym etapie będziesz już miał solidną wiedzę jak pracować z Node, jednak zanim przejdziemy dalej, zatrzymamy się, by omówić jak dokładnie działa Node.js, a także jak ta platforma została zbudowana. Dwie dość obszerne lekcje, będą być może jednymi z najważniejszych w tym kursie. Dowiesz się w nich czym jest, a także jak działa jednowątkowa pętla zdarzeń, czym jest proces i wątek, a także zobaczysz kod źródłowy Node.js i wszystkie bloki budulcowe, z jakich Node się składa. To naszym zdaniem niezwykle ważny temat, często jednak pomijany w wielu materiałach. Dzięki dogłębnemu zrozumieniu jednowątkowej natury języka JavaScript i asynchroniczności Node, będziesz mógł tworzyć dużo lepsze aplikacje.
Node.js posiada kilkanaście wbudowanych modułów, z których w dowolnej chwili można skorzystać. Wszystkie jednak dają nam dużą, niskopoziomową kontrolę, ale czasami sporo kodu należy napisać, by zrealizować jakieś zadanie. Jest to jednak świadomy wybór twórców Node, gdyż całą resztę świetnych rozwiązań, dopisuje nieustannie ogólnoświatowa społeczność deweloperów. Zdecydowana większość z modułów ląduje w rejestrze npm. Jest to genialny package manager, który pozwoli nam wyszukiwać, pobierać i aktualizować niezliczoną ilość modułów. Dowiesz się zatem jak korzystać z npm, a chwilę później zaczniemy wykorzystywać zgromadzone tam moduły w dalszej pracy.Jednym z najpopularniejszych modułów jest express.js, który pozwala w bardzo prosty sposób tworzyć serwery HTTP. Grzechem byłoby zatem z niego nie skorzystać. Dowiesz się wszystkiego co niezbędne, by zacząć tworzyć własne aplikacje bazujące na protokole HTTP z użyciem express.js, a także kilku dodatków do tego systemu. Zobaczysz jak routować zapytania, jak korzystać z middleware czy serwować statyczne pliki. Następnie omówimy współpracę z bazą danych MongoDB i z jej wykorzystaniem stworzymy API typu REST. Stworzona aplikacja pozwoli odczytywać dane z bazy i przesyłać je do klienta w formacie JSON, a także dodawać nowe dane, aktualizować i usuwać je. Wszystko to zgodnie z dobrymi praktykami pracy z REST.
Chwilę później czeka Cię kolejny praktyczny projekt - skracacz linków. Stworzymy wspólnie aplikację, która pozwoli skrócić dowolny adres URL do krótkiej formy. Oczywiście będzie działać również w drugą stronę! Kiedy przejdziemy pod skrócony adres, przekieruje nas do odpowiedniej witryny. Node.js to platforma wręcz stworzona do tworzenia aplikacji typu real-time, dlatego w kolejnym rodziale podejmiemy temat technologii WebSockets. Dowiesz się jakie są jej zalety, a także jak pracować z nią po stronie serwera i klienta. Tutaj czeka nas kolejny praktyczny, niezwykle ciekawy projekt. Wykonamy bowiem czat grupowy. Aplikacja ta pozwoli dowolnej ilości użytkowników podłączyć się do czatu podając swój nick, a następnie wysyłać widoczne dla wszystkich wiadomości. Zaimplementujemy nawet takie rozwiązania jak wyświetlanie statusów o dołączeniu kogoś do czatu, a także o jego opuszczeniu.W przedostatnim rodziale tego kursu podejmiemy tematykę dobrych praktyk pracy z Node.js. Na początku omówimy najważniejsze konstrukcje nowej specyfikacji EcmaScript 2015, które są znakomicie wspierane w Node. Chwilę później omówimy jak korzystanie z Promises uprości, a także ulepszy nasz kod. Wśród dobrych praktyk nie zabraknie również informacji o debugowaniu aplikacji. Zobaczysz sprawdzone sposoby, by znaleźć błędy lub lepiej, krok po kroku, zrozumieć jak działa napisany wcześniej kod. Dowiesz się również jak pracować z błędami, by Twoje aplikacje działały w sposób przewidywalny.
Ostatni rozdział w całości został poświęcony temu, co zwykle jest pomijane w innych materiałach, mianowicie wdrażaniu aplikacji do produkcji. Przez cały ten kurs pracować będziemy lokalnie, lecz kiedy aplikacje są już gotowe, wypadałoby udostępnić je światu. Wdrażanie aplikacji napisanych z użyciem Node.js nie jest jednak tak oczywiste, jak np. wgrywanie WordPress’a u wybranego hostingodawcy. Ty będziesz miał jednak możliwość zobaczyć, jak wdrożyć napisany przez nas grupowy czat na platformie Heroku. Jest to bardzo popularny serwis działający jako PaaS (Platform as a Service). Za darmo będziesz mógł w ciągu kilku chwil uruchomić swoją aplikację.Zobaczysz o co należy zadbać, by wszystko poszło gładko. Serwisy typu PaaS dbają o bardzo wiele aspektów wdrażania i serwowania naszych aplikacji, takich jak bezpieczeństwo oraz nieustanną dostępność. Mają jednak pewne ograniczenia. Z tego powodu, dowiesz się również jak wdrożyć swoją aplikację na serwerze wirtualnym VPS z systemem Ubuntu Server. Takie rozwiązanie daje nam całkowitą kontrolę, ale także obarczone jest większą odpowiedzialnością. Zaczniemy od instalacji na serwerze platformy Node.js, systemu kontroli wersji GIT, a także innych niezbędnych modułów
Następnie zobaczysz jak skonfigurować swoje lokalne środowisko tak, by za pomocą GIT’a wysyłać kod do zdalnego serwera, a potem jednym poleceniem wdrażać go do produkcji. Dowiesz się również jak jednocześnie serwować wersję produkcyjną oraz developmencką. W rodziale tym poruszymy również inne kwestie, takie jak procesy potomne czy tworzenie klastrów. Dzięki tej wiedzy, będziesz mógł maksymalnie wykorzystać dostępne zasoby serwera. Na sam koniec tego kursu rzucimy okiem również na inne, nie przedstawione wcześniej zastosowania Node, a także nakreślimy dalszą drogę nauki w tym zakresie.
Kurs ten jest dla wszystkich osób, które dobrze czują się w technologiach frontendowych, tj. HTML, CSS i JavaScript, a teraz chcą rozpocząć swoją przygodę z back-endem. Im zatem lepiej znasz język JavaScript, tym więcej wyciśniesz z Node, natomiast nie jest wymagana bardzo zaawansowana wiedza z zakresu tego języka.
Tą lekcją rozpoczynamy rozdział o WebSockets, czyli o technologii, która idealnie wpasowuje się w Node.js
i w jego jednowątkową pętlę zdarzeń, a także asynchroniczną naturę.
Na początek jednak chciałbym ci powiedzieć, jak WebSockets działa, zanim przejdziemy dalej.
Zapewne wiesz, że standardowy protokołu HTTP jest bezstanowy, to znaczy, że my wysyłamy do serwera zapytanie
i serwer odsyła nam odpowiedź.
I to jest wszystko.
Czyli powiedzmy pobieramy stronę.
Wysłaliśmy zapytanie, serwer przygotował dane i odesłał.
Później wysyłamy zapytanie po pliki CSS, odsyła nam je itd.
Natomiast nie mamy takiej komunikacji dwustronnej, nie mamy takiego po prostu kanału dwustronnej komunikacji.
Musimy wysłać zapytanie, aby otrzymać odpowiedź.
Jeżeli kiedykolwiek widziałeś stronę internetową, gdzie nie wysyłało się jakby żadnych zapytań, nic się nie odświeżało,
a co jakiś czas były np. nowe wiadomości wciskane na stronę za pomocą takiego pusha, to zanim powstały
WebSockets,
to działało to w ten sposób, że co kilka sekund np. wysłaliśmy żądanie AJAX a do serwera, pytając czy ma jakieś
dane.
Jeżeli miał, to nam odsyłał, jeżeli nie, to nie.
Wysłaliśmy kolejne i kolejne.
Taka technika nazywała się polling. Natomiast mieliśmy również long polling.
I ona polegała na tym, że wysłaliśmy zapytanie do serwera, ale równocześnie ustawiając timeout na jakąś
większą wartość, np. 10 sekund.
I w tym czasie serwer miał czas na odpowiedź. Jeżeli serwer stwierdził, że nie ma jeszcze żadnych danych,
nie przerywał tego połączenia, bo timeout był ustawiony na 10 sekund.
Ale jeżeli w tym czasie jakieś dane na serwer trafiły, to mógł nam je odesłać. Jeżeli nie, to po dziesięciu
sekundach połączenie się kończyło i wysyłaliśmy nowe. Takie techniki działały, ale nie były najlepsze.
One tak naprawdę były obejściem problemu. Natomiast kilka lat temu powstała technologia WebSockets razem
z HTML 5 i ona jest genialna z tego powodu, że pozwala nam tworzyć dwukierunkowy kanał komunikacji pomiędzy
klientem i serwerem.
Klientem może być przeglądarka internetowa, ale nie tylko, bo WebSockets jest również popularne np. w
aplikacjach mobilnych.
Działa to w ten sposób, że na początku podłączamy się do serwera i jest robiony tzw. uścisk dłoni, czyli
z angielskiego handshake.
Jeżeli serwer zaakceptuje nasze połączenie, to jest ustanowiony taki kanał dwukierunkowej komunikacji.
I teraz my o nic nie musimy serwera prosić. Wystarczy, że sobie czekamy a serwer może nam jakieś dane wysłać.
Podobnie my w dowolnym momencie możemy wysłać dane do serwera.
Taka technologia jest genialna m.in. do tworzenia aplikacji typu real time jak czaty. I taki czat sobie utworzymy
w jednej z kolejnych lekcji. Będziemy mogli nic nie robić, a jeżeli ktoś coś wyśle na czacie, to serwer
to do nas przyśle albo będziemy mogli coś wpisać, wysłać to do serwera i serwer roześle to dalej.
Na początek tej lekcji zainstalujmy sobie to, co jest w package.json, czyli Express i Express Handlebars.
Czyli npm install i teraz będziemy chcieli sobie znaleźć jakiś dobry moduł, który obsługuje
WebSockets.
Co ciekawe jest ich bardzo wiele. Ja teraz pokażę ci taki podstawowy, który nazywa się WS. Jest bardzo
popularny, co widać tutaj. 300 tysięcy pobrań wczoraj, więc śmiało możemy go zainstalować.
Dlatego zrobię to od razu - npm install ws save i będziemy chcieli go od razu sobie zaimportować.
Natomiast może zanim to zrobimy, to uruchommy sobie nodemonem serwer.
Wrócę jeszcze do kodu, żeby pokazać ci, co tutaj jest. Zwykły serwer i renderujemy sobie home. A w home zrobiłem
coś takiego, mianowicie prosty formularz i niżej kod do obsługi tego formularza. Jest to kod JavaScript.
On nie będzie wywoływany na serwerze.
Pamiętaj, że to zostanie odesłane do klienta, czyli jeżeli sobie tutaj odświeżę, to pojawi się to w tym miejscu, bo zostało
tutaj przesłane. I w tym formularzu w kodzie JavaScript wykonywanym po stronie klienta
napisałem sobie taką rzecz, że jeżeli coś tutaj wpiszemy, kliknę Wyślij, to to pole czyszczę, a wstawiam to
do konsoli. Zaraz sobie to zmodyfikujemy.
Natomiast tutaj będziemy chcieli sobie zrobić zmienną WebSocketServer i zrobimy require("ws") i następnie
.Server.
W ten sposób działa to WebSocketServer.
I chociaż tutaj mamy uruchomiony już serwer HTTP na porcie 8080, to pod spodem uruchomimy sobie kolejny serwer,
tym razem WebSockets. Więc utworzę zmienną, którą nazwę wss jak WebSocketServer i tutaj wpiszemy new
WebSocketServer.
I tutaj podajemy port, na którym chcemy taki serwer uruchomić - dowolny. Ja sobie wpiszę 3000. I teraz
wystarczy, że przypiszemy odpowiednią obsługę zdarzeń. Taki obiekt korzysta oczywiście z EventEmittera, czyli
możemy przypisywać zdarzenia. Przypiszemy sobie zdarzenie na połączenie, czyli to jest connection. Jest
to funkcja, która wykona się za każdym razem, gdy ktoś się podłączy do serwera.
Podobnie jak w przypadku HTTP, ale w przypadku HTTP ta funkcja wykonuje się dla każdego żądania, a tutaj
wykona się tylko na początku, kiedy będzie ten handshake, o którym mówiłem. I tutaj zostanie przekazany socket.
Zauważ, że jest to podobnie jak w przypadku modułu net, który omawialiśmy w tym kursie, na najniższym poziomie
w Node.js
I ten socket to będzie podłączony klient.
Czyli kiedy on się podłączy, to chcemy mu przypisać kolejne zdarzenia.
Będzie to zdarzenie message. Czyli za każdym razem jak klient, czyli nasza przeglądarka w tym przypadku, wyśle
do serwera coś, to wykona się ta funkcja, którą tutaj wpisuję. I to coś to będzie message przekazane w
tym miejscu.
Co ja będę chciał zrobić? Otóż zrobię sobie na serwerze console.log. Bo pamiętaj - cały czas teraz piszemy
kod Node, czyli ten wykonywany na serwerze. I następnie za pomocą socket.send możemy coś odesłać. Czyli
tu znowu moglibyśmy coś pobrać z bazy danych i przygotować i wysłać dalej.
Ja jednak chcę odesłać to, co przysłał klient.
Msg - u nas będzie to string, ale WebSockets pozwala przesyłać również dane binarne.
Skoro to jest string, to chcę go powiększyć i odesłać w formie toUpperCase .
Tyle nam wystarczy.
Nie mamy żadnych błędów, czyli ten serwer działa.
Natomiast teraz będziemy chcieli w kodzie klienckim, czyli w tym miejscu, połączyć się z takim WebSocket.
To, co jest ważne, to od kilku lat wszystkie poważne przeglądarki wspierają technologię WebSockets razem
z HTML 5, więc nie musimy tutaj importować żadnej dodatkowej biblioteki, ale w kolejnej lekcji to zrobimy
i powiem ci dlaczego. Natomiast natywnie można w przeglądarce skorzystać z WebSockets i wygląda to
w ten sposób.
Otóż na początku tego naszego skryptu tworzę zmienną socket i new WebSocket. WebSocket jest to właśnie
dostępna globalnie zmienna, taki konstruktor, który mamy w przeglądarce. I tutaj podajemy protokół nie
http, ale właśnie ws. Dla połączeń szyfrowanych, tak jak https,
tutaj byłoby wss, czyli secure. Localhost 3000, bo tutaj podałem taki port.
To nam się podłączy.
Mamy wiele zdarzeń, które to można przypisać, np. on connection, on open itd.
Natomiast ja chcę przypisać tylko jedno zdarzenie, zrobimy to za sekundę.
Natomiast w tym miejscu, w którym wyświetlałem console.log tutaj, to będę chciał zamienić go na socket.send.
W ten sposób możemy wysyłać coś do serwera i kiedy to wyślemy, to wykona się dokładnie ta funkcja. I pod
message będzie to, co prześlę.
Natomiast serwer tutaj nam odsyła coś, więc musimy nasłuchiwać na to, kiedy nam coś przyjdzie z serwera. I zrobimy
to w tym miejscu.
Socket.on, a w zasadzie nawet nie on, tylko addEventListener,
bo tak się przypisuje zdarzenia w przeglądarce, message i tutaj jest funkcja, w której będą przesłane z
serwera dane w formie data.
Ale to, co jest ważne, to jeżeli zrobisz console.log data, zobaczysz, co tam jest, to nie będzie od razu ten
odesłany string. Ten wysłany string znajdzie się pod kluczem
data. Czyli data data, albo może nawet msg napiszmy. Ok. I tyle wystarczy.
Czyli po odświeżeniu tej strony powinniśmy nawiązać połączenie z serwerem WebSockets,
kiedy coś wyślę.
Witaj! Pojawiło się nam to tutaj.
Czyli wszystko jest w porządku.
Serwer to powiększył na wielkie litery i nam odesłał. I to sobie wyświetliliśmy w tym miejscu.
Jak widzisz, wszystko działa poprawnie i połączenie nie jest skończone.
Możemy tutaj wysyłać dowolne rzeczy i wszystko będzie działać jak należy.
Bardzo ważne jest to, że mamy taki kanał komunikacji.
Gdybyśmy go chcieli zamknąć, to oczywiście również jest to możliwe.
Natomiast w tym przykładzie to jest już wszystko, a w lekcji kolejnej pokażę ci, jak skorzystać z biblioteki
io.js,
która działa zarówno po stronie serwera, jak i po stronie klienta.