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 jeszcze kilka rzeczy, które pomogą ci jeszcze lepiej zrozumieć to, w jaki sposób
Node.js radzi sobie z modułami. I wrócimy sobie w tym momencie do przykładu, który mieliśmy dwie lekcje temu, czyli
w pliku main robiliśmy require pliku add i następnie z tego korzystaliśmy, a w pliku add mieliśmy taki oto
kod.
I teraz jeżeli sobie wywołam plik main, to będziemy mieli błąd, bo chcieliśmy skorzystać ze zmiennej message,
która nie była zdefiniowana. Bo wspominałem ci, że ona jest prywatna w tym miejscu, dla tego pliku add.js.
Ale mógłbyś się zastanawiać, jak to działa, że to jest w ten sposób prywatne.
I teraz będę chciał to porównać do skryptu wykonywanego w przeglądarce internetowej.
Dlatego teraz do naszego katalogu 04 skopiuję sobie folder web. I w tym folderze web mamy bardzo podobny przykład.
Otóż najpierw mamy plik index.html, który uruchomimy w przeglądarce. I on ładuje sobie skrypt
add.js.
Ten skrypt zawiera dokładnie to, co już widzieliśmy wcześniej w przypadku Node.js.
Następnie ładuję plik main.js. I ten plik będzie wyświetlał console.log ("Moduł main.js"), następnie korzystał z
funkcji add i wyświetlał console.log message. Do tych zmiennych czy w zasadzie do tej funkcji i do tej
zmiennej będzie miał dostęp, bo one wcześniej zostały tutaj zdefiniowane, a ten plik jest wczytywany wcześniej.
Dlatego uruchommy sobie teraz ten plik. Przeciągnę go po prostu do przeglądarki. Ok, ten plik się uruchomił. Zobaczmy,
co mamy w konsoli.
Nic tutaj nie ma, czego byśmy się nie spodziewali.
Natomiast nas interesuje ta linijka, czyli moduł add.js. Jak możesz zobaczyć, w tej wersji
main miał dostęp do message, która została zdefiniowana w zupełnie innym pliku. I na pewno wiesz, że tak
jest w JavaScript, który jest wykonywany w przeglądarce,
jeżeli tworzymy zmienne w taki oto sposób. Czyli zakres zmiennych tutaj nie jest niczym ograniczony i
taka zmienna message stała się zmienną globalną, dlatego jest dostępna również w pliku main.js. Aby sobie
z tym poradzić,
musimy zamknąć takie oto zmienne w jakiejś funkcji. I zazwyczaj robimy taką samowywołującą się funkcję
anonimową i wszystko, co jest w środku, możemy sobie tutaj bez żadnego problemu wkleić.
I teraz zmienna message nie będzie dostępna w innych plikach, ale również funkcja add nie będzie dostępna
w tym pliku.
I tutaj po odświeżeniu będziemy mieli taki oto błąd.
Aby z tym z kolei sobie poradzić, to możemy w tym miejscu odwołać się do obiektu globalnego, a w przeglądarce
jest to window i możemy mu dodać tutaj dowolne właściwości. Napiszemy tutaj add. I chciałbym, aby add kierowało
na naszą funkcję. Znowu te nazwy są dowolne. Tutaj może się to nazwać inaczej, a tutaj musi się nazywać
tak, jak ta funkcja, bo referencje tylko przekazujemy.
Czyli w tym momencie message będzie prywatne, ale add będzie przypisane do window, czyli w pliku main będę
mógł napisać window add albo samo add,
dlatego że jest to obieg globalny i wszystkie jego właściwości i metody są dostępne globalnie.
W ten sposób zauważ, że wszystko działa.
Natomiast mamy błąd, że message nie jest zdefiniowane, czyli dokładnie taki sam błąd, jak możesz zobaczyć
tutaj w przypadku Node.js. Czyli widzimy, że musieliśmy sobie w jakiś sposób ograniczyć zakres tych zmiennych
taką oto funkcją. W Node jednak takiej funkcji nie widzisz, więc mógłbyś się zastanawiać, jak to jest, że
wszystko, co znajduje się w tym pliku, jest w nim zamknięte, a tylko to, co przypiszemy poprzez module.exports
pojawia się tam, gdzie wykonaliśmy require.
No i teraz ciekawa informacja jest taka, że my piszemy sobie moduły w takich plikach, ale Node.js zanim je wykona,
zanim przekaże je do silnika V8,
to oplata je taką podobną funkcją anonimową, jaką przed momentem widziałeś w wersji przeglądarkowej.
Ja teraz wkleję tutaj u góry,
jak taka funkcja wygląda, abyśmy mogli ją omówić.
Wygląda to w taki oto sposób. Czyli w miejscu, gdzie wpisałem nasz kod, będzie się pojawiał cały kod, który
my sobie napiszemy. Może ja go tutaj wkleję, żeby łatwiej było nam na to patrzeć.
Czyli wszystko, co my napisaliśmy, jest przez Node.js zawierane w takiej oto funkcji. Dlatego jeżeli
stworzę sobie poprzez var message jakąś zmienną, to ona nie jest w globalnym zakresie, bo jest ograniczona do
zakresu zmiennych tej oto funkcji.
Natomiast zauważ, że ta funkcja w tym miejscu jest definiowana i ona ma przyjmować kilka parametrów,
takich jak exports, require, module, filename i dirname.
I ona jest od razu wywoływana, a więc w tym miejscu te parametry musiałyby się pojawić. Ja później w tym
kursie pokażę ci, gdzie dokładnie w kodzie źródłowym Node znajduje się ta funkcja i jakie parametry są
tutaj przekazywane.
Natomiast mam na myśli tylko to, że aby tutaj pod exports nie było undefined, no to tutaj przy wywoływaniu
coś jej trzeba przekazać, jakiś obiekt, który nam tutaj wpadnie, ale na razie tutaj nic nie przekazujemy.
Zauważ przy okazji, że skoro my korzystaliśmy sobie z funkcji require, akurat nie w tym module, ale np. w main, który
tak samo będzie opleciony, to skąd ona się wzięła.
Otóż właśnie stąd, że wszystko zostało oplecione taką funkcją, która jako parametr przyjmuje require.
Jako drugi parametr więc tutaj coś musiałoby zostać przekazane, jakaś funkcja, która wpadnie tutaj pod
require. Ale mamy require, mamy module, z którego również korzystaliśmy.
Jest to jakiś obiekt, który ma właściwość exports, i ona na początku, jak pamiętasz, jest takim pustym obiektem.
Natomiast mamy tutaj również coś takiego jak samo exports i mógłbyś się zastanawiać, co to jest.
Otóż exports i module.exports to jest dokładnie to samo.
Natomiast tutaj gdybym chciał napisać samo exports równa się add, to pojawiłby nam się problem. I łatwiej będzie
go zobrazować w tym miejscu.
Mam nadzieję, że na tym etapie to rozumiesz. Ja takie koncepcje tłumaczę bardzo dokładnie w kursie JavaScript
od podstaw i JavaScript w praktyce. Exports w naszym przypadku tutaj jest to lokalna zmienna z tej funkcji. Ona będzie
kierować na coś, co zostanie przekazane tutaj, przy wywołaniu tej funkcji.
Czyli będzie to jakiś pusty obiekt, który gdzieś wcześniej został zdefiniowany.
Jeżeli chciałbym go nadpisać poprzez exports równa się add, to nie przypiszę do tego obiektu, który gdzieś tutaj
został przekazany tej funkcji add,
ale tylko nadpiszę sobie tutaj lokalną zmienną.
Natomiast jeżeli skorzystam z module, czyli obiekt, który został tutaj przekazany - i następnie odwołam się do
exports, to tak naprawdę przejdę już do tego obiektu, gdziekolwiek by on nie był, do jego właściwości
exports.
I dopiero ją nadpiszę funkcją add.
Wtedy to wszystko będzie działać.
Więc mógłbyś zapytać, po co nam tutaj taki skrót exports.
Bo gdybyśmy zrobili porównanie w ten sposób: module.exports równa się exports, to byłoby tutaj true.
To kieruje na dokładnie ten sam obiekt.
Natomiast taki skrót jest nam dodany tutaj tylko po to,
gdybyśmy chcieli nie nadpisywać całego tego exports, ale coś do niego dodawać. Bo mówiłem ci, że na początku
module.exports to jest taki pusty obiekt.
A skoro jest to pusty obiekt, to możemy do niego dodawać różne rzeczy.
Czyli module.exports to jest taki obiekt.
Samo exports skieruje na ten obiekt.
Czyli mógłbym tutaj napisać po prostu exports.
Kropka.
I do tego obiektu bym coś dodawał.
Jeżeli tutaj bym napisał add i skierował na to funkcję naszą add, to bez problemu by nam to zadziałało.
Bo poprzez exports nie nadpisuję tej lokalnej zmiennej, ale wchodzę jakby do tego obiektu
i dodaję mu nową właściwość.
Tylko że wtedy w pliku main, jeżeli wykonamy require, to zostanie nam cały ten obiekt zwrócony i on wewnątrz
dopiero miałby add.
Czyli przy wywołaniu naszego add, pod tą stałą musielibyśmy pisać add
albo tutaj po require, po kropce moglibyśmy się odwołać do add i wtedy tylko tamta właściwość zostałaby wyłuskana
do tej stałej. Mam nadzieję, że to rozumiesz.
Tak naprawdę twórcy Node moim zdaniem niepotrzebnie nam dają taką możliwość skracania sobie poprzez exports
zapisu module.exports, bo musimy to później zrozumieć i tak jak ja w tym momencie muszę ci to
wytłumaczyć i łatwo jest popełnić później błąd, jeżeli korzystamy raz z exports, a raz module.exports.
Dlatego ja polecam ci zawsze korzystać z takiego oto zapisu, który widzisz w tym miejscu, czyli module.exports.
Tutaj możesz sobie to nadpisać czym tylko chcesz i nie będzie żadnego problemu. Natomiast jeżeli korzystasz
z samego exports, to nie możesz tutaj przypisać znaku równości, tylko musisz do jakiejś właściwości najpierw
się odwołać w taki oto sposób. Mam nadzieję, że dobrze to zrozumiałeś.
No i teraz chciałbym ci pokazać jeszcze dwie rzeczy, które tutaj się znajdują. Bo skoro wiemy, że exports
i module.exports służą nam do eksportowania jakiejś funkcji czy innych danych, require jest to funkcja tutaj
przekazana, to omówmy jeszcze, czym jest zmienna filename oraz dirname.
Otóż możemy z nich skorzystać.
Może zrobimy sobie to w tym głównym module.
On też jest oplatany, tak jak ci mówiłem, taką funkcją i pokażę ci, co te zmienne w sobie kryją.
Może od razu w console logu napiszemy w ten sposób: Ścieżka do pliku to - i tutaj dodamy zmienną filename,
czyli, jak widzisz, ona przechowuje całą ścieżkę do pliku, który wykonaliśmy. W naszym przypadku będzie to
main.js, ale w tym pliku byłoby to add.js.
Wrócimy tutaj i następnie ścieżka do katalogu to jest dirname. Wywołajmy sobie plik main raz jeszcze. Mamy jakiś błąd.
Message is not defined. Rzeczywiście to sobie wykomentujmy i zobaczmy. Ścieżka do pliku
i tutaj mamy pełną ścieżkę do pliku, który uruchomiliśmy. I następnie ścieżka do katalogu - jest tutaj pełna
ścieżka do katalogu.
Czyli jak widzisz, możemy z takich zmiennych korzystać. Jeszcze to w tym kursie robić będziemy. I zobaczyłeś wszystko,
co ta funkcja, dla nas niewidoczna, oplatająca zawsze nasz kod, zawiera.
Teraz już to rozumiesz, więc na sam koniec pokażę ci jeszcze tylko jeden trik.
Gdybyś w danym module chciał sprawdzić, czy został on wywołany za pomocą node, np. main -
w ten sposób, tak jak ten plik - czy został on zaimportowany za pomocą require, to możesz skorzystać
z takiego zapisu, mianowicie require.main, czyli require jest to funkcja, ale ma ona właściwość main,
która kieruje na moduł. I w tym momencie jeżeli require.main jest równe module, to znaczy, że jesteśmy
w pliku, który został wywołany za pomocą node, a jeżeli tutaj będzie false zwrócone z takiego oto zapisu, to oznacza,
że dany moduł,
gdybyśmy to wstawili tutaj, został nie wywołany za pomocą node, ale został wywołany za pomocą require.
Więc tutaj możemy zapytać, czy to główny moduł i wywołajmy to sobie. I widzimy
odpowiedź "tak".
Natomiast w innych plikach mielibyśmy tutaj false i w tym przypadku pojawiłoby nam się "nie".
Ostatnia rzecz, o której prawie bym zapomniał, to fakt, że Node za każdym razem, kiedy korzystamy z funkcji
require, zapisuje w pamięci podręcznej moduły, które importujemy.
Jest to bardzo ważne i ma pewnego rodzaju konsekwencje, o których chciałbym ci teraz powiedzieć. Natomiast
pierwsza z nich jest to dobra wiadomość, dlatego że jeżeli tutaj korzystaliśmy sobie z require add, a mielibyśmy jeszcze
wiele innych modułów, które byśmy tutaj inkludowali, wyobraź sobie, że pod spodem byśmy zainkludowali moduł
calculator, który mieliśmy wcześniej, i on również korzystałby z require add, to
jeżeli raz już to zrobiliśmy, to za każdym kolejnym wywołaniem właśnie takiego zapisu,
nawet jeżeli tutaj będzie inna ścieżka, bo ten moduł będzie w innym podkatalogu - mam na myśli moduł np. calculator,
który będzie do tego modułu się odwoływał, to nie będzie drugi raz ten plik odczytywany, ale z pamięci podręcznej
będzie wczytany w to miejsce. Czyli nawet jeżeli w wielu plikach wielokrotnie do tego samego modułu
się odwołujemy, to on tylko raz będzie tak naprawdę wczytany. Ale ma to swego rodzaju konsekwencje i warto
o nich wiedzieć. Dlatego teraz chciałbym ci pokazać taki prosty przykład, w jaki sposób może to wyglądać.
Utwórzmy sobie na szybko moduł, który nazwę sobie calculator. I chciałbym, żeby on się znajdował w katalogu 04.
I tutaj zrobimy sobie dokładnie coś takiego, jak mieliśmy w tym miejscu. I teraz zauważ, że inkludujemy sobie tutaj poprzez
require naszą funkcję add i chciałbym się odwołać do
add.
Czyli tak naprawdę odwołamy się do funkcji, która znajduje się w tym miejscu.
W JavaScript funkcje są obiektami, więc możemy dodawać im różne właściwości. W tym przypadku będzie to tylko,
aby ci pokazać, o co chodzi. Napiszemy tutaj number, np. 1. I teraz zrobimy sobie const calculator i będę
chciał tutaj zainkludować moduł, który przed momentem utworzyłem.
Zauważ, że ten moduł inkluduje sobie u siebie poprzez require add i za pomocą module.exports, powiedzmy, że wyeksportuje
taki obiekt, który w środku będzie miał add i będzie to kierowało na tę funkcję. Czyli w miejscu, w którym ja
sobie raz już wykonałem require add,
cała ta funkcja czy cały ten moduł został wyeksportowany,
czyli funkcja add. Następnie do tej funkcji dodałem właściwość number równą 1 i później zaimportowałem
calculator, który znowu odwołał się do require add. I tym razem już z pamięci podręcznej została tutaj wczytana
cała ta funkcja, cały ten moduł. I on wyeksportował
kolejny jakby moduł od siebie, który kieruje na tę samą funkcję. Mam nadzieję, że jest to jasne. I zauważ,
co stanie się, jeżeli teraz odwołam się do calculator. Zrobimy sobie to w console logu add, bo pamiętaj, że w ten
sposób to wyeksportowałem.
I do number.
Może te inne console logi sobie na tę chwilę usuniemy, aby nam nie przeszkadzały.
Przejdziemy tutaj i wpiszemy node main i zauważ, że mamy tutaj jedynkę, a to oznacza właśnie to, o czym
mówiłem wcześniej, że te moduły nie są od nowa wczytywane, bo gdyby tak było, to zauważ, że tutaj nigdzie
do tej funkcji add nie dostawałem jedynki, nie byłoby problemu. Natomiast skoro są wczytywane z pamięci podręcznej
i przekazywane przez referencje, to w taki oto sposób to wygląda. I przy bardziej zaawansowanych modułach,
gdzie będziesz miał jakieś inne obiekty, warto zdawać sobie z tego sprawę, że może być tak, iż w jednym
miejscu coś zostanie dodane do takiego modułu, a chwilę później zostanie on gdzieś zaimportowany za
pomocą polecenia require
i będzie to zmienione, chociaż w oryginalnym pliku tego nie było widać, aby tutaj coś było dodawane.
Ok.
Mam nadzieję, że w tych trzech lekcjach dobrze zrozumiałeś, w jaki sposób działają moduły w Node.js, jak możemy
je tworzyć. Jeszcze będziemy wielokrotnie z nich korzystać.
Natomiast w lekcji kolejnej pokażę ci, jak możemy importować moduły wbudowane w Node.js.