Czym właściwie jest Node
Node.js to program, który instalujesz na komputerze i który uruchamia pliki JavaScript. To najprostszy opis i jest trafny. Gdy wpisujesz node script.js, Node czyta plik, przekazuje go silnikowi V8 od Google (silnikowi JavaScript z Chrome) i wykonuje, z dużą biblioteką dodatkowych API doklejoną do rzeczy, których V8 sam nie potrafi.
V8 umie wykonywać JavaScript. Nie umie otworzyć pliku, nasłuchiwać na gnieździe TCP, uruchomić procesu ani odczytać zmiennej środowiskowej. Node dostarcza to wszystko, napisane w C++, i udostępnia twojemu kodowi JavaScript jako wbudowane moduły.
node --version
node script.js
Node nie jest więc językiem. Nie jest też frameworkiem. To środowisko uruchomieniowe: V8 plus biblioteka standardowa plus system modułów plus pętla zdarzeń. To wszystko.
Pierwszy skrypt
Każdy plik .js jest poprawnym programem Node. Żadnego boilerplate'u, żadnej funkcji main:
console.log działa tak samo jak w przeglądarce. Template literals, Date, tablice, promisy: wszystkie znane ci funkcje języka pochodzą z V8 i zachowują się identycznie. W Node zmienia się to, co jest dostępne wokół języka.
Globalne obiekty dostępne tylko w Node
Przeglądarka ma window, document, localStorage, fetch. Node ma inny zestaw globalnych obiektów, dopasowany do roli środowiska po stronie serwera:
processto działający proces Node. Zawiera zmienne środowiskowe (process.env), argumenty wiersza poleceń (process.argv) i metody do zakończenia działania (process.exit(1)).__filenamei__dirnamedają bezwzględną ścieżkę bieżącego pliku i jego folderu. (W modułach ES nie istnieją, zamiast nich używaszimport.meta.url.)globalto obiekt najwyższego poziomu, odpowiednikwindoww Node.
Nie ma document ani window. Jeśli spróbujesz ich użyć, dostaniesz ReferenceError. To zwykle pierwszy sygnał, że biblioteka została napisana dla przeglądarki i nie zadziała w Node bez zmian.
Argumenty wiersza poleceń i środowisko
Duża część zastosowań Node, czyli narzędzia CLI, skrypty budujące i serwery, wymaga odczytu argumentów i zmiennych środowiskowych. Oba są dostępne w process:
process.argv to tablica: pierwsze dwa elementy to ścieżka do programu Node i ścieżka skryptu, więc właściwe argumenty zaczynają się od indeksu 2. process.env to zwykły obiekt ze zmiennymi środowiskowymi. Odczytywanie z niego NODE_ENV, PORT czy kluczy API to standardowa praktyka.
Wbudowane moduły
Node ma bibliotekę standardową dostępną przez require (CommonJS) lub import (ESM). Nazwy modułów zaczynają się od node:, żeby było jasne, że są wbudowane:
Te, po które będziesz sięgać najczęściej:
node:fs: odczyt i zapis plików. Wersja z async/await tonode:fs/promises.node:path: łączenie, rozwiązywanie i parsowanie ścieżek plików niezależnie od systemu.node:http/node:https: budowanie serwerów HTTP i wysyłanie żądań.node:url: parsowanie i tworzenie adresów URL.node:os: informacje o komputerze, na którym działa program.node:crypto: haszowanie, losowe bajty, szyfrowanie.
Tych modułów nie instalujesz. Są częścią Node. Wszystko inne pochodzi z npm.
Pętla zdarzeń w skrócie
Node uruchamia twój JavaScript w jednym wątku, a mimo to obsługuje wiele rzeczy naraz. Sztuczka polega na pętli zdarzeń. Gdy wywołujesz coś asynchronicznego, na przykład odczyt pliku, żądanie HTTP czy timer, Node przekazuje właściwą pracę systemowi operacyjnemu (lub swojej puli wątków) i wykonuje kod dalej. Gdy praca się kończy, callback trafia do kolejki, a pętla odbiera go, gdy bieżący kod skończy działanie.
Wypisana kolejność to 1, 4, 2, 3. Najpierw wykonuje się kod synchroniczny. Potem mikrozadania (rozwiązane promisy). Potem timery. Dlatego wolna pętla obciążająca procesor blokuje cały serwer: dla twojego kodu jest tylko jeden wątek. Współbieżność w Node dotyczy operacji wejścia/wyjścia, a nie obliczeń.
Malutki serwer HTTP
Nagroda za to wszystko: działający serwer WWW mieści się w kilku liniach:
Bez frameworka, bez zależności. createServer przyjmuje funkcję, która wykonuje się przy każdym żądaniu, a listen sprawia, że pętla zdarzeń zaczyna obsługiwać przychodzące połączenia. Prawdziwe aplikacje używają do tego Express lub Fastify, ale pod spodem to ten sam wbudowany moduł http.
Node kontra przeglądarka
Warto jasno powiedzieć, co się przenosi, a co nie:
| Działa w obu | Tylko Node | Tylko przeglądarka |
|---|---|---|
Funkcje języka (klasy, promisy, async/await) | fs, http, process, __dirname | window, document, DOM |
console.log | CommonJS require / dziwactwa ESM specyficzne dla Node | localStorage, sessionStorage |
fetch (Node 18+) | Dostęp do systemu plików i gniazd sieciowych | Zdarzenia użytkownika, renderowanie |
setTimeout, setInterval | Procesy potomne, strumienie | History API, navigator |
Nowoczesny Node przejął kilka API z przeglądarki, takich jak fetch, URL, AbortController czy structuredClone, więc różnica jest mniejsza niż kiedyś. Ale DOM do Node nie trafi, a system plików do przeglądarki też nie.
Node kontra Deno kontra Bun
Node jest domyślnym wyborem, ale nie jest już jedynym środowiskiem JavaScript. Alternatywy to Deno i Bun: Deno stworzył pierwotny twórca Node, a Bun nowszy zespół skupiony na szybkości. Uruchamiają JavaScript (i natywnie TypeScript), mają wbudowane narzędzia, takie jak test runnery i bundlery, i różnią się od Node obsługą modułów, uprawnień i instalacji pakietów.
Do nauki JavaScript Node wciąż jest miejscem, gdzie żyje dokumentacja, tutoriale i oferty pracy. Pojęcia takie jak pętla zdarzeń, moduły i wbudowane API niemal w całości przenoszą się na inne środowiska. Naucz się najpierw Node, a po pozostałe sięgnij, gdy projekt będzie tego wymagał.
Szybkie uruchamianie skryptów
Kilka sposobów na faktyczne wykonanie kodu podczas pracy:
# Run a file
node script.js
# Run a one-liner
node -e "console.log(2 ** 10)"
# Open the REPL (interactive prompt)
node
# Watch a file and re-run on save (Node 18.11+)
node --watch script.js
REPL to wygodny brudnopis, gdy chcesz sprawdzić, co zwraca dana metoda, bez tworzenia pliku. --watch przydaje się podczas pracy nad kodem: zapisujesz plik, a Node automatycznie uruchamia skrypt ponownie.
Dalej: obsługa błędów
Uruchamianie kodu to jedno, a radzenie sobie z sytuacją, gdy coś pójdzie nie tak, to drugie. Odczyty plików się nie udają, żądania HTTP przekraczają limit czasu, parsowanie JSON rzuca błędy. Następny rozdział dotyczy try/catch, typów błędów i wzorców radzenia sobie z tym, co się psuje, a w programie Node prędzej czy później psuje się wszystko.
Najczęściej zadawane pytania
Czym jest środowisko uruchomieniowe Node.js?
Node.js to program, który uruchamia JavaScript poza przeglądarką. Łączy silnik V8 od Google (ten sam, który wykonuje JS w Chrome) z warstwą w C++, która dostarcza API, jakich sam V8 nie ma: dostęp do systemu plików, sieć, procesy, timery. To połączenie pozwala budować w JavaScript serwery, narzędzia CLI i narzędzia do budowania projektów.
Czym Node różni się od przeglądarki?
Oba uruchamiają JavaScript, ale API wokół języka są inne. Przeglądarka daje ci window, document i DOM. Node daje ci process, fs, http, __dirname oraz ładowanie modułów CommonJS/ESM. W Node nie ma DOM, a w przeglądarce nie ma systemu plików: język jest wspólny, platforma nie.
Czy Node.js to framework czy środowisko uruchomieniowe?
Środowisko uruchomieniowe. Sam Node nie narzuca żadnej struktury aplikacji: po prostu wykonuje JavaScript i udostępnia API. Frameworki takie jak Express, Next.js czy NestJS są zbudowane na Node. Deno i Bun to alternatywne środowiska JavaScript, które konkurują z Node, ale pełnią tę samą rolę.
Czym jest pętla zdarzeń w Node?
Pętla zdarzeń (event loop) pozwala Node obsługiwać wiele rzeczy naraz w jednym wątku. Gdy wywołujesz coś asynchronicznego, na przykład odczyt pliku, żądanie HTTP czy setTimeout, Node przekazuje pracę systemowi i działa dalej. Gdy praca się kończy, jej callback trafia do kolejki, a pętla zdarzeń go odbiera. Dlatego fs.readFile nie blokuje reszty programu.