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 bardzo ważny temat, mianowicie debugowanie kodu.
To, co masz przed oczyma, jest to prosty serwer HTTP, który utworzyliśmy w jednej z poprzednich lekcji.
Teraz go będę chciał uruchomić za pomocą node index, żeby sprawdzić, czy wszystko działa jak należy.
Zobaczmy. Jak najbardziej, wszystko się nam poprawnie wyświetla.
Natomiast teraz chciałbym zrobić jedną ciekawą rzecz.
I co jest ważne, to również możesz to robić w przypadku kodu JavaScript pisanego dla przeglądarek, bo
większość przeglądarek to obsługuje, jeżeli o tym nie wiedziałeś - mianowicie wpisać sobie debugger. Mogę
wpisać coś takiego.
Nie jest to błąd w JavaScript, bo jest to odwołanie do jakiejś po prostu zmiennej. Natomiast ta zmienna
nie istnieje.
Jeżeli coś takiego zrobimy, zatrzymam sobie ten serwer i uruchomimy ten skrypt w specjalnym takim trybie
do debugowania, to zatrzymamy się w tym miejscu, w którym jest debugger. Ale to zobaczysz za moment.
Na razie przejdziemy na stronę debuggera na nodejs,
czyli w dokumentacji. Możesz zobaczyć, że możemy dowolny skrypt uruchomić w trybie debugowana za pomocą node debug
i tutaj nazwa skryptu.
No więc zróbmy sobie to.
Wpiszmy node debug i nazwa naszego skryptu index.js.
Zauważ, że debugger zatrzymał się na pierwszej linijce akurat nie dlatego, że wpisałem gdziekolwiek to
słowo kluczowe debugger.
Ono nie było aż tak istotne, natomiast zawsze zatrzyma się na pierwszej linijce kodu.
Ten debugger nie wygląda najlepiej, ale zaraz do tego przejdziemy.
Mianowicie co chciałbym zrobić?
Przejść dalej. I dalej możemy przejść, wpisując tutaj w tym interfejsie, który nam się pojawił,
c jak continue. Wciskam sobie Enter i przejdziemy dalej.
Widzimy serwer uruchomiony pod adresem localhost, czyli zaglądając do naszego kodu, jest wszystko w porządku.
Cały kod się wykonał. Bo ta funkcja wykona się dopiero, jak ktoś się podłączy i wtedy chciałbym tutaj
zrobić debuggera.
Dlatego odświeżymy stronę.
Zauważ, że serwer wisi. Nie otrzymał odpowiedzi, bo zatrzymaliśmy się w miejscu debugger. I dopiero teraz mogę
sobie wszystko sprawdzić, co tutaj się dzieje.
To co jest ważne, w dowolnym momencie możemy wpisać repl i zostaniemy przeniesieni do interfejsu REPL, w którym
możemy wszystko sprawdzić. Czyli mogę sprawdzić, np. w tym miejscu jesteśmy, jaka jest zmienna body.
Czy to była strona główna, czy jakiś inny adres. Więc wpiszemy sobie tutaj body.
Wyświetli nam się to i widzimy, że jest to strona główna. Czyli ten repl pozwala nam tutaj jakby wchodzić
w interakcje z kodem, który się zatrzymał.
Zauważ, że serwer ciągle wisi, bo nie otrzymał odpowiedzi.
Ctrl+C pozwoli z niego wyjść i będziemy mogli przejść dalej.
I teraz mamy kilka opcji. Albo mogę wcisnąć s, tzn step in, czyli wejść głębiej do kodu, albo o - to jest step out - natomiast
nie będę tego robił, bo zaraz pokażę ci to w trochę lepszym interfejsie. Albo mogę znowu wcisnąć c, czyli
continue. Wcisnąłem c,
przeszliśmy dalej i ta funkcja się zakończyła.
I zauważ, że serwer otrzymał odpowiedź. Czyli możemy w ten sposób debugować, chociaż jest to nieco toporne.
Zatrzymam to Ctrl+C
raz jeszcze. I teraz pokażę ci lepszy na to sposób. Istnieje specjalny moduł, który możemy globalnie zainstalować,
nazywa się Node Inspector. Więc mógłbyś sobie wpisać npm install -g node-inspector.
I jeżeli go zainstalujesz, to będziesz miał tutaj w wierszu poleceń do dyspozycji node-debug, a więc
takie polecenie i możesz z niego skorzystać.
Natomiast spłatał nam ten Node Inspector figla tutaj w przypadku nagrywania tego kursu. Wtedy, kiedy chciałem
ci to pokazać,
to nie działa to z najnowszą wersją Node. Musiałbym się cofać do starszej wersji Node, żeby pokazać ci, jak on działa.
Ale jest lepszy sposób na to.
Mianowicie od kilku wersji Node wspiera domyślnie prawie identycznego inspektora, bo mówimy tutaj tak
naprawdę o narzędziach deweloperskich przeglądarki Chrome.
Zaraz zobaczysz, jak to wygląda.
Więc skoro bez instalacji takiego modułu możemy tak naprawdę z niego skorzystać,
jest to postać bardzo podobna, to pokażę ci, jak to zrobić.
Niemniej jednak jeżeli jesteś ciekaw, spróbuj skorzystać z tego w ten sposób, jak pokazałem przed momentem.
Czyli zainstaluj sobie globalnie tego Node Inspectora.
Niemniej jednak ja pokażę ci teraz sposób natywny w Node.
Wystarczy, że bez instalacji czegokolwiek wpiszemy node i następnie --inspect
--debug.
To sprawi, że zatrzyma się wykonywanie naszego kodu na pierwszej linijce, tak jak zrobił to przed momentem
ten można powiedzieć toporny debugger Node. I następnie nazwa skryptu, czyli index.js.
Zauważ, że mamy tutaj informację, iż pod takim adresem został uruchomiony specjalny inspektor.
Ten adres muszę skopiować i otworzyć go w przeglądarce Chrome.
To jest bardzo ważne, żeby mieć przeglądarkę Chrome, najlepiej najnowszą wersję. I otworzy nam się taki
oto debugger.
To co jest ważne, to jeżeli kiedykolwiek debugowałeś JavaScript w przeglądarce Chrome, to będziesz doskonale
wiedział, jak się tutaj poruszać.
Zrobię mu trochę więcej miejsca i zauważ, co się dzieje. Od razu zatrzymaliśmy się na pierwszej linijce naszego
kodu i mamy tutaj to, o czym mówiliśmy w całym tym kursie, czyli że nasz kod jest oplatany taką oto funkcją,
która się sama wywołuje i są do niej przekazywane odpowiednie parametry.
Tutaj na własne oczy zobaczyć to można, no bo w naszym pliku nigdzie tego nie ma.
Zaczynamy od linijki require("http"). No i ona rzeczywiście tutaj się znalazła. I teraz mamy tę kontrolki, które
widać tutaj. Przed momentem w tym topornym debuggerze
powiedziałem ci, że mamy taką funkcję jak na przykład o.
Jeżeli byśmy wpisali o, to byśmy wykonali step out. Jeżeli byśmy wpisali s, to byśmy wykonali step in.
Dokładnie to tutaj można zrobić za pomocą tych kontrolek.
I teraz co to oznacza?
Pierwsza linijka mówi nam require, czyli polecenie require. Od razu mi tutaj dymek pokazuje, w którym pliku
się to znajduje.
Jeżeli zatem kliknę sobie Step into next function call, to zauważ, że przeniosło nas do pliku internal/module. I ja pokazałem
ci, gdzie te pliki znajdują się na GitHubie w kodzie źródłowym Node.js.
Zauważ, że tutaj możemy krok po kroku zobaczyć, co dzieje się w momencie, kiedy nasz kod jest wykonywany.
Mogę sobie tak przeskakiwać. Jesteśmy teraz w return, więc zobaczmy, co będzie dalej. A dalej wracamy do
naszego modułu.
Wyskoczyliśmy i jesteśmy w kolejnym pliku.
Nie jest to nasz moduł index.js, tylko plik module.js i jesteśmy w tym miejscu. I tak możemy krok po
kroku prześledzić wszystko, co dzieje się w tym środowisku JavaScript,
zanim wrócimy do naszego index.js do wykonania kolejnej linijki. Teraz jesteśmy w jeszcze innym pliku.
Natomiast gdybyś chciał z tego wyskoczyć, to możesz tutaj dać step out.
To samo mógłbyś zrobić w tym pierwszym debuggerze, który ci pokazałem na początku tej lekcji, za pomocą odpowiednich
poleceń.
Ale tam nie wygląda to tak ładnie. Więc wyskoczymy sobie raz jeszcze. Jesteśmy tutaj, w internal/module raz
jeszcze i wróciliśmy do naszego pliku index.js.
Mamy już zaimportowane przez require tutaj http. Natomiast to, co jest bardzo ważne, to po prawej stronie
widzimy wiele cennych informacji, m.in. lokalne zmienne, które są dostępne w naszej funkcji.
Jest to właśnie dirname czy filename, a także exports -
to, co zostało przekazane w tym miejscu.
Dodatkowo widzimy np. http, bo już mamy taką zmienną, a w zasadzie stałą, utworzoną po wykonaniu tej pierwszej
linijki. I możemy sobie tutaj zajrzeć, co w środku się znajduje.
Ja jednak chcę przeskoczyć dalej i zauważ, że wskoczymy do pliku http.js, do takiego miejsca return.
Więc jeżeli skoczymy jeszcze jeden krok dalej, to już będziemy w kolejnym pliku.
W ten sposób naprawdę możesz świetnie uczyć się, jak pod spodem działa Node.js.
Gdybyśmy jednak chcieli nie po kroku przeskakiwać, tak jak teraz, ale w większych takich krokach, wykonywać całe
funkcje, to możemy tutaj korzystać z tej kontrolki Step over. Ok. Ale z tego pliku sobie może wyskoczymy.
Jeszcze raz chciałbym wrócić do naszego.
Teraz jesteśmy tutaj i wybiorę sobie właśnie Step over.
Zakończyliśmy. Jesteśmy na końcu. I taką pauzą czy play - tym przyciskiem - możemy to wszystko puścić.
Ok.
Cały nasz skrypt się wykonał, ale chciałbym ci przypomnieć, że ja wpisałem w pewnym miejscu debugger. I ten debugger
zatrzyma się, kiedy ta funkcja się wykona, a ona się wykona dopiero wtedy, kiedy ktoś się podłączy.
Dlatego spróbujmy tutaj odświeżyć.
Zauważ, że serwer wisi dlatego, że przeglądarka nie otrzymała odpowiedzi i widzimy, że dokładnie w miejscu
debugger się zatrzymaliśmy. To, co jest niezwykle istotne, to możemy sobie z boku podejrzeć na przykład jaką
wartość ma zmienna body, a także jakie mamy tutaj jeszcze inne zmienne, np. status: 200.
I teraz mogę krok po kroku przeskakiwać za pomocą tej strzałki.
Jeżeli kliknę jeszcze raz, to przejdziemy do modułu http.server, tam gdzie to wszystko będzie sprawdzane.
Ja bym chciał z tego wyskoczyć.
Jesteśmy tutaj, a za pomocą tego przejdziemy dalej, przeskakując tę funkcję. Zauważ - jesteśmy tutaj,
nie wchodziliśmy jakby do tego pliku, tylko przeskoczyliśmy dalej i przeglądarka nadal czeka, bo nigdy
nie doszliśmy do res.end.
Możemy przeskakiwać, sprawdzać, co tutaj się dzieje. I teraz jeśli przeskoczę do res.end, to zauważ na
tym kółeczku, że wreszcie nam się to wczyta. Wyskoczyłem z tej funkcji.
I rzeczywiście odpowiedź została tutaj wysłana.
Node Inspector, który nie działa z tymi najnowszymi wersjami Node na chwilę obecną, wygląda niemal identycznie
jak to, co widzisz tutaj.
Niemniej jednak zachęcam cię, abyś spróbował go uruchomić.
Jeżeli nie, to uruchom takiego debuggera, jak ja teraz ci pokazałem. Jak widzisz, świetna sprawa.
Natomiast teraz pokażę ci jeszcze jedną rzecz. Otóż możesz zamiast wpisywać w kodzie debugger, to możesz
stawiać sobie break pointy dopiero tutaj.
Czyli możemy tutaj nacisnąć np. na linijkę ósmą, połączymy się tutaj raz jeszcze.
Widzisz, znowu wisimy. I tym razem nie zatrzymaliśmy się na debugger, ale w linijce 8, bo postawiłem tutaj
break point. I znowu mogę wszystko analizować albo kliknąć play, żeby przejść dalej.
Jeżeli to wybiorę, to zatrzymamy się w miejscu, gdzie było słowo debugger. Czyli z tego słowa w ogóle w kodzie
korzystać nie musisz.
Na koniec tej lekcji chcę ci jeszcze przypomnieć, że możesz korzystać z obiektu console.
Robiliśmy to wielokrotnie, na przykład robiąc console.log, czy console.time i console.timeEnd. Natomiast jest tutaj
jeszcze kilka ciekawych opcji. Console.info to jest tylko alias dla log, to jest dokładnie to samo. Tak samo
jak console.warn to jest alias dla console.error. Natomiast error działa w ten sposób, że będzie do standardowego
wyjścia dla błędów, czyli stderr, wysyłać nam wszystkie błędy. W naszym przypadku byłoby to tutaj, ale
być może pamiętasz, jak mieliśmy lekcję o streamach, gdzie pokazywałem ci, że można stworzyć własny obiekt konsoli
i tam standard error mogliśmy podać jako dowolny stream, więc wtedy console.error będzie tam właśnie
wysyłało takie błędy.
Ja natomiast na koniec chcę ci pokazać, w jaki sposób działa console.trace.
Jest to bardzo fajna rzecz, dlatego wrócimy sobie do naszego kodu i w dowolnym miejscu w swoim kodzie możesz
sobie wpisać
console.trace i podać tutaj string, na przykład powiedzmy, że jest to zapytanie http. Bo wiemy, że tutaj
będzie ta funkcja wtedy obsługiwana. Uruchomimy node index. Kiedy ktoś się podłączy, to nam się to wykona.
I zauważ, że to nie jest żaden błąd, chociaż tak może wyglądać, dlatego że kiedy nam konsola tutaj zgłasza
błędy, to też nam wyświetla taki stack trace.
Natomiast jeśli pamiętasz lekcję, w której mówiłem o jednowątkowej pętli zdarzeń i na prezentacji pokazywałem ci
stos, czyli stack, to tutaj widać, jak ten stack tak naprawdę wygląda.
Ja tutaj wpisałem trace zapytanie http i możemy od samego dołu zobaczyć, jak to wszystko na tym stacku
było układane. Bo w prezentacji pokazałem to w dużo bardziej uproszczonej formie. Czyli na samej górze
jest nasz index.js, ale na samym dole jest np. http_common.js.
Ten plik wywołał jakąś funkcję, która z kolei jest w pliku http_server. Widzimy dokładnie, w których linijkach.
Ten z kolei skorzystał z events, później mieliśmy znowu events.js i dopiero nasz plik.
Zatem console.trace pozwala nam wyśledzić, jak dokładnie wyglądał stos w momencie, kiedy wykonaliśmy właśnie
console.trace.
Czasami może to się okazać przydatne, natomiast wszystko to możesz również prześledzić, jak widziałeś,
w tym Node debuggerze, który przed momentem mieliśmy aktywny.
Jeśli zatem natrafisz na jakieś problemy w swojej aplikacji i nie będziesz potrafił sobie z nimi poradzić,
to spróbuj skorzystać z debuggera, które pokazałem ci w tej lekcji.