Платформа Node.js як середовище виконання

Інструменти налагодження та розробки

Node.js debugger, Chrome DevTools, VS Code debugging, nodemon, ts-node, tsx, nvm, профілювання

Інструменти налагодження та розробки

🎯 Мета лекції

  • Опанувати вбудовані інструменти налагодження Node.js: node inspect та Chrome DevTools.
  • Навчитися налагоджувати TypeScript-код безпосередньо у VS Code через launch.json.
  • Освоїти інструменти продуктивності розробки: nodemon, ts-node, tsx.
  • Вивчити управління версіями Node.js через nvm та fnm.
  • Зрозуміти методи профілювання та аналізу продуктивності застосунків.

🔑 Ключові терміни

  • Debugger: інструмент для покрокового виконання коду, інспектування змінних та аналізу call stack.
  • Breakpoint: точка зупинки виконання програми для дослідження стану у конкретний момент.
  • Inspector Protocol: протокол Node.js для підключення зовнішніх debugger-клієнтів (Chrome DevTools, VS Code).
  • Hot Reload: автоматичний перезапуск застосунку при зміні вихідних файлів.
  • Profiling: аналіз продуктивності програми для виявлення вузьких місць (bottlenecks).

Еволюція налагодження: від console.log до Inspector Protocol

Антипаттерн: налагодження через console.log

Найпростіший, але найменш ефективний спосіб налагодження — вставлення console.log() у різні місця коду:

function calculateDiscount(price: number, customerType: string): number {
  console.log('calculateDiscount викликано з:', price, customerType); // 🐛 Debug

  let discount = 0;

  if (customerType === 'premium') {
    discount = 0.2;
    console.log('Premium клієнт, знижка 20%'); // 🐛 Debug
  } else if (customerType === 'regular') {
    discount = 0.1;
    console.log('Regular клієнт, знижка 10%'); // 🐛 Debug
  }

  const finalPrice = price * (1 - discount);
  console.log('Фінальна ціна:', finalPrice); // 🐛 Debug

  return finalPrice;
}

const result = calculateDiscount(100, 'premium');
console.log('Результат:', result); // 🐛 Debug

Проблеми цього підходу:

  1. Забруднення коду: Debug-логи змішуються з бізнес-логікою та потрапляють у production.
  2. Відсутність контексту: Важко зрозуміти весь шлях виконання та стан програми.
  3. Ручне видалення: Після налагодження потрібно видаляти всі console.log(), що може призвести до пропуску деяких.
  4. Обмежені можливості: Неможливо змінити значення змінної під час виконання або перемотати стек викликів назад.
console.log() залишається корисним для швидких перевірок та логування у production, але не замінює повноцінний debugger для розслідування складних багів.

Рішення: інтерактивні debugger

Сучасні debugger надають:

  • Breakpoints: Зупинка виконання у конкретних рядках коду.
  • Step-through execution: Покрокове виконання (step over, step into, step out).
  • Variable inspection: Перегляд та модифікація значень змінних у реальному часі.
  • Call stack navigation: Перегляд ланцюга викликів функцій.
  • Conditional breakpoints: Зупинка лише за виконання певної умови.
  • Watch expressions: Відстеження значень виразів протягом виконання.

Вбудований Node.js Debugger: node inspect

Node.js має вбудований CLI-debugger, який працює безпосередньо у терміналі. Він корисний для швидкого налагодження без налаштування IDE.

Запуск у режимі налагодження

// app.ts
function fibonacci(n: number): number {
  if (n <= 1) return n;
  return fibonacci(n - 1) + fibonacci(n - 2);
}

debugger; // 🔴 Точка зупинки

const result = fibonacci(10);
console.log('Fibonacci(10) =', result);

Запуск із вбудованим debugger:

node inspect app.js
$ node inspect app.js
< Debugger listening on ws://127.0.0.1:9229/...
< For help, see: https://nodejs.org/en/docs/inspector
break in app.js:6
4 }
5
> 6 debugger; ← Зупинка тут
7
8 const result = fibonacci(10);
debug> _ (очікування команди)

Команди debugger у терміналі

cont або c
command
Продовжити виконання до наступного breakpoint.
next або n
command
Виконати наступний рядок (не заходити у функції — step over).
step або s
command
Крок у функцію (step into).
out або o
command
Вийти з поточної функції (step out).
repl
command
Відкрити інтерактивну консоль для виконання JavaScript-коду у поточному контексті.
exec <expression>
command
Виконати вираз та вивести результат. Приклад: exec n покаже значення змінної n.
watch('<expr>')
command
Додати вираз до списку спостереження. Приклад: watch('result').
list(<lines>)
command
Показати код навколо поточного рядка. Приклад: list(10) покаже 10 рядків.
setBreakpoint() або sb()
command
Встановити breakpoint у поточному рядку.
.exit
command
Вийти з debugger.

Приклад інтерактивної сесії

Інтерактивне налагодження
debug> n ← next (крок далі)
> 8 const result = fibonacci(10);
debug> exec result ← перевірити змінну
ReferenceError: result is not defined (ще не виконано)
debug> s ← step into функцію fibonacci
> 2 if (n <= 1) return n;
debug> exec n
10
debug> watch('n') ← додати до спостереження
debug> c ← continue до кінця
Fibonacci(10) = 55
Waiting for the debugger to disconnect...
Ключове слово debugger; у коді еквівалентно встановленню breakpoint. Коли Node.js запущено у режимі налагодження (node inspect або node --inspect), виконання зупиниться на цьому рядку.

Chrome DevTools: графічний інтерфейс налагодження

Node.js підтримує Inspector Protocol, що дозволяє підключати Chrome DevTools для візуального налагодження з усіма можливостями браузерного debugger.

Запуск у режимі inspect

# Запуск із дефолтним портом 9229
node --inspect server.js

# Або відразу з паузою на першому рядку
node --inspect-brk server.js

# Кастомний порт
node --inspect=0.0.0.0:9230 server.js
node --inspect server.js
$ node --inspect server.js
Debugger listening on ws://127.0.0.1:9229/a1b2c3d4-...
For help, see: https://nodejs.org/en/docs/inspector
Debugger attached.
Server running at http://localhost:3000

Підключення Chrome DevTools

Крок 1: Відкрийте Chrome

Відкрийте браузер Google Chrome (або будь-який Chromium-based: Edge, Brave, Vivaldi).

Крок 2: Перейдіть до інспектора

У адресному рядку введіть:

chrome://inspect

Крок 3: Знайдіть процес Node.js

У розділі Remote Target з'явиться ваш Node.js процес:

Target (v20.x.x): /path/to/server.js
inspect

Крок 4: Клікніть "inspect"

Відкриється DevTools з повним доступом до:

  • Sources: Перегляд коду з breakpoints
  • Console: Інтерактивна консоль у контексті застосунку
  • Memory: Профілювання пам'яті (heap snapshots)
  • Profiler: CPU profiling для пошуку вузьких місць
Для автоматичного відкриття DevTools при запуску використовуйте прапор --inspect-brk, який зупиняє виконання на першому рядку, даючи час підключити debugger перед стартом застосунку.

Встановлення breakpoints у Chrome DevTools

У вкладці Sources ви можете:

  1. Клікнути на номері рядка — встановити звичайний breakpoint.
  2. ПКМ на номері рядка → Add conditional breakpoint — зупинка лише за умови:
    userId === 42  // Зупинитися тільки для користувача з ID 42
    
  3. ПКМ на номері рядка → Add logpoint — вивести повідомлення без зупинки:
    "User logged in:", username
    
  4. Event Listener Breakpoints (права панель):
    • XHR/fetch breakpoints — зупинка на AJAX-запитах
    • Timer breakpoints — на setTimeout, setInterval
    • Script breakpoints — на динамічному eval()

VS Code Debugger: інтегроване налагодження

VS Code має вбудований debugger, який працює через Inspector Protocol Node.js. Це найзручніший спосіб налагодження для повсякденної розробки.

Автоматична конфігурація (JavaScript Runtime)

VS Code автоматично розпізнає Node.js проєкти. Для швидкого старту:

  1. Відкрийте файл із кодом (наприклад, server.ts)
  2. Натисніть F5 або перейдіть до Run → Start Debugging
  3. Оберіть Node.js у списку середовищ

VS Code автоматично створить конфігурацію та запустить debugger.

Ручна конфігурація через launch.json

Для детального контролю створіть файл .vscode/launch.json у корені проєкту:

{
  "version": "0.2.0",
  "configurations": [
    {
      "type": "node",
      "request": "launch",
      "name": "Launch Program",
      "skipFiles": ["<node_internals>/**"],
      "program": "${workspaceFolder}/src/server.js",
      "outFiles": ["${workspaceFolder}/dist/**/*.js"]
    }
  ]
}

Пояснення ключових параметрів

type
string required
Тип середовища виконання. Для Node.js завжди "node".
request
string required
Режим debugger: "launch" (запустити новий процес) або "attach" (підключитися до існуючого).
program
string
Шлях до головного файлу застосунку. Змінні: ${workspaceFolder}, ${file} (поточний файл).
runtimeArgs
array
Аргументи для Node.js runtime. Приклад: ["-r", "dotenv/config"] для завантаження .env.
skipFiles
array
Файли, які потрібно пропустити при step-through. <node_internals>/** пропускає внутрішній код Node.js.
console
string
Де виводити консоль: "integratedTerminal" (вбудований термінал VS Code) або "internalConsole" (Debug Console).
env
object
Змінні оточення для процесу. Приклад: { "NODE_ENV": "test", "DEBUG": "*" }.
restart
boolean
Автоматично перепідключатися до процесу після перезапуску (корисно з nodemon).

Встановлення breakpoints у VS Code

Спосіб 1: Клік на полі номерів рядків

Клікніть ліворуч від номера рядка — з'явиться червона точка 🔴.

Спосіб 2: Клавіша F9

Поставте курсор на потрібний рядок та натисніть F9 для toggle breakpoint.

Спосіб 3: Conditional Breakpoint

ПКМ на breakpoint → Edit Breakpoint → введіть умову:

userId === 42 && status === 'active'

Зупинка відбудеться лише за виконання умови.

Спосіб 4: Logpoint

ПКМ на breakpoint → Edit Breakpoint → Logpoint → введіть повідомлення:

User {username} logged in at {new Date().toISOString()}

Повідомлення виводиться у Debug Console без зупинки виконання.

Контроль виконання у VS Code

Під час налагодження доступна панель керування:

Continue (F5)

Продовжити виконання до наступного breakpoint.

Step Over (F10)

Виконати поточний рядок, не заходячи у функції.

Step Into (F11)

Зайти у функцію для покрокового виконання.

Step Out (Shift+F11)

Завершити виконання поточної функції та повернутися на рівень вище.

Restart (Ctrl+Shift+F5)

Перезапустити процес налагодження з початку.

Stop (Shift+F5)

Зупинити налагодження та завершити процес.

Інспектування змінних

У лівій панелі VARIABLES відображаються:

  • Local: Змінні поточної функції
  • Global: Глобальні об'єкти (process, console, Buffer)
  • Closure: Змінні із замикань (closures)

Можна розгорнути об'єкти, змінити значення (клік на значення) та додати до Watch (ПКМ → Add to Watch).

VS Code автоматично підсвічує змінні, які змінили своє значення після останнього кроку, жовтим кольором. Це допомагає відстежувати зміни стану під час виконання.

Інструменти продуктивності розробки

nodemon: автоматичний перезапуск при зміні файлів

Під час розробки незручно вручну перезапускати сервер після кожної зміни коду. nodemon автоматично відстежує файли та перезапускає процес.

npm install --save-dev nodemon

Використання у package.json:

{
  "scripts": {
    "dev": "nodemon src/server.ts",
    "dev:inspect": "nodemon --inspect src/server.ts"
  }
}
npm run dev
$ npm run dev
[nodemon] 3.1.0
[nodemon] to restart at any time, enter `rs`
[nodemon] watching path(s): *.*
[nodemon] watching extensions: ts,js,json
[nodemon] starting `ts-node src/server.ts`
🚀 Server running at http://localhost:3000
[Зміна файлу src/routes/users.ts]
[nodemon] restarting due to changes...
[nodemon] starting `ts-node src/server.ts`
🚀 Server running at http://localhost:3000

Конфігурація через nodemon.json

Для точного контролю створіть файл nodemon.json у корені проєкту:

{
  "watch": ["src"],
  "ext": "ts,js,json",
  "ignore": ["src/**/*.test.ts", "node_modules"],
  "exec": "ts-node --transpile-only src/server.ts",
  "env": {
    "NODE_ENV": "development",
    "DEBUG": "app:*"
  },
  "delay": 1000,
  "restartable": "rs"
}
watch
array
Директорії для відстеження. За замовчуванням відстежується вся поточна папка.
ext
string
Розширення файлів для моніторингу. Приклад: "ts,tsx,js,json".
ignore
array
Файли та папки, які потрібно ігнорувати. Підтримує glob-паттерни.
exec
string
Команда для виконання. Приклад: "tsx src/server.ts".
delay
number
Затримка перед перезапуском (мс). Уникає багаторазових перезапусків при збереженні кількох файлів.
env
object
Змінні оточення для процесу.
Опція --transpile-only у ts-node вимикає перевірку типів для швидшого перезапуску. Перевірку типів можна запустити окремо через tsc --noEmit --watch у паралельному терміналі.

ts-node: виконання TypeScript без компіляції

ts-node дозволяє запускати TypeScript-файли безпосередньо, без попередньої компіляції у JavaScript:

npm install --save-dev ts-node typescript @types/node

Конфігурація у tsconfig.json:

{
  "compilerOptions": {
    "target": "ES2022",
    "module": "commonjs",
    "esModuleInterop": true,
    "skipLibCheck": true
  },
  "ts-node": {
    "transpileOnly": true,
    "files": true,
    "compilerOptions": {
      "module": "commonjs"
    }
  }
}
ts-node компілює TypeScript у пам'яті (in-memory) під час виконання, тому перший запуск може бути повільнішим, ніж запуск попередньо скомпільованого JavaScript. Для production завжди використовуйте tsc для компіляції у статичні файли.

tsx: швидша альтернатива ts-node

tsx — це сучасна заміна ts-node, написана на Rust (через esbuild), що забезпечує значно швидшу компіляцію:

npm install --save-dev tsx

Порівняння продуктивності:

ts-node

Швидкість запуску: ~3-5 секунд для середнього проєкту. Переваги: Повна сумісність з TypeScript, підтримка перевірки типів.

tsx

Швидкість запуску: ~100-300 мс (в 10-50 разів швидше!). Переваги: Миттєвий старт, вбудований watch mode, не потребує nodemon.
Для production-застосунків завжди компілюйте TypeScript у JavaScript через tsc. Інструменти на кшталт ts-node та tsx призначені виключно для розробки та тестування.

Управління версіями Node.js

Різні проєкти можуть вимагати різних версій Node.js. Менеджери версій дозволяють швидко перемикатися між ними.

nvm (Node Version Manager): класичний інструмент

nvm — найпопулярніший менеджер версій Node.js для Unix-систем (macOS, Linux).

# Завантаження та встановлення nvm
curl -o- https://raw.githubusercontent.com/nvm-sh/nvm/v0.39.7/install.sh | bash

# Або через Homebrew (macOS)
brew install nvm

# Перезавантажте термінал або виконайте:
source ~/.bashrc  # або ~/.zshrc

Основні команди nvm

nvm commands
$ nvm list-remote # Показати доступні версії
...
v20.11.0 (LTS: Iron)
v21.6.2 (Latest)
$ nvm install 20 # Встановити останню версію 20.x
Downloading and installing node v20.11.0...
✓ Installed Node.js v20.11.0 (npm v10.2.4)
$ nvm install 18.19.0 # Встановити конкретну версію
✓ Installed Node.js v18.19.0
$ nvm list # Показати встановлені версії
v18.19.0
-> v20.11.0
$ nvm use 18 # Перемкнутися на версію 18.x
Now using node v18.19.0 (npm v10.2.3)
$ node --version
v18.19.0
$ nvm alias default 20 # Встановити версію за замовчуванням
default -> 20 (-> v20.11.0)

Файл .nvmrc: фіксація версії проєкту

Створіть файл .nvmrc у корені проєкту для автоматичного вибору версії:

20.11.0

Або з вказанням LTS:

lts/iron

Тепер команда nvm use автоматично зчитає версію з файлу:

cd /path/to/project
nvm use
# Found '.nvmrc' with version <20.11.0>
# Now using node v20.11.0
Додайте .nvmrc у Git, щоб вся команда використовувала однакову версію Node.js. Це запобігає проблемам із несумісністю залежностей або API.

fnm (Fast Node Manager): швидка альтернатива

fnm написаний на Rust і працює у 10-40 разів швидше, ніж nvm. Він автоматично перемикає версію Node.js при зміні директорії (якщо знаходить .nvmrc або .node-version).

brew install fnm

# Додайте у ~/.zshrc або ~/.bashrc:
eval "$(fnm env --use-on-cd)"

Основні команди fnm

# Встановити версію
fnm install 20

# Використати версію
fnm use 20

# Показати встановлені версії
fnm list

# Встановити версію за замовчуванням
fnm default 20

# Встановити LTS версію
fnm install --lts

Автоматичне перемикання:

# У проєкті А (.nvmrc: 18.19.0)
cd ~/projects/legacy-app
node --version  # v18.19.0 (автоматично!)

# У проєкті Б (.nvmrc: 20.11.0)
cd ~/projects/modern-app
node --version  # v20.11.0 (автоматично!)
fnm підтримує як .nvmrc, так і .node-version файли. Якщо версія не встановлена, fnm запропонує встановити її автоматично.

Профілювання продуктивності

Профілювання (profiling) — це процес аналізу того, де застосунок витрачає час виконання та пам'ять. Node.js надає вбудовані інструменти для виявлення вузьких місць (bottlenecks).

CPU Profiling: пошук повільних функцій

Node.js може генерувати CPU profile, який показує, скільки часу витрачено на кожну функцію:

# Запуск із профілюванням (V8 profiler)
node --prof server.js

# Після роботи застосунку з'явиться файл isolate-0x....-v8.log
# Обробка лог-файлу у читабельний формат:
node --prof-process isolate-0x....-v8.log > profile.txt

Результат у profile.txt:

 [Summary]:
   ticks  total  nonlib   name
   1582   39.6%   39.8%  JavaScript
   2403   60.2%   60.4%  C++
      2    0.1%    0.1%  GC
    268    6.7%          Shared libraries

Детальна статистика функцій:

 [JavaScript]:
   ticks  total  nonlib   name
    234    5.9%    5.9%  LazyCompile: *calculateDiscount /path/to/app.js:42:28
    189    4.7%    4.7%  LazyCompile: *queryDatabase /path/to/db.js:15:22
    145    3.6%    3.6%  RegExp: [a-zA-Z0-9]+
CPU profiling корисний для виявлення синхронного коду, який виконується занадто довго (складні обчислення, регулярні вирази, парсинг великих JSON). Для аналізу асинхронних операцій використовуйте трасування (tracing).

Chrome DevTools Profiler

Більш зручний спосіб — профілювання через Chrome DevTools:

Крок 1: Запустіть з inspect

node --inspect server.js

Крок 2: Відкрийте DevTools

Перейдіть до chrome://inspect та клікніть inspect.

Крок 3: Вкладка Profiler

У DevTools перейдіть до вкладки Profiler → Start.

Крок 4: Навантажте застосунок

Виконайте операції, які потрібно проаналізувати (HTTP-запити, обробка даних).

Крок 5: Зупиніть профілювання

Клікніть Stop — отримаєте інтерактивний flame graph.

Flame Graph показує:

  • Горизонтальна вісь: Час виконання (ширина = тривалість функції).
  • Вертикальна вісь: Глибина call stack (батьківські функції зверху, дочірні знизу).
  • Колір: Hot functions (червоний/жовтий) — функції, що споживають найбільше CPU.
Шукайте "плато" у flame graph — широкі блоки на одному рівні. Це функції, де застосунок проводить найбільше часу. Якщо функція займає >10% загального часу, вона є кандидатом на оптимізацію.

Memory Profiling: пошук витоків пам'яті

Node.js може створювати heap snapshots — знімки стану пам'яті у конкретний момент:

// Програмне створення heap snapshot
import v8 from 'node:v8';
import fs from 'node:fs';

function takeSnapshot(filename: string): void {
  const snapshotStream = v8.writeHeapSnapshot(filename);
  console.log(`Heap snapshot збережено у ${snapshotStream}`);
}

// Створення snapshot перед та після операції
takeSnapshot('./heap-before.heapsnapshot');

// Операція, яка може викликати витік пам'яті
const leakyArray: unknown[] = [];
for (let i = 0; i < 1_000_000; i++) {
  leakyArray.push({ id: i, data: Buffer.alloc(1024) });
}

takeSnapshot('./heap-after.heapsnapshot');

Аналіз через Chrome DevTools:

Крок 1: Завантажте snapshot

У DevTools → Memory → Load → оберіть файл .heapsnapshot.

Крок 2: Порівняйте snapshots

Завантажте heap-before.heapsnapshot та heap-after.heapsnapshot.

Крок 3: Виберіть режим "Comparison"

DevTools покаже різницю: які об'єкти додалися та скільки пам'яті вони займають.

Крок 4: Знайдіть витік

Відсортуйте за колонкою Size Delta — найбільші значення вказують на витік.

Heap snapshots можуть бути великими (сотні МБ для production-застосунків). Не створюйте їх занадто часто і не зберігайте у Git. Використовуйте тільки для діагностики витоків пам'яті.

Clinic.js: автоматичний аналіз продуктивності

clinic — це набір інструментів від команди Node.js для автоматичної діагностики:

# Встановлення
npm install -g clinic

# Clinic Doctor: виявлення проблем із Event Loop та I/O
clinic doctor -- node server.js

# Clinic Bubbleprof: візуалізація асинхронних операцій
clinic bubbleprof -- node server.js

# Clinic Flame: генерація flame graphs
clinic flame -- node server.js

# Після завершення тестування (Ctrl+C) відкриється HTML-звіт у браузері

Clinic Doctor виявляє:

  • Event Loop затримки (блокуючий синхронний код)
  • Повільне введення/виведення (файли, бази даних, мережа)
  • Проблеми з garbage collection
clinic doctor -- node server.js
$ clinic doctor -- node server.js
◉ Starting server...
✓ Server running at http://localhost:3000
[Виконайте навантажувальні тести, потім Ctrl+C]
^C
◉ Analysing data...
✓ Generated HTML report
⚠ Detected issue: Event Loop delay detected
Possible cause: Synchronous file operations or heavy computations
Recommendation: Use async APIs (fs.promises) or Worker Threads
Opening report in browser...

Налагодження у production: безпечні практики

Логування замість debugger

У production-середовищі debugger не є опцією. Натомість використовуйте структуроване логування:

import pino from 'pino';

const logger = pino({
  level: process.env.LOG_LEVEL || 'info',
  transport:
    process.env.NODE_ENV === 'development'
      ? { target: 'pino-pretty', options: { colorize: true } }
      : undefined,
});

// Структуровані логи з контекстом
logger.info({ userId: 42, action: 'login' }, 'User logged in');

// Логування помилок зі stack trace
try {
  throw new Error('Database connection failed');
} catch (err) {
  logger.error({ err, context: { userId: 42 } }, 'Failed to process request');
}
Використовуйте рівні логування (debug, info, warn, error) для контролю об'єму логів у production. Встановіть LOG_LEVEL=error для мінімального виводу або LOG_LEVEL=debug для детальної діагностики.

Error Tracking: Sentry, Rollbar, Bugsnag

Для автоматичного збору помилок у production використовуйте сервіси error tracking:

import * as Sentry from '@sentry/node';

// Ініціалізація Sentry
Sentry.init({
  dsn: process.env.SENTRY_DSN,
  environment: process.env.NODE_ENV,
  tracesSampleRate: 0.1, // 10% запитів для performance monitoring
});

// Express інтеграція
app.use(Sentry.Handlers.requestHandler());
app.use(Sentry.Handlers.tracingHandler());

// Ваші routes...

// Error handler (має бути останнім middleware)
app.use(Sentry.Handlers.errorHandler());

// Ручне логування помилок
try {
  await riskyOperation();
} catch (err) {
  Sentry.captureException(err, {
    tags: { userId: req.user?.id },
    extra: { requestBody: req.body },
  });
  throw err;
}

Distributed Tracing: OpenTelemetry

Для мікросервісних архітектур використовуйте distributed tracing для відстеження запиту через всі сервіси:

import { NodeSDK } from '@opentelemetry/sdk-node';
import { getNodeAutoInstrumentations } from '@opentelemetry/auto-instrumentations-node';
import { JaegerExporter } from '@opentelemetry/exporter-jaeger';

const sdk = new NodeSDK({
  traceExporter: new JaegerExporter({
    endpoint: 'http://localhost:14268/api/traces',
  }),
  instrumentations: [getNodeAutoInstrumentations()],
});

sdk.start();

// Автоматично інструментує HTTP, Express, PostgreSQL, Redis тощо

Питання для самоконтролю

Підсумок: оптимальний workflow розробки

Крок 1: Налаштування проєкту

# Встановити інструменти розробки
npm install --save-dev nodemon tsx @types/node

# Створити .nvmrc для фіксації версії Node.js
echo "20.11.0" > .nvmrc

Крок 2: Конфігурація scripts

// package.json
{
  "scripts": {
    "dev": "tsx watch src/server.ts",
    "dev:debug": "tsx --inspect-brk src/server.ts",
    "build": "tsc",
    "start": "node dist/server.js",
    "type-check": "tsc --noEmit"
  }
}

Крок 3: Налаштування VS Code

// .vscode/launch.json
{
  "configurations": [
    {
      "type": "node",
      "request": "launch",
      "name": "Debug TypeScript",
      "runtimeExecutable": "tsx",
      "program": "${workspaceFolder}/src/server.ts",
      "skipFiles": ["<node_internals>/**"]
    }
  ]
}

Крок 4: Профілювання перед production

# Перевірка продуктивності
clinic doctor -- node dist/server.js

# Heap snapshot для аналізу пам'яті
node --heapsnapshot-signal=SIGUSR2 dist/server.js
# Відправити сигнал: kill -USR2 <pid>

✅ Розробка

  • tsx watch для миттєвого перезапуску
  • VS Code Debugger для покрокового виконання
  • console.log() для швидких перевірок
  • Chrome DevTools для візуального профілювання

🧪 Тестування

  • NODE_ENV=test для ізольованого середовища
  • Heap snapshots для виявлення витоків
  • Clinic.js для автоматичного аналізу
  • Load testing (autocannon, k6)

🚀 Production

  • Компільований JavaScript (tsc)
  • Структуроване логування (pino, winston)
  • Error tracking (Sentry, Rollbar)
  • Distributed tracing (OpenTelemetry, Jaeger)

У наступній лекції ми розглянемо best practices продуктивності Node.js: оптимізацію Event Loop, використання Worker Threads, кешування та стратегії масштабування застосунків.

Copyright © 2026