Node.js a serverové skriptování

Co je Node.js a proč je vhodný pro serverové skriptování

Node.js je běhové prostředí pro JavaScript založené na enginu V8, které umožňuje spouštět JS mimo prohlížeč. Díky event-driven a non-blocking I/O architektuře je ideální pro síťové aplikace s vysokou paralelní zátěží (API, realtime komunikace, proxy, streamovací brány). Silnou stránkou je jednotný jazyk napříč frontendem i backendem, bohatý ekosystém balíčků a snadná práce se JSONem.

Událostní smyčka, vlákna a model konkurence

Node.js používá event loop v jednom hlavním vlákně pro řízení asynchronních operací (časovače, I/O, síť). Blokující úlohy (např. kryptografie, komprese) provádí na pozadí libuv pomocí thread poolu. Pro CPU-intenzivní práci lze využít worker_threads nebo horizontální škálování přes cluster. Klíčové je navrhovat kód tak, aby neblokoval smyčku (vyhýbat se synchronnímu I/O, dlouhým smyčkám, rozsáhlým serializacím na hlavním vlákně).

Moduly: CommonJS vs. ECMAScript Modules

Node.js podporuje CommonJS (require/module.exports) i ESM (import/export). Volba ovlivňuje způsob načítání, cache i interoperabilitu. Doporučeným směrem je ESM, který je standardem v JS ekosystému. Konfigurace probíhá pomocí type v package.json a/nebo přípon .mjs/.cjs. Při návrhu knihoven je třeba dbát na jasnou distribuci (dual-package, export mapy) a precizní určení engines (minimální verze Node.js).

Správa závislostí a monorepa

Balíčky se spravují přes npm, yarn nebo pnpm. Pro rozsáhlejší kódové báze je běžná organizace do monorep s workspaces a nástroji jako Turborepo či Nx. Důležité je zamykat přesné verze (package-lock.json/pnpm-lock.yaml), pečovat o audit zranitelností a používat semantic versioning. Při provozu v produkci preferujte --omit=dev (instalace bez dev závislostí) a deterministické buildy.

Serverové frameworky a architektonické styly

  • Minimalistické HTTP frameworky: Express, Fastify – rychlý start, middleware, pluginy, validace, serializace.
  • Opinionated a modulární: NestJS – dependency injection, moduly, interceptory, filtry, integrace s GraphQL a WebSockety.
  • GraphQL servery: Apollo, Yoga – schémata, resolvery, federace, kontext per požadavku.
  • Serverless/edge adaptéry: lehké runtime-agnostické knihovny (Hono, Elysia) pro nasazení na edge platformy.

API vrstvy: REST, RPC a GraphQL

REST je srozumitelný a dobře cacheovatelný. RPC (např. tRPC) zjednodušuje typovou bezpečnost mezi klientem a serverem. GraphQL je vhodný pro komplexní klientské aplikace s potřebou flexibilních dotazů; vyžaduje však důsledný query cost management, dataloadery a autorizaci na úrovni jednotlivých polí.

Asynchronní programování: Promise, async/await, streamy

Doporučuje se používat async/await pro lepší čitelnost kódu, avšak dbát na paralelizaci pomocí Promise.all tam, kde to dává smysl. Streamy (Readable/Writable/Transform/Duplex) jsou klíčové pro efektivní práci s velkými objemy dat (upload/download, komprese, parsování). Používejte backpressure a utilitu pipeline pro bezpečné řetězení.

Práce s databázemi a datovou vrstvou

  • SQL: knihovny Knex, node-pg, mysql2 a ORM jako Prisma nebo TypeORM. Důraz na connection pooling, transakce a migrace.
  • NoSQL: MongoDB (Mongoose), dokumentové a klíč-hodnota úložiště. Navrhujte sharding/TTL a adekvátní indexy.
  • Cache: Redis jako in-memory cache, rate-limit store, pub/sub a distribuované zámky.
  • Fronty a streamy: RabbitMQ, Kafka, SQS – pro asynchronní workflow, outbox pattern a exactly-once semantiku (kompenzační transakce).

Autentizace a autorizace

JWT a PASETO jsou běžné pro bezstavové přístupové tokeny, session s podepsaným cookie je vhodná pro tradiční webové aplikace. Dbejte na rotaci klíčů (JWKS), krátkou dobu životnosti tokenů, refresh token flow a implementaci RBAC/ABAC v aplikační vrstvě. Na API bráně aplikujte rate limiting, IP allow-list a mTLS dle potřeby.

Bezpečnost serveru a závislostí

  • HTTP ochrany: hlavičky (HSTS, CSP, X-Frame-Options), CSRF ochrana pro stateful weby, sanitace vstupů.
  • Správa tajemství: neukládat citlivé údaje do .env v repozitáři, používání bezpečného trezoru; rotace a audit přístupů.
  • Dependabot/audit: pravidelný audit zranitelností, omezení postinstall skriptů, integrita lockfile.
  • SSR/templating: escapování výstupu a prevence XSS, bezpečné generování šablon.

Konfigurace, 12-Factor a prostředí

Konfigurace by měla být uchovávána v proměnných prostředí. Oddělte build a run fáze, logujte do STDOUT a používejte immutable buildy. Zajistěte idempotentní start aplikace (bez vedlejších efektů). Zavádějte feature flags pro řízené nasazování funkcí.

Logování, metriky a observabilita

  • Strukturované logy (JSON) s korelačními ID pro sledování požadavků napříč službami.
  • Metriky: latence, propustnost, chybovost, saturace (RED/USE). Export do Promethea nebo StatsD.
  • Trace: OpenTelemetry SDK pro distribuované trasování (span context přes HTTP/AMQP).

Výkon a škálování

  • Horizontální škálování více procesů (cluster) za reverzní proxy (NGINX/Envoy) s sticky sessions dle potřeby.
  • Worker Threads pro CPU náročné operace (hashování, PDF, obrázky), vyvarovat se blokujícímu kódu.
  • Optimalizace V8: vyhýbat se polymorfismu horkých funkcí, udržovat stabilní tvary objektů, recyklovat alokace.
  • Streamy a backpressure pro velké přenosy, zero-copy metody (fs.createReadStreamres).

Testování a kvalita

  • Jednotkové a integrační testy (Jest, Vitest, Mocha) s izolací závislostí a fixtures.
  • Contract testy rozhraní mezi mikroslužbami (Pact).
  • End-to-end testy API (Supertest), případně pro SSR/SPA části prohlížečové testy (Playwright).
  • Static analysis a TypeScript pro typovou bezpečnost, ESLint a Prettier pro konzistenci.

Typy běhu: dlouho běžící služby, cron a serverless

Node.js spolehlivě běží jako dlouhotrvající proces (HTTP servery, WebSocket huby), je však také vhodný pro cron úlohy a dávkové zpracování (např. s knihovnami pro plánování). V prostředí serverless je nezbytná inicializace bez stavů, rychlý cold start, krátké připojení k DB (pooling přes proxy) a idempotentnost handlerů.

Nasazení: kontejnery, orchestrátory a procesní manažery

  • Kontejnerizace: malé immutable image (alpine/distroless), multi-stage build, non-root uživatel, healthcheck.
  • Orchestrace: Kubernetes (readiness/liveness, HPA podle CPU/RAM/latence), service mesh (mTLS, retries, circuit breaking).
  • Procesní manažer: PM2 nebo systemd pro restart po pádu, rolling restarty a rotaci logů v tradičních VM.

HTTP, WebSocket a realtime

Pro realtime notifikace používejte WebSockety nebo SSE. Důležité je škálovat pub/sub vrstvu (Redis, NATS) a řešit presence, backoff a resubscribe po výpadku. Rate-limitujte události a nastavte kvóty na úrovni tenantů.

Souborový systém, uploady a CDN

Velké uploady obsluhujte přes multipart streaming a ukládejte do objektových úložišť s podpisovanými URL (pre-signed). Stahování servírujte přes CDN, server v Node.js pouze generuje odkazy a kontroluje přístupová práva.

Mezijazyková interoperabilita a nativní doplňky

Pro integraci s nativním kódem slouží N-API a node-addon-api. Vyžaduje to pečlivé verzování a CI pro různé platformy. Alternativou jsou externí mikroslužby v jiných jazycích komunikující přes HTTP/gRPC, což zjednodušuje build, avšak přidává síťovou latenci.

Stabilita, odolnost a vzory spolehlivosti

  • Circuit breaker, bulkhead, retry s jitterem a timeouty na všech výstupech.
  • Graceful shutdown: zachycení signálů, dokončení rozpracovaných požadavků, uzavření poolů.
  • Idempotence: opakovatelné operace v dávkách a webhooky chráněné podpisy a detekcí opakování.

Mezinárodní prostředí, lokalizace a formátování

Využívejte Intl API pro formátování čísel, měn a časů, vyhněte se manuálnímu parsování. Čas vždy ukládejte jako UTC, uživatelům jej prezentujte v jejich časové zóně. Pro lokalizaci zpráv používejte ICU message formát a externí slovníky.

Správa verzí Node.js a LTS strategie

Nasazujte na LTS řadách, sjednoťte verzi pomocí .nvmrc nebo engines v package.json. V rámci CI implementujte matrix buildy pro cílové verze a pravidelně testujte kompatibilitu. Sledujte deprekační upozornění a změny v API (fs/promises, URL, WHATWG Streams).

Observabilita výkonu a profilování

  • CPU profil a heap snapshot pro vyhledávání úniků paměti, flamegraphy pro „hot paths“.
  • Event loop lag monitorujte a snižujte přes delegaci CPU práce do workerů.
  • GC tuning – minimalizujte alokace, používejte pooling bufferů, pozor na neúmyslné referenční cykly.

Mikroslužby a kontrakty

Node.js je vhodný pro lehké mikroslužby: každá má jasný bounded context, smluvené kontrakty (OpenAPI/AsyncAPI), zpětně kompatibilní změny a verzování endpointů. Dodržujte consumer-driven contracts a CI validace schémat.

Bezustavové vs. stavové služby

Doporučuje se bezstavovost a stav ukládat do externích systémů (databáze, cache, fronty). V případě, že je stav nezbytný (např. herní realtime aplikace), použijte sticky sessions, robustní replikaci a conflict resolution. Plánujte rebalance při škálování.

Praktické zásady pro produkci

  • Vždy nastavte time-outy na HTTP klienty i servery a limity velikosti požadavků.
  • Logujte korelační ID a uživatele/tenanty (bez osobních údajů) pro dohledatelnost.
  • Automatizujte CI/CD (lint, testy, build, skenování, release, canary deploy, rollback).
  • Vytvářejte chaos scénáře (síťová latence, výpadky závislostí) a testujte odolnost systému.

Typické antipatterny a jak se jim vyhnout

  • Blokující synchronní kód na cestě požadavku (soubory, CPU-intenzivní smyčky).
  • Neřízené Promisy (zapomenuté await, nezachycené odmítnutí), chybějící try/catch.
  • „God server“ bez modulárního návrhu, míchání transportní a doménové logiky.
  • Nevalidované vstupy a serializace bez schémat (JSON Schema/Zod) – vede k exploatovatelným zranitelnostem.

Závěr

Node.js je vyzrálé a výkonné prostředí