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 nadbudujemy jeszcze trochę wiedzy z lekcji poprzedniej o procesie, ale przede wszystkim
o tym, jak możemy ze standard input i standard output jeszcze odczytywać dane.
Zazwyczaj jeżeli uczymy się programowania np. w C++, to większość tych programów, które piszemy, działają
właśnie w konsoli.
Dlatego chciałem ci pokazać, że w Node również jest to możliwe.
W tej lekcji skorzystamy z wbudowanego modułu Node, który nazywa się readline i możesz go znaleźć tutaj, w dokumentacji.
Nie ma on, jak widzisz, bardzo wielu metod, jest dosyć prosty w użyciu.
Dlatego będę go chciał teraz tutaj na samej górze zaimportować.
Taka linijka załatwi sprawę. I teraz będziemy chcieli utworzyć nowy interfejs. Tworzę sobie również stałą, nazwę
ją rl i odwołam się do readline.
Następnie do createInterface. I ta funkcja przyjmuje tutaj obiekt konfiguracyjny, któremu musimy podać
input i co ciekawe nie musi to być wcale standard output, to może być dowolny stream.
Już o streamach wiesz, dlatego może to być np. plik stworzony za pomocą fs.creatreReadstream.
Natomiast my tutaj podamy proces.stdin.
Znasz to już. I output: process.stdout
W ten sposób. Utworzyliśmy nowy interfejs i z niego będziemy mogli korzystać.
Teraz wkleję gotowy kod. Pokażę ci uproszczoną wersję tego, co widzieliśmy w lekcji poprzedniej.
Na procesie mówiłem ci, że w kolejnej lekcji będzie o tym trochę więcej.
Jak widzisz, znowu ten interfejs rl korzysta z EventEmittera, skoro możemy przypisywać zdarzenia. Jedno z takich
zdarzeń nazywa się line i możemy tutaj na jedną linijkę, bo po linijce będziemy odczytywać, czy właśnie
tutaj z standard input, czy z pliku, gdybyś tutaj podał plik, to po jednej linijce byłby odczytywany, będzie
wywoływana funkcja, która będzie zawierała tę linijkę od razu już sparsowaną na UTF-8 - nie będzie to buffer.
Więc możemy porównać, tak jak to robiliśmy w lekcji poprzedniej, czy np. wpisaliśmy exit,
jeżeli tak, to chcę zakończyć, odwołując się do rl.close.
Jeżeli nie, to chcę wyświetlić to, co wpisaliśmy. Korzystam tutaj z template stringu w
ECMAScript 6.
W ten sposób. I następnie korzystam z rl.prompt po to, aby jeszcze raz zapytać, czyli aby jeszcze raz wywołać
sobie to zdarzenie.
Zobaczmy, jak to będzie wyglądać.
Nic nam się nie pojawiło, ale widzimy, że proces jakby wisi. Możemy tutaj coś wpisać - cokolwiek.
No i widzimy - wpisałeś "cokolwiek" i teraz prompt pokazało nam taką oto strzałeczkę, więc możemy znowu coś wpisać.
"Coś".
I tak będzie w nieskończoność, chyba że wpiszemy exit i to się zakończy.
Czyli taki interfejs readline jest, jak widzisz, bardzo fajny i dużo prościej niż w lekcji poprzedniej możemy
z niego korzystać.
Natomiast teraz pokażę ci inną ciekawą metodę tego obiektu. Mianowicie zauważyłeś że prompt, jeśli byśmy
to raz jeszcze sobie wywołali - wpiszę "cokolwiek" - pokazuje nam taką oto strzałeczkę.
Natomiast gdybyśmy ją chcieli sobie skonfigurować. Zatrzymam to CTRL+C, to możemy to zrobić, korzystając
rl.setPropmpt.
I tutaj wpiszemy sobie to, co chcemy, aby się pojawiało.
Zapiszę to i raz jeszcze uruchomię. I teraz za pierwszym razem tego nie ma, ale za drugim razem już tak,
to zauważ, że za każdym razem będzie "wpisz coś",
nowa linia, którą wpisałem i trzy takie strzałeczki. Mogę coś wpisać i wiesz, że aż do exit będziemy taki kod
wykonywać.
Więc gdybyś tworzył taką aplikację command line interface, to możesz również z tego skorzystać.
Teraz będę chciał ci pokazać jeszcze jedną ciekawą metodę na zakończenie, która jest dostępna w readline.
I będzie to metoda question. Wkleję teraz gotowy kod. Na samej górze tworzę sobie tablicę z nagrodami do wygrania.
To 100 złotych, 1000, 2000 itd.
Następnie korzystamy z metody rl.question i pytamy tutaj "Wybierz sejf od 1 do 5".
To, co wpisze użytkownik i wciśnij Enter, pojawi nam się w tej funkcji pod answer jako string.
Dlatego będę chciał w console.log wyświetlić za pomocą template stringu ten string, czyli np. wpisaną dwójkę
sparsować za pomocą parseInt,
żebyśmy mieli prawdziwy number, a nie sring i następnie od tego odjąć jeden. Bo jeżeli ktoś wpisze jeden,
to chcę odwołać się do zero, czyli do pierwszego elementu tej tablicy.
Dlatego tutaj odejmuję jedynkę i na końcu robimy rl.close, aby ten proces się zakończył.
Jeżeli teraz sobie to wywołamy, widzimy "Wybierz sejf od 1 do 5". Wpiszmy np 3 i widzimy: "Wygrałeś 2000 złotych", czyli
dokładnie ten trzeci sejf nam się tutaj otworzył i mogliśmy zgarnąć tę kasę. Na sam koniec tej lekcji
pokażę ci jeszcze jedną ciekawostkę, bo być może wielokrotnie coś takiego już widziałeś, a nie wiesz, w
jaki sposób zostało stworzone, dlatego warto wiedzieć.
Pokażę ci, w jaki sposób możemy tutaj, w wierszu poleceń zrobić sobie ładowanie takie procentowe. Ja może
wrzucę tutaj od razu kod. Nie chcę tracić czasu na pisanie od zera, więc stworzyliśmy funkcję, która nazywa
się printPercentage i ją tutaj wywołujemy. I ona, co jest ważne,
zaczniemy od tego - będzie co 200 milisekund wywoływać samą siebie. Czyli chcemy, aby ona się wywoływała,
ale nie w nieskończoność.
Czyli jeżeli wcześniej gdzieś zrobimy return, tak jak jest tutaj, to już nie dojdziemy do tego momentu
i to się nie wykona. Kiedy go zrobimy?
Otóż mamy tutaj zmienną percentage.
I zauważ, że co te 200 milisekund będziemy dodawać do niej 5. Czyli później, kiedy ona się wywoła,
można powiedzieć po raz ostatni, to sprawdzimy, czy percentage ma już wartość 100.
Jeżeli tak, to będę chciał w naszym readline napisać "Zakończono wczytywanie" i poprzez return to zakończyć,
również korzystając tutaj z rl.close.
Mógłbym to oczywiście zapisać w dwóch klinikach rl.close i return.
To return jest po to, abyśmy nie doszli do tego momentu.
Zostawmy sobie to w ten sposób.
I teraz zauważ, co jest ciekawe.
Możemy odwołać się do readline, czyli bezpośrednio jakby do tego modułu tutaj zaimportowanego, a nie do tego interfejsu
i następnie do jego statycznej metody, która nazywa się clearLine. Mówimy, że chcemy wyczyścić ostatnią linijkę tutaj w terminalu
tego interfejsu rl, który mamy utworzony u góry.
OK. W ten sposób. Zero podajemy tutaj.
Dlaczego?
Otóż przejdźmy tutaj i znajdźmy clearLine. Ok.
I jak może zobaczyć, mamy takie parametry jak dir, jest to direction. 0 oznacza, że całą linię chcemy wyczyścić.
Bo możemy np. od kursowa w prawo albo od kursowa w lewo.
Następnie aby ten kursor przesunąć do lewej strony, to korzystam z readline.cursorTo.
I znowu podaję interfejs i zero, aby przesunąć go do początku linii, a następnie wyświetlam sobie
postęp. Ja może na razie to skasuję. I zobaczysz, po co to wszystko jest.
Jak widzisz, mamy coś takiego jak postęp. To nam będzie tutaj szaleć, dlatego że ten kursor jest w różnych
miejscach. Natomiast jeżeli właśnie za każdym razem będziemy go przesuwać do lewej strony, w ten sposób,
to będziemy mieli coś takiego jak postęp.
Mam nadzieję, że już powoli widzisz zalety takiego interfejsu readline.
To, co tutaj mamy, czyli wyświetlanie tych procentów, moglibyśmy sobie zapisać w zupełnie osobnym module i w taki
sposób go zapisać, że gdzieś później w twoim kodzie on się może przydać, kiedy będziesz wykonywał jakieś
operacje i będziesz chciał wyświetlać postęp wykonywania takich prac.
Tutaj zrobiłem to za pomocą setTimeout wyłącznie po to, abyśmy mogli to zasymulować. Podsumowując, jeżeli
będziesz chciał tworzyć jakieś czy to quizy, czy proste aplikacje, które będą zadawać jakieś pytania, na przykład
żeby stworzyć jakiś plik konfiguracyjny, to jak najbardziej możesz korzystać z bardzo łatwego w użyciu interfejsu readline.
Polecam ci również zajrzeć do jego dokumentacji, aby zobaczyć, jakie jeszcze metody tam się
znajdują.