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.
W tej lekcji pokażę ci, w jaki sposób możemy korzystać z procesów potomnych w Node.
I chociaż ta lekcja nie jest bezpośrednio związana z wdrażaniem do produkcji, a taki jest tytuł tego
rozdziału, to później będziemy korzystać z innych rzeczy, które pod spodem korzystają z tego, co będzie
tutaj.
A te przykłady, które z kolei ja ci pokażę, mogą się przydać tobie w przyszłości.
Więc przejdźmy sobie od razu na stronę dokumentacji.
Jak widzisz, jesteśmy w module child processes i tutaj będziemy mogli go sobie zainkludować w ten sposób.
Posiada on kilka metod.
Skorzystamy m.in. z metody spawn, ale także z metody exec.
Pokażę ci, na czym sprawa polega.
Przejdziemy zatem do edytora i od razu będę chciał tutaj sobie pobrać obydwie te funkcje i zapisać do nich referencje
w stałych. Za sekundę z nich skorzystamy.
Natomiast co będę chciał zrobić najpierw? Przejdziemy sobie tutaj do terminala i co to znaczy, że będziemy mogli uruchomić
zaraz w Node.js proces potomny? Procesem, już ci w kursie mówiłem, jest instancja dowolnego uruchomionego
programu. Czyli procesem może być zarówno ten terminal, w którym teraz jesteśmy, jak i np. polecenie ls,
które tutaj wpisujemy. Wykonaliśmy proces ls, on coś zwrócił do standardowego wyjścia, czyli stdout -
konkretnie to index.js - i się zakończył.
Podobnie będzie np. z pingiem. Jeżeli wpiszę ping google.com powiedzmy, to mamy proces, który cały czas
jest uruchomiony i jak widzisz, zwraca nam tutaj jakieś wartości. Mogę go zatrzymać Ctrl+C. Np. gdybyś
był na Windowsie, to tylko cztery takie pingi będą domyślnie puszczone.
Takie polecenie też zadziała.
I teraz ten proces się zakończył. Dlatego wyczyszczę ekran i spróbujemy taki proces uruchomić z poziomu
Node.
Na początek zrobimy to metodą exec i zobaczysz, jaka jest różnica pomiędzy nią a metodą spawn.
Tutaj musimy jako pierwszy parametr podać to, co chcielibyśmy wpisać w wierszu poleceń do wykonania.
Czyli skoro pisałam np. ls, to możemy to podać, ale ja chcę wpisać od razu ping.
Tylko chciałbym, żeby się mi wykonały cztery pingi, dlatego w Linuksie czy na Macu można wpisać
-c np. 4 i dopiero potem google.com.
Jeżeli będziesz w Windowsie, to wpisz po prostu ping google.com. Tutaj zobaczysz, że 4 takie pingi się wykonają i się
proces zakończy. Więc dokładnie to chcę tutaj wpisać.
Zatem taki proces chcemy uruchomić.
I tutaj mamy funkcję, która wykona się, kiedy ten proces się zakończy. Ona przyjmie error, jeżeli się pojawi
stdout, czyli jakby zbuforowane to, co zostanie do standardowego wyjścia wyrzucone.
I to, co do standardowego błędu.
Na czym sprawa polega?
Otóż ten proces wykonując się, jak widzisz, robił nam takie logi tutaj do standardowego wyjścia. Czyli kiedy
się zakończy ta funkcja, to będę to wszystko miał tutaj sklejone razem.
Jeżeli wystąpiłby błąd, to będziemy mieli tutaj obiekt błędu JavaScript.
Natomiast pod standard error mielibyśmy coś, jeżeli ten proces gdzieś u siebie w kodzie źródłowym korzystałby
ze standardowego wyjścia dla błędów.
No i teraz sprawdzimy sobie.
Jeżeli byłby błąd, czyli if error, to będę chciał go wyświetlić i zakończyć.
Natomiast w przeciwnym wypadku będę chciał wyświetlić stdout i stderr. Ok.
W ten sposób. Więc jeżeli teraz ten plik sobie wykonamy,
pamiętaj, że gdybyś był na Windowsie, nie dopisuj tego.
-4, -c4. Wykonamy sobie tutaj node index.
Musimy chwilę poczekać.
Zaraz ci powiem dlaczego. I mamy output. Czyli ten output tutaj to jest wyświetlony console.log, dokładnie
stdout.
Zatem metoda exec działa tak, że po pierwsze uruchomi nam proces, a po drugie będzie buforować wszystko to,
co ten proces będzie wrzucał do standardowego wyjścia i do standardowego błędu.
Natomiast wcale nasz proces jakby nie wisi, bo gdybym sobie tutaj zrobił console.log i napisał dalszy kod,
to możemy zobaczyć, że dalszy kod wykona się od razu, a to zostanie zwrócone dopiero później.
Czyli nie jest to synchroniczne i w żaden sposób nie blokuje.
Zanim jeszcze powiem, do czego to może być przydatne, to chciałbym pokazać ci teraz metodę spawn - w jaki
sposób ona
z kolei działa. Od razu ci powiem, że ta metoda zwróci nam stream. Dlatego możemy śmiało utworzyć sobie zmienną.
Ja ją nazwę ping i wywołamy sobie spawn.
I teraz to, co jest ważne, to tutaj podajemy nazwę tego programu. Czyli skoro tu wpisuję ping, to tutaj
to podaję, ale nie podaję już tych wszystkich parametrów, które były wyżej. Je podajemy w osobnej tablicy
jako stringi. Czyli -c
to będzie pierwszy. Kolejny z nich, który podawaliśmy - widzisz go u góry - to było 4.
Na Windowsie je pomiń. Podaj tylko ten, który podam jako ostatni. I ostatni będzie to google.com. To wszystko
zostanie odpowiednio wywołane.
I tak możemy sobie to zakończyć, bo mówiłem ci, że metoda spawn zwróci nam stream. A do streamów - i to wielokrotnie
już w tym kursie robiliśmy -
możemy przypisywać zdarzenia. Dlatego odwołamy się do ping i konkretnie do streamu, który jest wewnątrz,
czyli stdout. I teraz on data. Czyli za każdym razem, kiedy ten proces ping tutaj nam jedną linijkę wyrzucał
do standardowego wyjścia, to będziemy mieli właśnie tutaj. Standard output on data - będziemy mogli sobie
to skonsumować. Napiszemy data.
Co ciekawe, to będzie buffer, dlatego chcę to wyświetlić za pomocą console.log(data.toString).
Gdyby się pojawił jakiś błąd, to chcę zrobić dokładnie to samo. W naszym przypadku akurat to nie będzie
miało znaczenia.
Standard error on data i na końcu sobie przypiszemy jeszcze jedno zdarzenie.
Będzie to po prostu close. I to już możemy przypisać bezpośrednio do ping on close.
I tutaj zostanie przekazany kod, który jest wysyłany do procesu, kiedy ten proces się jakby kończy.
Dlatego napiszemy sobie tutaj coś takiego.
Proces zakończył się z kodem i tutaj zobaczymy, jaki to był kod. Zobaczysz, jaka jest różnica. W przypadku
exec czekaliśmy, aż to wszystko zostanie zbuforowane i nam zwrócone.
Zobacz, jak to będzie wyglądać w przypadku takiego streamu. Ale myślę, że już się domyślasz. Więc wpiszemy
node index. I zauważ, że ten ping nam się pojawia za każdym razem, kiedy coś zostanie wyrzucone
do tego standard input przez... czy standard output przez proces ping. I na końcu proces zakończył się z kodem 0.
Jeżeli mamy kod 0, to znaczy, że poprawnie zakończył się proces. Więc tak to wygląda. Metoda spawn, jak widzisz,
pozwala uruchamiać nam dowolny proces i działa to jako stream. Czyli jeżeli ten proces coś wyrzuca, to możemy
z tego skorzystać.
Podobnie moglibyśmy uruchomić metodę np. ls, która listuje pliki i zobaczyć, jakie pliki są w tym katalogu.
Natomiast teraz chcę ci pokazać, do czego tak naprawdę to mogłoby być przydatne, a w zasadzie tylko o
tym na moment opowiedzieć.
Mam nadzieję, że podobne przykłady przerabiałeś, więc zrozumiesz, co mam na myśli.
Nie wiem, czy kiedykolwiek korzystałeś z takiego automatora zadań, jakim jest Gulp.
Będę o nim jeszcze mówił pod koniec tego kursu.
Natomiast na eduweb.pl znajdziesz warsztat na jego temat.
Działa on w ten sposób, że korzysta z Node i możemy w nim sobie zautomatyzować pewne czynności, np. minifikację
kodu CSS czy JavaScript, automatyczne odświeżanie przeglądarki itd. I teraz podam ci konkretny przykład,
w jaki sposób ja w Node korzystałem sobie z procesów potomnych. Wkleję tutaj taki oto komentarz. I zatrzymajmy się u góry.
Potrzebowałem w Gulpie zrobić coś takiego, że najpierw zbudujemy całą stronę w HTML z poszczególnych
szablonów, a mogłem to zrobić poleceniem w terminalu, które bym tutaj musiał wpisać - jekyll build - i kiedy
to wszystko by się wykonało,
widzisz, mam tutaj na zielono, bo mam taki system jak jekyll. On pozwala z różnych takich szablonów tworzyć
kod HTML - gotową stronę.
Chciałem najpierw to wykonać, a kiedy ten proces się zakończy, to dopiero wtedy odświeżyć przeglądarkę.
No i miałem tutaj jakby w kodzie Node.js taki systemik napisany w Gulpie, który pozwalał mi odświeżać przeglądarkę.
Ale żeby wiedzieć, kiedy to się stanie, to musiałem sobie utworzyć taki proces potomny dla jekylla, który
to wykona, i będę miał informację, kiedy skończy. Konkretny kod wyglądał w ten sposób. Jeżeli nigdy nie
korzystałeś z Gulpa,
to może niewiele ci to powie.
Natomiast jeżeli korzystałeś, to zobaczysz, o co chodzi.
Czyli chciałem zbudować sobie, tak jak wspomniałem, HTML za pomocą jekyll build. I zrobiłem to w ten sposób,
że metodą spawn, wcześniej miałem zmienną cp, metodą spawn uruchomieniem sobie Jekylla, tak jak to zrobiliśmy
tutaj wyżej w przypadku ping. I jako jego pierwszy parametr podałem build, czyli to, co mamy w tym miejscu.
Dzięki temu te szablony zostały zbudowane już z poziomu jakby tego kodu Gulpa. Nie musiałem tego wpisywać w
terminalu. Natomiast w momencie, kiedy ten proces się zakończył, a widzisz że Node.js pozwolił mi przypisać
zdarzenie on close, mogłem się odwołać do browserSync.reload. Ten kod akurat miałem w tym Gulpie. Czyli żeby po
pierwsze zbudować te szablony, a po drugie wiedzieć, kiedy odświeżyć przeglądarkę, żeby nową stronę wyświetlić,
korzystałem sobie z takiego oto zapisu.
Jak zatem widzisz, procesy potomne mogą się przydać w różnych sytuacjach.
Nawet jeżeli teraz nie widzisz dla nich zastosowania, to być może w przyszłości przypomnisz sobie, że
w tym kursie o tym słyszałeś i rozwiąże to jakiś twój problem.
Dowolny proces możesz uruchomić z poziomu Node i możesz monitorować zarówno to, co on wyrzuca do standard output.
Widzisz, że ja np. tutaj tego nie robiłem, w ogóle mnie to nie interesowało. Interesowało mnie
to, aby wykonał jakąś robotę i dał mi znać, kiedy skończy, abym mógł przejść dalej.