Перейти к содержимому

Node.js — обзор раздела

Node.js — точка, где фронтенд-инженер впервые становится бэкенд-инженером. Ты уже знаешь язык, и это обманчивое преимущество: кажется, что «сервер на JS» — это те же функции и тот же console.log, только без браузера. Пара недель эксплуатации первого реального сервиса расставляет всё по местам. Сервис «подвис» на один запрос с большим JSON — и перестали отвечать все остальные. Файл в 2 ГБ уронил контейнер по OOM, хотя «мы же просто его скачивали». Деплой прошёл, но процесс не остановился по SIGTERM, и оркестратор убил его через 30 секунд посередине записи в базу. Все эти истории — не магия, а следствия конкретных механизмов: Event Loop — фазовый цикл, который планирует все твои колбеки, стримы, модели процессов и системы модулей.

Краткая версия материала уже дала обзор: фазы Event Loop, pipe для файлов, cluster для ядер, отличия CJS и ESM. В этом разделе мы спускаемся на уровень глубже — туда, где заканчиваются туториалы и начинается понимание платформы. Правило раздела: после каждой главы ты должен уметь предсказать поведение кода, а не угадывать его по результату.

Раздел построен от «как вообще выполняется код» к «как это эксплуатировать в проде»:

  1. Event Loop Node.js и libuv — сердце платформы. Фазы таймеров, poll, check и close; почему setImmediate и setTimeout(..., 0) — это не одно и то же; отдельная очередь process.nextTick, которая важнее промисов; thread pool libuv для файлов и криптографии; как измерять event loop lag и почему это главная метрика Node-сервиса.
  2. Streams и backpressure — способ обрабатывать данные любого размера в ограниченной памяти. Режимы flowing и paused, highWaterMark, ручное управление backpressure через возврат write(), pipeline против pipe, итерация через for await. Практика: файловый копировщик, gzip-стрим и CSV-парсер.
  3. Многопоточность: cluster, worker_threads, child_process — Node.js однопоточен, но машина — нет. Три механизма параллелизма: процессы-воркеры на все ядра CPU, потоки для тяжёлых вычислений, дочерние процессы для внешних программ. Плюс безопасность: чем опасен exec с пользовательским вводом.
  4. CJS vs ESM, циклические зависимости — две системы модулей, которые ещё долго будут сосуществовать. Механика загрузки, hoisting в ESM, import.meta, интероп в обе стороны, поле exports в package.json и главное — как ведут себя циклические зависимости в каждой системе и как их разруливать.
  5. Node.js в продакшене — то, что отличает учебный проект от сервиса: graceful shutdown по сигналам, keep-alive агенты и таймауты HTTP, логирование через pino, валидация конфигурации через Zod, healthchecks, метрики prom-client, утечки памяти в долгоживущих процессах и удалённая отладка через --inspect.

Event Loop в Node.js — прямое продолжение Event Loop в браузере: микротаски и макротаски общие, фазы и очереди — свои. Стримы и backpressure пригодятся в разделе про данные, когда пойдут миграции и импорты CSV в PostgreSQL. Graceful shutdown и healthchecks — фундамент для Docker и Kubernetes: именно по сигналу и именно эти эндпоинты смотрит оркестратор. Метрики и логирование развернутся в главе про наблюдаемость.

Код здесь исполняемый: создай директорию node-lab, инициализируй npm init -y, ставь "type": "module" в package.json — дальше примеры можно копировать и запускать как есть. Если какая-то тема даётся тяжело, начинай с официального раздела Learn на nodejs.org — короткие гайды по event loop, стримам и асинхронности от самих мейнтейнеров платформы; для справки по API всегда под рукой документация nodejs.org/api, а устройство нативной части платформы раскрывает Design Overview документации libuv. В каждой главе есть блок «предскажи вывод» — закрывай глаза, рассуждай вслух, потом запускай. Если предсказание не совпало — раздел написан для тебя.