Skip to content

Latest commit

 

History

History
572 lines (370 loc) · 21.9 KB

File metadata and controls

572 lines (370 loc) · 21.9 KB

Node.js

Node.js basics

Что такое Node.js?

Node.js — JavaScript runtime вне браузера, построенный вокруг V8 и системных API. Он используется для servers, CLI, build tools и automation. Node предоставляет filesystem, processes и network APIs, которых нет в browser sandbox.

Чем Node.js отличается от браузера?

В Node нет DOM, window и browser security model, но доступны process, filesystem и server sockets. Browser имеет UI, Web APIs и origin restrictions. Общий JavaScript syntax не гарантирует совместимость окружений.

Что такое V8?

V8 — JavaScript engine от Chromium, который парсит, интерпретирует и JIT-компилирует код. Node использует V8 для выполнения ECMAScript. Browser APIs и Node APIs находятся вокруг engine, а не внутри языка.

Что такое libuv?

libuv — библиотека Node для event loop, async I/O, timers, filesystem и thread pool. Она скрывает различия операционных систем. Не все операции выполняются на главном JavaScript thread.

Почему Node.js называют event-driven runtime?

Программа регистрирует handlers, а runtime вызывает их при событиях I/O, timers или завершении задач. Это позволяет обслуживать много соединений без отдельного JavaScript thread на каждое. CPU-bound handler все равно блокирует event loop.

Что такое event loop в Node.js?

Event loop проходит фазы timers, pending callbacks, poll, check и close callbacks, обрабатывая готовые задачи. Microtasks выполняются между соответствующими этапами. Детали важны при диагностике starvation и порядка callbacks.

Чем event loop в Node.js отличается от browser event loop?

Оба координируют tasks и microtasks, но источники событий и фазы различаются. Browser привязан к rendering frames и Web APIs, Node — к libuv phases и server I/O. Нельзя механически переносить весь порядок callbacks между окружениями.

Что такое CommonJS?

CommonJS — историческая module system Node с require() и module.exports. Модули загружаются синхронно и имеют собственный wrapper scope. Экосистема постепенно переходит на стандартные ES Modules.

Что такое ES Modules в Node.js?

Это стандартная система import/export, включаемая расширением .mjs или "type": "module". Она поддерживает static analysis, top-level await и browser-compatible syntax. Resolution и interop с CommonJS имеют отдельные правила.

Чем require отличается от import?

require() — CommonJS function с синхронной загрузкой и runtime-вызовом. Static import анализируется до выполнения и работает в ESM. Dynamic import() асинхронен и доступен в обоих современных контекстах.

Что такое process.env?

Это объект environment variables текущего процесса. Значения являются строками или undefined, поэтому их нужно валидировать и преобразовывать. Секреты server process нельзя автоматически встраивать во frontend bundle.

Что такое __dirname и почему его нет в ESM?

В CommonJS это directory текущего module file. ESM использует стандартный import.meta.url, из которого путь получают через fileURLToPath. Отсутствие __dirname связано с другой module model, а не с невозможностью работать с путями.

Что такое stream?

Stream обрабатывает данные частями вместо загрузки всего объема в память. Бывают readable, writable, duplex и transform streams. Backpressure предотвращает переполнение медленного consumer.

Что такое Buffer?

Buffer представляет последовательность bytes в Node и используется для файлов, sockets и binary protocols. Encoding нужно задавать явно при преобразовании в строку. В browser близкие primitives — ArrayBuffer и typed arrays.

Что такое child process?

Это отдельный процесс операционной системы, запущенный из Node через spawn, exec или fork. Он имеет отдельную память и может выполнять внешнюю команду. Нужно обрабатывать exit code, stderr, signals и размер output.

Что такое worker_threads?

Worker threads выполняют JavaScript параллельно внутри одного Node process с отдельными isolates. Они подходят для CPU-bound вычислений, а не обычного async I/O. Обмен сообщениями и shared memory добавляют overhead.

npm и package scripts

Что такое npm package?

Это directory или опубликованный artifact с package.json и кодом. Package может быть библиотекой, CLI или приложением. Имя и version определяют его identity в registry.

Что такое package.json?

Manifest проекта описывает metadata, scripts, dependencies, package exports и настройки tools. Он не фиксирует точное дерево transitive dependencies. Для этого нужен lock-файл.

Чем dependencies отличаются от devDependencies?

dependencies нужны package во время runtime потребителя, devDependencies — для разработки, тестов и сборки. Для frontend application обе группы обычно устанавливаются перед build. Для library правильная классификация влияет на потребителя.

Что такое peerDependencies?

Они объявляют, что package ожидает совместимую dependency от host-проекта. Это важно для frameworks и plugins, которым нужен общий runtime instance. Например, Angular library обычно указывает Angular как peer dependency.

Что такое package-lock.json?

Lock-файл фиксирует точные версии и integrity всего установленного dependency tree. Он делает installs воспроизводимыми. Ручное редактирование обычно не требуется.

Почему lock-файл важно коммитить?

CI и разработчики получают одно и то же разрешенное дерево, а изменения dependencies видны в review. Без lock-файла compatible ranges могут установить разные transitive versions. Это усложняет debugging и supply-chain audit.

Что делает npm install?

Разрешает dependencies, устанавливает их в node_modules и обновляет lock-файл при необходимости. Он подходит для локальной разработки и добавления packages. Результат может изменить lock при рассинхронизации manifest.

Что делает npm ci?

Удаляет существующий node_modules и устанавливает точно по lock-файлу. Команда завершится ошибкой, если package.json и lock не согласованы. Она не переписывает dependency tree.

Чем npm ci лучше для CI?

Дает чистую, воспроизводимую установку и быстро обнаруживает незакоммиченный lock update. Поведение меньше зависит от предыдущего workspace state. Кеш npm downloads можно использовать отдельно от node_modules.

Что такое npm scripts?

Это именованные shell-команды в поле scripts, запускаемые через npm run. npm добавляет локальные binaries из node_modules/.bin в PATH. Lifecycle scripts могут запускаться автоматически, поэтому dependencies должны быть доверенными.

Как npm scripts используются во frontend-проектах?

Для start, build, test, lint, format, code generation и deployment wrappers. Они дают команде единый interface поверх Angular CLI, Vite и других tools. Scripts должны оставаться понятными и composable.

Что такое semantic versioning?

SemVer использует major.minor.patch: major для breaking changes, minor для совместимой функциональности, patch для совместимых fixes. До 1.0.0 гарантии часто трактуются осторожнее. Versioning полезно только при честном публичном контракте.

Что значит ^, ~ и exact version в package.json?

Exact устанавливает только указанную version. ~1.2.3 допускает patch updates, ^1.2.3 — compatible minor и patch до следующего major. Фактическую установленную версию фиксирует lock-файл.

Node.js для frontend tooling

Почему frontend-проекту нужен Node.js?

Node запускает package manager, compiler, linter, tests, dev server и production build. Результат затем выполняется в browser и может не зависеть от Node. SSR-приложение дополнительно использует Node во время runtime.

Как Node.js используется в Angular CLI?

CLI запускается как Node program, читает workspace config и вызывает builders. TypeScript/Angular compiler, dev server и test runner также работают в Node. Поддерживаемая Node version зависит от Angular version.

Как Node.js используется в Vite/Webpack/esbuild?

Он запускает bundler process, читает файлы, разрешает modules и обслуживает plugins. Vite предоставляет dev server, Webpack строит module graph, esbuild выполняет быстрые transforms/bundling. Production output предназначен для browser или server target.

Что такое dev server?

Локальный HTTP server для разработки с module transforms, source maps, watch и hot reload. Он оптимизирован для feedback, а не безопасности, кеширования и production traffic. Его нельзя использовать как production hosting.

Чем dev server отличается от production build?

Dev server часто преобразует modules по запросу и хранит часть данных в памяти. Production build минифицирует, хеширует, оптимизирует и записывает deployable artifacts. Поведение окружения нужно проверять production build.

Почему код, который работает в Node.js, может не работать в браузере?

Browser не предоставляет fs, process, CommonJS resolution и unrestricted sockets. Также действуют CORS, CSP и sandbox. Bundler polyfills не следует считать автоматическими или бесплатными.

Почему код, который работает в браузере, может не работать в Node.js?

В Node обычно нет window, document, DOM, layout и browser storage. SSR-код должен изолировать browser-only API. Некоторые Web APIs появляются в новых Node versions, но их поддержку нужно проверять.

Node.js observability и RPS monitoring

Что такое RPS?

RPS, или Requests Per Second, — количество запросов, которое сервер обрабатывает за секунду. Например, 120 RPS означает, что сервер в среднем обрабатывает 120 HTTP-запросов в секунду.

Что такое RPS monitor?

RPS monitor измеряет количество запросов за единицу времени. Он помогает увидеть текущую нагрузку, всплески трафика и связать их с деградацией производительности или доступности.

Зачем frontend-разработчику понимать RPS?

Frontend-разработчик может работать с SSR, BFF, dev server, Node.js tooling и API-интеграциями. RPS помогает оценивать нагрузку на SSR, rate limits, кеширование, retry-логику и влияние frontend-кода на backend.

Как может выглядеть простой RPS monitor в Node.js?

Этот учебный HTTP-сервер считает запросы за последнюю секунду и выводит результат в консоль:

import http from 'node:http';

let requests = 0;

setInterval(() => {
  console.log(`RPS: ${requests}`);
  requests = 0;
}, 1000);

const server = http.createServer((request, response) => {
  requests += 1;

  response.writeHead(200, {'Content-Type': 'application/json'});
  response.end(JSON.stringify({ok: true}));
});

server.listen(3000, () => {
  console.log('Server started on http://localhost:3000');
});
Как проверить RPS monitor через curl?

После запуска сервера можно отправить несколько запросов вручную:

curl http://localhost:3000
curl http://localhost:3000
curl http://localhost:3000

В следующем секундном интервале сервер выведет количество полученных запросов.

Почему такой RPS monitor не production-ready?

Он хранит счетчик только в памяти одного процесса и теряет данные при перезапуске. Несколько процессов или containers будут считать RPS независимо. В production метрики агрегируют через Prometheus, OpenTelemetry, APM или другую систему observability и визуализируют, например, в Grafana.

Какие метрики кроме RPS важны для Node.js сервера?
  • Latency и p95/p99 response time.
  • Error rate и количество ответов 4xx/5xx.
  • CPU и memory usage.
  • Event loop delay.
  • Active connections.
  • Throughput.

Метрики полезно связывать между собой: один RPS не объясняет состояние системы.

Чем RPS отличается от latency?

RPS показывает количество обработанных запросов в секунду, а latency — время обработки отдельного запроса. Высокий RPS сам по себе не является проблемой, но рост latency и error rate вместе с ним может указывать на перегрузку.

Что такое p95 и p99 latency?

p95 — значение, быстрее которого завершились 95% запросов; p99 аналогично описывает 99% запросов. Перцентили лучше среднего показывают медленный хвост распределения, хотя для полной картины также нужны размер выборки и временное окно.

Как event loop delay связан с производительностью Node.js?

JavaScript выполняется в основном потоке Node.js. CPU-bound работа и долгие синхронные операции блокируют event loop, из-за чего callbacks и обработчики запросов запускаются позже. Event loop delay измеряет эту задержку и помогает найти такие блокировки.

Что может увеличить RPS capacity Node.js приложения?
  • Кеширование и использование reverse proxy или CDN.
  • Уменьшение CPU-bound работы в request handler.
  • Горизонтальное масштабирование и несколько процессов.
  • Оптимизация запросов к базе и connection pooling.
  • Уменьшение лишнего logging на горячем пути.

Изменения нужно подтверждать нагрузочными тестами: увеличение RPS не должно ухудшать latency и error rate сверх SLO.