1. Що таке Node.js і які основні сфери його використання?
Node.js — це середовище виконання JavaScript поза браузером, побудоване на V8. Використовується для створення серверних застосунків, REST/GraphQL API, реального часу (чати, стріми), мікросервісів, CLI-утиліт.
2. Як у Node.js реалізована робота з дочірніми потоками?
Node.js за замовчуванням виконує код у одному потоці (event loop), але:
-
Для асинхронних I/O операцій використовує пул потоків libuv. Це приховано від розробника.
-
Для створення дочірніх потоків у самому Node.js є модуль worker_threads — дозволяє запускати паралельні обчислення в окремих потоках з можливістю обміну пам’яттю.
-
Для ізольованих процесів застосовується child_process, але це вже не потоки, а окремі процеси.
В реальних проєктах: CPU-bound задачі (наприклад, хешування, обробка зображень) варто виносити у worker_threads, щоб не блокувати основний потік.
3. Опишіть принцип event-driven програмування в Node.js.
Node.js працює за event-driven (подієво-орієнтованою моделлю): основний потік виконує event loop, який реагує на події (I/O, мережеві запити, таймери). Замість блокуючих викликів використовуються колбеки, проміси або async/await. Це дозволяє ефективно обробляти велику кількість одночасних з’єднань без створення додаткових потоків.
Приклад з практики: HTTP-сервер у Node.js слухає події request і виконує потрібний обробник кожного запиту.
4. Що таке event loop у Node.js?
-
Принцип: Event loop — це механізм, який керує виконанням асинхронних операцій у Node.js.
-
Як працює: Він безперервно перевіряє чергу подій (callback queue) та виконує колбеки, коли стек викликів порожній.
-
Роль: Забезпечує неблокуюче виконання коду в одному потоці.
-
Приклад: HTTP-запит завершується → колбек потрапляє в чергу → event loop виконує його, коли готовий.
5. У чому різниця між Node.js та традиційними вебсерверними технологіями?
- Архітектура:
-
Node.js — однопотокова подієво-орієнтована модель (event loop).
-
Традиційні вебсервери (Apache, Tomcat, IIS) — багатопотокові: кожен запит обробляється окремим потоком/процесом.
- Продуктивність:
-
Node.js краще масштабується при великій кількості одночасних I/O-запитів.
-
Традиційні сервери добре працюють із CPU-bound задачами, але витрачають більше ресурсів на управління потоками.
- Розробка:
-
Node.js розширив можливості JavaScript, зробивши його придатним і для серверної розробки.
-
У класичних підходах бекенд реалізується іншими мовами (PHP, Java, C#, Python).
Приклад з практики:
Node.js підходить для чату або API з великою кількістю клієнтів у реальному часі, а Java/Tomcat краще для важких транзакційних систем (банкінг, ERP).
6. Поясніть, що означає неблокуюче (non-blocking) у Node.js.
-
Принцип: Неблокуюче означає, що виконання коду не чекає завершення I/O операцій (файли, мережа, БД).
-
Як працює: Node.js запускає I/O асинхронно і реєструє колбек або проміс для обробки результату, поки основний потік продовжує виконання іншого коду.
-
Роль: Забезпечує високу продуктивність при великій кількості одночасних запитів без створення додаткових потоків.
Читання великого файлу з диску через fs.readFile() не зупиняє сервер — він може обробляти інші HTTP-запити в цей час.
7. Як оновити Node.js до останньої версії?
-
Через офіційний сайт: завантажити останній інсталятор з nodejs.org і встановити.
-
Через пакетний менеджер:
-
Windows/macOS:
nvm
(Node Version Manager) —nvm install node
абоnvm install <version>
-
Linux:
nvm
або системний пакетний менеджер (apt
,yum
)
- Перевірка версії:
node -v
Практика: для проєктів з різними версіями Node.js краще використовувати nvm
—
легко перемикатися між версіями без конфліктів.
8. Що таке npm і для чого його використовують?
-
npm (Node Package Manager) — менеджер пакетів для Node.js.
-
Призначення: встановлення, оновлення та управління бібліотеками/модулями у проєкті.
-
Приклади команд:
-
npm install <package>
— встановити пакет -
npm update
— оновити пакети -
npm init
— створити package.json
-
Практика: використовується для підключення сторонніх бібліотек (Express, Axios, Lodash) і управління залежностями проєкту.
9. Як керувати пакетами у проєкті на Node.js?
-
Ініціалізація проєкту:
npm init
абоnpm init -y
створюєpackage.json
. -
Встановлення пакетів:
-
npm install <package>
— додає пакет і записує у dependencies -
npm install <package> --save-dev
— додає у devDependencies
- Оновлення та видалення:
-
npm update
— оновлення пакетів -
npm uninstall <package>
— видалення пакета
- Фіксація версій:
package-lock.json
гарантує однакові версії для всіх учасників проєкту.
Практика: завжди використовуй package-lock.json і розділяй залежності на runtime та dev, щоб уникнути конфліктів і зайвого коду на продакшні.
10. Що таке файл package.json?
-
Призначення:
package.json
описує Node.js проєкт і його залежності. -
Що містить:
-
Назву, версію проєкту
-
Залежності (
dependencies
іdevDependencies
) -
Скрипти (
scripts
) для запуску команд (start
,test
,build
) -
Метадані про автора, ліцензію, сумісність Node.js
-
Практика: Використовується npm/yarn для встановлення потрібних пакетів і
запуску команд через npm run <script>
.
11. Опишіть деякі з основних модулів Node.js
У Node.js є вбудовані модулі, які не потребують встановлення через npm:
-
fs (File System):
робота з файлами (читання, запис, стрімінг). -
http / https:
створення вебсерверів та робота з HTTP(S)-запитами. -
path:
робота з файловими шляхами, кросплатформене вирівнювання. -
os:
інформація про операційну систему (CPU, пам’ять, мережа). -
events:
реалізація подієвої моделі через EventEmitter. -
crypto:
шифрування, хешування, генерація ключів.
12. Як створити простий сервер у Node.js за допомогою модуля HTTP?
-
Імпортувати модуль:
const http = require('http');
-
Створити сервер через
http.createServer()
. -
Визначити обробку запитів (
req
,res
). -
Запустити сервер на вказаному порту (
server.listen(3000)
).
const http = require('http');
const server = http.createServer((req, res) => {
res.writeHead(200, { 'Content-Type': 'text/plain' });
res.end('Hello, Node.js server!');
});
server.listen(3000, () => {
console.log('Server is running at http://localhost:3000');
});
Практика: такий підхід підходить для демо чи дуже простих API. У реальних проєктах зазвичай використовують Express.js для зручності.
13. Поясніть призначення модуля File System (fs).
-
Призначення: модуль
fs
дозволяє працювати з файловою системою напряму з Node.js. -
Можливості:
-
читання (
fs.readFile
,fs.createReadStream
) -
запис (
fs.writeFile
,fs.createWriteStream
) -
створення/видалення файлів і директорій
-
робота в синхронному й асинхронному режимі
-
-
Практика: використовується для завантаження/збереження файлів користувача, логування, роботи з конфігами.
const fs = require('fs');
fs.readFile('data.txt', 'utf8', (err, data) => {
if (err) throw err;
console.log(data);
});
14. Що таке клас Buffer у Node.js?
-
Призначення:
Buffer
— це клас у Node.js для роботи з двійковими даними (raw data). -
Особливості:
-
зберігає дані у вигляді байтів (подібно до масиву байтів у C).
-
використовується для обробки файлів, мережевих потоків, зображень тощо.
-
працює поза V8 heap, напряму в пам’яті.
-
-
Практика: корисний для читання/запису файлів (
fs
), роботи з TCP/UDP сокетами, обробки даних у потоках.
const buf = Buffer.from('Hello');
console.log(buf); // <Buffer 48 65 6c 6c 6f>
console.log(buf.toString()); // Hello
15. Що таке стріми (streams) у Node.js і які їхні типи?
-
Призначення: Стріми — це інтерфейс для роботи з потоковими даними по частинах, без завантаження всього в пам’ять. Використовуються для файлів, HTTP-запитів/відповідей, сокетів.
-
Перевага: ефективна робота з великими обсягами даних.
-
Readable — джерело даних (читання файлів, вхідні HTTP-запити).
-
Writable — приймач даних (запис у файл, вихідні HTTP-відповіді).
-
Duplex — одночасно читання і запис (TCP-сокети).
-
Transform — Duplex із можливістю трансформації даних під час потоку (наприклад, стиснення через zlib).
const fs = require('fs');
const readStream = fs.createReadStream('input.txt');
const writeStream = fs.createWriteStream('output.txt');
readStream.pipe(writeStream); // копіює файл через стріми
16. Як у Node.js читати та записувати файли?
У Node.js для цього використовується модуль fs (File System).
- Асинхронне читання/запис (рекомендовано):
const fs = require('fs');
// Читання
fs.readFile('input.txt', 'utf8', (err, data) => {
if (err) throw err;
console.log(data);
});
// Запис
fs.writeFile('output.txt', 'Hello Node.js', (err) => {
if (err) throw err;
console.log('Файл збережено!');
});
- Синхронні методи (блокують event loop, краще не використовувати у продакшн):
const data = fs.readFileSync('input.txt', 'utf8');
fs.writeFileSync('output.txt', 'Hello Sync');
-
асинхронні методи застосовуються в більшості сценаріїв (вебсервери, API).
-
синхронні зручні для скриптів або ініціалізації конфігів при старті.
17. Як використовувати EventEmitter у Node.js?
-
EventEmitter — це клас із модуля events, який реалізує подієву модель у Node.js.
-
Дозволяє створювати власні події та підписників (listeners).
const EventEmitter = require('events'); const emitter = new EventEmitter();
// підписка на подію emitter.on('greet', (name) => {
console.log(`Hello, ${name}!`); });
// виклик події emitter.emit('greet', 'Viktor');
-
Використовується у внутрішніх механізмах Node.js (наприклад, стріми побудовані на EventEmitter).
-
У проєктах застосовується для кастомних івентів — наприклад, логування, повідомлення між модулями.
18. Що таке модуль QueryString у Node.js?
-
Призначення: модуль querystring використовується для роботи з рядками запитів (URL query strings).
-
Можливості:
-
перетворює query string у JavaScript-об’єкт
-
формує query string з об’єкта
-
const querystring = require('querystring');
const parsed = querystring.parse('name=Viktor&age=30'); console.log(parsed); //
{ name: 'Viktor', age: '30' }
const str = querystring.stringify({ city: 'Kyiv', lang: 'ua' });
console.log(str); // city=Kyiv&lang=ua
Практика: у сучасних застосунках частіше використовують URLSearchParams (стандартний Web API у Node.js 10+), але querystring усе ще застосовують у легасі-коді.
19. Як у Node.js керувати операціями з файловими шляхами?
- У Node.js для цього є вбудований модуль path, який забезпечує кросплатформену роботу з шляхами.
-
path.join([...paths])
— об’єднання шляхів у правильному форматі. -
path.resolve([...paths])
— повертає абсолютний шлях. -
path.basename(path)
— отримати ім’я файлу. -
path.dirname(path)
— отримати директорію. -
path.extname(path)
— отримати розширення файлу.
const path = require('path');
const filePath = '/users/viktor/docs/file.txt';
console.log(path.basename(filePath)); // file.txt
console.log(path.dirname(filePath)); // /users/viktor/docs
console.log(path.extname(filePath)); // .txt
console.log(path.join('users', 'viktor', 'docs')); // users/viktor/docs
Практика: path застосовується для роботи з файлами у різних ОС (Windows → , Linux/macOS → /).
20. Що таке колбеки (callbacks) у Node.js?
Колбек — це функція, яка передається як аргумент іншій функції і викликається після завершення асинхронної операції.
-
У Node.js вони широко застосовуються для роботи з I/O (файли, мережа, база даних).
-
Стандартний підхід: error-first callback — перший аргумент
err
, другий — результат.
const fs = require('fs');
fs.readFile('data.txt', 'utf8', (err, data) => {
if (err) {
console.error('Помилка:', err);
return;
}
console.log('Вміст файлу:', data);
});
Практика: Колбеки — основа асинхронності у Node.js. Але через проблему "callback hell" у сучасних проєктах переважно використовують Promises та async/await.
21. Що таке callback hell і як його уникнути?
Callback hell — це ситуація, коли в коді є багато вкладених колбеків, що ускладнює читання, відлагодження та підтримку.
fs.readFile('a.txt', (err, dataA) => {
fs.readFile('b.txt', (err, dataB) => {
fs.readFile('c.txt', (err, dataC) => {
console.log(dataA, dataB, dataC);
});
});
});
-
Використовувати Promises — ланцюжки .then().
-
Застосовувати async/await — більш лаконічний та зрозумілий синтаксис.
-
Розбивати код на менші функції (modularization).
-
Використовувати готові бібліотеки для керування асинхронністю (async, bluebird).
Сучасна практика: майже всюди застосовують async/await, бо це найчитабельніший спосіб писати асинхронний код у Node.js.
22. Поясніть, що таке проміси (Promises) у Node.js.
Promise — це об’єкт, який представляє результат асинхронної операції:
успішний (resolved
) або з помилкою (rejected
).
-
Дозволяє уникнути вкладених колбеків і писати асинхронний код більш структуровано.
-
Стани проміса:
-
pending
(очікування) -
fulfilled
(успішно виконано) -
rejected
(помилка)
const fs = require('fs').promises;
fs.readFile('data.txt', 'utf8')
.then(data => console.log('Вміст:', data))
.catch(err => console.error('Помилка:', err));
-
Використовуються для роботи з асинхронними API (fetch, fs.promises, БД).
-
У сучасному коді зазвичай поєднуються з async/await, що робить код ще чистішим.
23. Як працюють функції async/await у Node.js?
-
async
— позначає функцію, яка завжди повертає Promise. -
await
— зупиняє виконання всередині async-функції, поки Promise не буде виконано (resolved
абоrejected
). -
Це синтаксичний цукор над Promises, що робить асинхронний код схожим на синхронний.
Приклад:
const fs = require('fs').promises;
async function readFile() {
try {
const data = await fs.readFile('data.txt', 'utf8');
console.log('Вміст:', data);
} catch (err) {
console.error('Помилка:', err);
}
}
readFile();
-
Використовується у більшості сучасних проєктів для роботи з асинхронним кодом.
-
Полегшує обробку помилок через
try/catch
. -
Уникає “callback hell” і довгих ланцюжків
.then()
.
24. У чому різниця між синхронними та асинхронними методами в модулі fs?
Синхронні методи (fs.readFileSync
, fs.writeFileSync
):
-
Блокують event loop, поки операція не завершиться.
-
Простий код, але погано для серверних застосунків з багатьма запитами.
Асинхронні методи (fs.readFile
, fs.writeFile
):
-
Виконуються неблокуюче.
-
Результат обробляється через callback, Promise або async/await.
-
Рекомендовані для продакшн-коду.
const fs = require('fs');
// Асинхронно
fs.readFile('data.txt', 'utf8', (err, data) => {
if (err) throw err;
console.log('Async:', data);
});
// Синхронно
const data = fs.readFileSync('data.txt', 'utf8');
console.log('Sync:', data);
-
Синхронні методи підходять для скриптів або ініціалізації під час старту програми.
-
Асинхронні — для роботи сервера, щоб не блокувати інші запити.
25. Як Node.js обробляє HTTP-запити та відповіді?
Node.js використовує вбудований модуль http для створення серверів.
-
Сервер працює в подієво-орієнтованій моделі: на кожен запит генерується подія, яку можна обробити у callback.
-
Об’єкт req (request) містить дані запиту (метод, заголовки, тіло).
-
Об’єкт res (response) використовується для формування та відправки відповіді клієнту.
const http = require('http');
const server = http.createServer((req, res) => {
res.writeHead(200, { 'Content-Type': 'text/plain' });
res.end('Hello from Node.js server!');
});
server.listen(3000, () => {
console.log('Server is running on http://localhost:3000');
});
-
Node.js може обробляти велику кількість одночасних HTTP-запитів завдяки неблокуючій архітектурі.
-
Для складніших застосунків використовуються фреймворки на базі http, наприклад Express.js.
26. Що таке Express.js і чому він важливий для Node.js?
Express.js — це мінімалістичний і гнучкий веб-фреймворк для Node.js.
-
Дає простіший спосіб роботи з HTTP-запитами, відповідями, маршрутизацією, middleware.
-
Значно спрощує розробку REST API та веб-додатків.
-
Зменшує кількість “ручного коду” порівняно з нативним модулем
http
. -
Має велику екосистему middleware для авторизації, логування, обробки JSON, статичних файлів тощо.
-
Де-факто стандарт у Node.js-середовищі для побудови серверних застосунків.
const express = require('express');
const app = express();
app.get('/', (req, res) => {
res.send('Hello from Express.js!');
});
app.listen(3000, () => {
console.log('Server running on http://localhost:3000');
});
У реальних проєктах Express — це "каркас" для швидкої розробки, тоді як чистий http модуль використовують рідко.
27. Як створити RESTful API за допомогою Node.js?
-
Використати Express.js (спрощує маршрутизацію та обробку запитів).
-
Визначити ендпоінти для CRUD-операцій (Create, Read, Update, Delete).
-
Використовувати JSON як формат обміну даними.
-
Опціонально: підключити базу даних (MongoDB, PostgreSQL, MySQL).
const express = require('express');
const app = express();
app.use(express.json());
// Read (GET)
app.get('/users', (req, res) => {
res.json([{ id: 1, name: 'Alice' }]);
});
// Create (POST)
app.post('/users', (req, res) => {
const newUser = req.body;
res.status(201).json(newUser);
});
// Update (PUT)
app.put('/users/:id', (req, res) => {
res.json({ id: req.params.id, ...req.body });
});
// Delete (DELETE)
app.delete('/users/:id', (req, res) => {
res.status(204).send();
});
app.listen(3000, () => console.log('API running on http://localhost:3000'));
-
Кожен ендпоінт відповідає певній операції над ресурсом.
-
Дані передаються у форматі JSON.
-
Легко масштабувати та інтегрувати з базами даних і фронтендом.
28. Що таке middleware у контексті Node.js?
Middleware — це функція, яка виконується між отриманням HTTP-запиту і відправкою відповіді в Express.js або іншому Node.js-фреймворку.
- Вона може змінювати
req
іres
, виконувати логіку (логування, аутентифікація, валідація, обробка помилок) і викликатиnext()
для передачі керування далі.
const express = require('express');
const app = express();
// Кастомне middleware для логування
app.use((req, res, next) => {
console.log(`${req.method} ${req.url}`);
next(); // передати керування наступному middleware/роуту
});
app.get('/', (req, res) => {
res.send('Hello, Middleware!');
});
app.listen(3000, () => console.log('Server running on http://localhost:3000'));
-
Вбудовані (
express.json()
,express.urlencoded()
) -
Сторонні (наприклад,
morgan
,cors
) -
Кастомні (написані вручну під бізнес-логіку)
29. Як забезпечити безпеку HTTP-заголовків у Node.js?
- Використати
helmet
— популярний middleware для Express.js, який автоматично додає та налаштовує безпечні HTTP-заголовки.
const express = require('express');
const helmet = require('helmet');
const app = express();
app.use(helmet()); // додає набір захисних заголовків
- Основні заголовки для безпеки:
-
Content-Security-Policy (CSP) → захист від XSS.
-
X-Frame-Options → запобігає clickjacking.
-
X-Content-Type-Options → блокує MIME sniffing.
-
Strict-Transport-Security (HSTS) → примусове використання HTTPS.
-
Referrer-Policy → контроль витоку інформації у реферері.
Ключова ідея: у Node.js зазвичай не пишуть заголовки вручну — helmet робить це централізовано та безпечно.
30. Як у Node.js обробляються помилки?
- Синхронний код → через
try/catch
:
try {
throw new Error("Something went wrong");
} catch (err) {
console.error(err.message);
}
- Асинхронний код з callback → помилка передається першим аргументом:
fs.readFile('file.txt', (err, data) => {
if (err) {
return console.error("Помилка:", err);
}
console.log("Дані:", data.toString());
});
- Promises → через
.catch()
:
someAsyncTask()
.then(result => console.log(result))
.catch(err => console.error("Помилка:", err));
async/await
→ зtry/catch
:
async function run() {
try {
const data = await someAsyncTask();
console.log(data);
} catch (err) {
console.error("Помилка:", err);
}
}
run();
- Глобальна обробка (як крайній захід):
process.on('uncaughtException', err => {
console.error('Невловлена помилка:', err);
});
process.on('unhandledRejection', err => {
console.error('Невловлене відхилення Promise:', err);
});
Головний принцип: завжди обробляти помилки на місці, а глобальні хендлери використовувати тільки як резервний варіант.
31. Опишіть патерн error-first callback у Node.js.
-
Суть: у Node.js колбеки зазвичай реалізовані у форматі error-first, тобто перший аргумент завжди призначений для помилки, а другий — для результату.
-
Причина: це дозволяє уніфікувати обробку помилок і результатів у асинхронних функціях.
const fs = require('fs');
fs.readFile('file.txt', 'utf8', (err, data) => {
if (err) {
console.error("Сталася помилка:", err);
return;
}
console.log("Файл прочитано:", data);
});
-
Єдиний стандарт для обробки помилок.
-
Проста перевірка: if (err) → зупиняємо виконання.
-
Сумісність із багатьма бібліотеками Node.js.
Недолік: при вкладених колбеках → виникає callback hell, який вирішується Promises або async/await.
32. Які є поширені техніки дебагінгу Node.js застосунків?
-
Консольні логи – console.log, console.error, console.table для швидкого відстеження.
-
Вбудований інспектор – запуск з node --inspect або node --inspect-brk і підключення Chrome DevTools / VS Code Debugger.
-
Debugger statement – додавання debugger; у код, щоб зупинити виконання і проаналізувати змінні.
-
Логування – використання бібліотек (winston, pino) для структурованих логів.
-
unit/integration тести – з jest, mocha, chai для відлову багів на ранніх етапах.
-
Аналіз стек-трейсів – читання помилок і використання Error.stack.
-
Performance профайлінг – node --prof, clinic.js для аналізу продуктивності та memory leaks.
-
Лінтери та статичний аналіз – eslint, typescript для запобігання помилкам.
Коротко: найшвидший старт – console.log та node --inspect, більш системний підхід – логери й тести.
33. Поясніть, що таке process.nextTick() у Node.js.
-
process.nextTick() ставить callback у чергу next tick queue, яка виконується перед переходом до наступної фази event loop.
-
Це означає, що він виконується раніше за setImmediate та setTimeout(0).
-
Використовується для відкладення виконання функції, але без виходу з поточного циклу подій.
console.log("start");
process.nextTick(() => {
console.log("nextTick callback");
});
console.log("end");
start
end
nextTick callback
Добре для асинхронних дій, які потрібно виконати після поточної операції, але перед будь-якими I/O.
Надмірне використання може "заблокувати" event loop, якщо в nextTick постійно ставити нові колбеки.
34. Що таке глобальний об’єкт у Node.js?
-
У Node.js глобальний об’єкт — це global, аналогічний до window у браузері.
-
Він доступний у будь-якій частині застосунку без require.
-
Містить вбудовані об’єкти та функції:
-
process
– інформація про процес -
Buffer
– робота з бінарними даними -
setTimeout
,setInterval
,setImmediate
– таймери -
console
– логування
-
console.log(global.process.platform);
// Виведе платформу (наприклад, 'darwin' або 'linux')
Важливо: краще уникати створення власних глобальних змінних через global, щоб не було конфліктів у коді.
35. Які фреймворки доступні для тестування застосунків на Node.js?
У Node.js існує багато фреймворків і бібліотек для тестування, найпопулярніші:
-
Mocha – гнучкий тестовий фреймворк (часто разом з Chai для assertions).
-
Jest – all-in-one фреймворк від Facebook (асерти, мокінг, coverage).
-
Jasmine – behavior-driven testing, без додаткових бібліотек.
-
AVA – мінімалістичний, паралельне виконання тестів.
-
Supertest – спеціально для тестування REST API (часто з Mocha або Jest).
На практиці найчастіше обирають Jest (через простоту та інтеграцію), або Mocha + Chai + Supertest для більшої гнучкості.
36. Поясніть концепцію мокінгу (mocking) у Node.js.
-
Mocking — це техніка тестування, коли ми імітуємо поведінку залежностей (наприклад, бази даних, API, файлової системи), щоб ізолювати й протестувати лише потрібний модуль.
-
Використовується, коли реальні залежності:
-
повільні (запити до БД чи API),
-
нестабільні (зовнішні сервіси),
-
або не потрібні для конкретного юніт-тесту.
-
// userService.js
const db = require("./db");
exports.getUser = (id) => db.findUser(id);
// userService.test.js
const db = require("./db");
jest.mock("./db");
test("getUser returns mocked user", () => {
db.findUser.mockReturnValue({ id: 1, name: "Test" });
const userService = require("./userService");
expect(userService.getUser(1)).toEqual({ id: 1, name: "Test" });
});
-
Моки допомагають писати швидкі та ізольовані юніт-тести.
-
Для мокінгу у Node.js найчастіше використовують Jest (вбудовано) або Sinon.js.
37. Чому бенчмаркінг важливий у Node.js?
-
Бенчмаркінг — це вимірювання продуктивності коду (швидкість виконання, споживання пам’яті, latency).
-
У Node.js це особливо важливо, бо він працює на однопоточному event loop, і будь-яка повільна операція може заблокувати виконання всієї програми.
-
виявляти вузькі місця (bottlenecks);
-
порівнювати різні реалізації функцій/алгоритмів;
-
прогнозувати масштабованість при рості навантаження;
-
оптимізувати використання CPU та пам’яті.
-
модуль benchmark або perf_hooks у Node.js,
-
зовнішні інструменти (наприклад, Apache Bench, autocannon, Artillery).
38. Як протестувати HTTP-сервер у Node.js?
-
Тестування HTTP-сервера зазвичай роблять за допомогою інтеграційних тестів, які перевіряють відповіді на реальні запити.
-
Основні підходи:
-
Використати вбудований модуль http + бібліотеки для запитів (supertest, axios, node-fetch).
-
Писати тести через фреймворки — Mocha, Jest, Jasmine.
-
Перевіряти статус-код, заголовки, тіло відповіді.
// app.js
const express = require("express");
const app = express();
app.get("/hello", (req, res) => {
res.status(200).json({ message: "Hello World" });
});
module.exports = app;
// app.test.js
const request = require("supertest");
const app = require("./app");
test("GET /hello should return Hello World", async () => {
const res = await request(app).get("/hello");
expect(res.statusCode).toBe(200);
expect(res.body.message).toBe("Hello World");
});
Такий підхід дозволяє запускати сервер у тестовому середовищі, робити HTTP-запити й перевіряти реальні відповіді.
39. Як підключити базу даних MySQL до Node.js?
-
Для роботи з MySQL у Node.js використовують клієнтські бібліотеки, найпопулярніші: mysql2 або sequelize (ORM).
-
Підключення відбувається через створення з’єднання (connection) або пулу з’єднань (connection pool).
-
Далі можна виконувати SQL-запити або працювати через ORM.
const mysql = require("mysql2");
const connection = mysql.createConnection({
host: "localhost",
user: "root",
password: "password",
database: "testdb"
});
connection.connect((err) => {
if (err) {
console.error("Помилка підключення:", err);
return;
}
console.log("MySQL підключено!");
});
// Виконання запиту
connection.query("SELECT * FROM users", (err, results) => {
if (err) throw err;
console.log(results);
});
connection.end();
У продакшні зазвичай використовують пул з’єднань для ефективності й ORM (Sequelize, TypeORM, Prisma) для зручності.
40. Поясніть, як NoSQL бази даних, наприклад MongoDB, можна використовувати з Node.js.
-
MongoDB — документно-орієнтована база даних, яка зберігає дані у форматі JSON-подібних документів (BSON).
-
У Node.js найчастіше використовують бібліотеки:
-
mongodb — офіційний драйвер для роботи з MongoDB.
-
Mongoose — ODM (Object Data Modeling), що додає схеми, валідацію та методи моделі.
-
const { MongoClient } = require("mongodb");
const url = "mongodb://localhost:27017";
const client = new MongoClient(url);
async function run() {
try {
await client.connect();
console.log("MongoDB підключено!");
const db = client.db("testdb");
const users = db.collection("users");
// Створення документа
await users.insertOne({ name: "Alice", age: 30 });
// Читання документів
const result = await users.find({}).toArray();
console.log(result);
} finally {
await client.close();
}
}
run().catch(console.error);
const mongoose = require("mongoose");
mongoose.connect("mongodb://localhost:27017/testdb");
const userSchema = new mongoose.Schema({ name: String, age: Number });
const User = mongoose.model("User", userSchema);
async function run() {
const alice = new User({ name: "Alice", age: 30 });
await alice.save();
const users = await User.find();
console.log(users);
}
run();
-
JSON-подібна структура зручно інтегрується з JavaScript.
-
Висока масштабованість та швидке прототипування.
-
Легка робота з динамічною схемою даних.
41. Яка роль ORM у Node.js?
- ORM (Object-Relational Mapping) — це шар між Node.js і базою даних, який дозволяє працювати з даними як з JavaScript-об’єктами, а не писати чисті SQL-запити.
-
Абстрагування SQL – розробник маніпулює об’єктами, а ORM генерує SQL-запити.
-
Валідація та схема даних – багато ORM підтримують схеми, типи даних і валідацію.
-
Міграції – керування змінами у структурі бази.
-
Взаємозв’язки – легко працювати з зв’язками між таблицями (One-to-Many, Many-to-Many).
-
Sequelize – для SQL баз (MySQL, PostgreSQL, SQLite).
-
TypeORM – підтримує TypeScript, SQL та NoSQL (MongoDB).
-
Prisma – сучасний ORM з генерацією типів TypeScript.
const { Sequelize, DataTypes } = require('sequelize');
const sequelize = new Sequelize('mysql://user:pass@localhost:3306/testdb');
const User = sequelize.define('User', {
name: DataTypes.STRING,
age: DataTypes.INTEGER
});
(async () => {
await sequelize.sync();
await User.create({ name: 'Alice', age: 30 });
const users = await User.findAll();
console.log(users);
})();
Ключова ідея: ORM спрощує роботу з базами даних, підвищує безпеку (захист від SQL injection) і робить код більш читабельним.
42. Як можна моніторити продуктивність Node.js застосунку?
- Вбудовані інструменти:
-
process.memoryUsage()
,process.cpuUsage()
— перевірка використання ресурсів. -
console.time()
/console.timeEnd()
— заміри виконання коду.
- Node.js профайлінг:
-
node --inspect
+ Chrome DevTools → профайлінг CPU/heap. -
clinic.js
(Clinic Doctor, Flame, Bubbleprof).
- Моніторинг у продакшн:
-
APM (Application Performance Monitoring): New Relic, Datadog, AppDynamics.
-
Метрики через Prometheus + Grafana.
-
Логування (Winston, Pino) + централізація логів (ELK stack).
Практика: у великих продакшн-застосунках зазвичай ставлять Prometheus для метрик і Grafana для дашбордів, плюс APM для глибинного трейсингу.
43. Що таке кластеризація (clustering) у Node.js і як вона працює?
-
Призначення: Кластеризація дозволяє Node.js використовувати всі CPU-ядра для масштабування серверних застосунків.
-
Як працює:
-
Node.js за замовчуванням однопотоковий.
-
Модуль cluster створює кілька воркер-процесів, що виконують той самий код.
-
Майстер-процес розподіляє вхідні з’єднання між воркерами.
Практика: дає можливість обробляти більше запитів паралельно без ручного керування процесами.
const cluster = require('cluster');
const http = require('http');
const os = require('os');
if (cluster.isMaster) {
const numCPUs = os.cpus().length;
for (let i = 0; i < numCPUs; i++) {
cluster.fork();
}
} else {
http.createServer((req, res) => {
res.end(`Handled by worker ${process.pid}`);
}).listen(3000);
}
Важливо: кожен воркер має власну пам’ять, тому для обміну даними потрібен IPC або зовнішнє сховище (Redis, DB).
44. Як запобігти витокам пам’яті (memory leaks) у Node.js застосунку?
- Правильне управління подіями:
-
Видаляти непотрібні listeners (emitter.removeListener / emitter.off).
-
Уникати нескінченної кількості підписок.
- Оптимізація замикань:
-
Не тримати посилання на змінні, які більше не потрібні.
-
Очищати таймери/інтервали (clearTimeout, clearInterval).
- Обмеження кешування:
- Використовувати LRU Cache або встановлювати ліміти на збережені дані.
- Моніторинг та профайлінг:
-
--inspect, Chrome DevTools, clinic.js для перевірки heap snapshots.
-
APM (New Relic, Datadog) у продакшн.
- Робота зі стрімами:
-
Завжди використовувати .pipe() замість ручного буферизації.
-
Закривати стріми після використання.
Практика: У великому застосунку ми виявили memory leak через невидалені listeners. Вирішили — використали .once() замість .on для одноразових подій і додали моніторинг heap у продакшн.
45. Поясніть призначення прапорця --inspect у Node.js.
-
Призначення: прапорець --inspect запускає Node.js у режимі налагодження (debug mode).
-
Як працює:
-
відкриває віддалений debug-порт (за замовчуванням 127.0.0.1:9229),
-
дозволяє підключати інструменти для відлагодження (Chrome DevTools, VS Code Debugger).
-
-
Варіанти:
-
node --inspect app.js
— стандартний режим. -
node --inspect-brk app.js
— запускає в debug і одразу ставить breakpoint на першому рядку.
-
node --inspect index.js
- відкриває chrome://inspect у Chrome для налагодження.
Практика: зручно для пошуку memory leaks, профайлінгу CPU, покрокового виконання коду.
46. Як Node.js обробляє багатозадачність (concurrency)?
-
Однопоточна модель: Node.js працює в одному потоці для виконання JS-коду.
-
Event Loop: використовується подієвий цикл для асинхронних операцій (I/O, таймери, мережеві запити).
-
Non-blocking I/O: важкі операції (читання файлів, запити до БД, HTTP) виконуються асинхронно, без блокування головного потоку.
-
libuv thread pool: під капотом Node.js має пул робочих потоків (4 за замовчуванням) для обробки дорогих операцій (наприклад, криптографія, робота з файловою системою).
-
Масштабування: для багатоядерних CPU використовують Cluster API або Worker Threads, щоб запускати кілька процесів/потоків паралельно.
Ключова ідея: Node.js досягає concurrency не через багатопоточність у JS-коді, а завдяки event loop + async I/O + thread pool.
47. У чому різниця між модулями process та child_process у Node.js?
-
process
-
Глобальний об’єкт, що представляє поточний процес Node.js.
-
Дозволяє працювати з аргументами (
process.argv
), середовищем (process.env
), виходами (stdout
,stderr
), завершенням (process.exit()
), ресурсами (process.memoryUsage()
). -
Використовується для керування поточним середовищем виконання.
-
-
child_process
-
Модуль для створення нових процесів із поточного.
-
Методи:
spawn
,exec
,fork
,execFile
. -
Використовується для виконання зовнішніх команд, скриптів чи створення окремих Node.js-процесів.
-
Дає можливість організувати паралельну роботу через окремі процеси.
-
process
= керування поточним процесом.
child_process
= створення й керування новими процесами.
48. Як працюють Worker Threads у Node.js?
-
Призначення: Worker Threads дозволяють виконувати JavaScript-код у паралельних потоках в межах одного процесу Node.js. Це вирішує проблему обмежень однопоточного Event Loop для CPU-інтенсивних задач.
-
Як працює:
-
Кожен Worker має власний Event Loop, пам’ять та виконання.
-
Обмін даними відбувається через message passing (postMessage / on('message')) або SharedArrayBuffer для спільної пам’яті.
-
Основний потік (main thread) створює робітників через модуль
worker_threads
.
-
const { Worker } = require('worker_threads');
const worker = new Worker('./worker.js');
worker.on('message', msg => console.log(`Message: ${msg}`));
worker.postMessage('start');
Ключова ідея: Worker Threads = багатопоточність у Node.js для CPU-heavy задач (наприклад, хешування, обчислення), тоді як I/O краще віддавати Event Loop + async I/O.
49. Як Node.js використовується в мікросервісній архітектурі?
-
Легка вага та швидкість: завдяки асинхронній подієвій моделі Node.js ідеально підходить для побудови сервісів із високою кількістю одночасних з’єднань.
-
API Gateway: часто використовується для створення шлюзів, що агрегують запити до різних мікросервісів.
-
Комунікація між сервісами: реалізація через REST, GraphQL або асинхронні шини повідомлень (Kafka, RabbitMQ, NATS).
-
Docker + Kubernetes: Node.js-сервіси добре контейнеризуються й масштабуються в Kubernetes чи іншому оркестраторі.
-
Інтеграція з базами даних: кожен мікросервіс може мати свою базу (PostgreSQL, MongoDB, Redis), і Node.js забезпечує швидке підключення через драйвери.
-
Практика: Node.js часто застосовують для BFF (Backend For Frontend) — легких API для мобільних і веб-додатків, які взаємодіють із мікросервісами.
Ключова ідея: Node.js у мікросервісах = швидке, асинхронне API, яке добре масштабується й легко деплоїться у хмарі.
50. Поясніть, як відбувається міжпроцесна комунікація (Inter-Process Communication, IPC) у мікросервісній архітектурі на Node.js.
-
Що таке IPC: механізми обміну даними між незалежними процесами/сервісами. У мікросервісах це критично, бо кожен сервіс ізольований.
-
Основні підходи в Node.js:
-
HTTP/REST API – найпростіший спосіб (сервіси спілкуються через HTTP-запити).
-
gRPC – швидша двійкова комунікація з автогенерацією клієнтів і контрактами.
-
Message Brokers (async IPC):
-
RabbitMQ, Kafka, NATS, Redis Pub/Sub.
-
Сервіси публікують/споживають події → loosely coupled архітектура.
- Вбудований IPC у Node.js (child_process, worker_threads, cluster):
- для комунікації між процесами в межах одного хоста через
.send()
іmessage
events.
- WebSockets / Socket.IO: для real-time зв’язку між сервісами чи клієнтом і мікросервісами.
-
Практичний приклад:
- API Gateway (Node.js) приймає запит → кладе подію в Kafka → сервіс-обробник підписаний на цю подію → після обробки повертає результат у базу/чергу.
👉 Ключова ідея: у Node.js мікросервісах IPC реалізується або синхронно (HTTP/gRPC), або асинхронно (message broker, pub/sub). Вибір залежить від вимог до швидкості, надійності й масштабованості.
51. Які є поширені практики безпеки для Node.js застосунків?
- Управління залежностями:
-
Використовувати npm audit, snyk для перевірки вразливостей.
-
Мінімізувати кількість сторонніх пакетів.
- Валідація даних:
-
Використовувати бібліотеки (наприклад, Joi, zod) для перевірки вводу.
-
Захист від SQL/NoSQL інʼєкцій.
- Аутентифікація та авторизація:
-
Використовувати JWT або OAuth2.
-
Реалізувати role-based доступ (RBAC).
- Безпека HTTP:
-
Використовувати helmet для встановлення безпечних заголовків.
-
Примусовий HTTPS (HSTS).
- Захист від XSS/CSRF:
-
Екранування даних перед рендерингом.
-
CSRF-токени (csurf).
- Секрети та конфіг:
-
Зберігати ключі у Vault/Secret Manager, а не в коді.
-
Використовувати змінні оточення (dotenv тільки для dev).
- Rate limiting & захист від brute-force:
- Використовувати express-rate-limit, slow-down.
- Моніторинг та логування:
-
Централізоване логування (Winston, Pino).
-
APM/IDS для відстеження аномалій.
Ключова ідея: головне — мінімізувати вразливості у залежностях, захистити дані користувача й контролювати доступ.
52. Як ви захистите Node.js застосунок від XSS-атак?
- Екранування (escaping) виводу:
-
Завжди екранувати динамічний контент перед рендерингом у HTML.
-
Використовувати шаблонізатори, які автоматично це роблять (наприклад, Handlebars, Pug).
- Content Security Policy (CSP):
-
Додавати CSP-заголовки через helmet.
-
Забороняти inline-скрипти й дозволяти лише whitelist джерела.
- Валідація вводу:
- Використовувати бібліотеки (validator, Joi, zod) для перевірки даних користувача.
- HTTP-заголовки:
- X-XSS-Protection, X-Content-Type-Options, X-Frame-Options.
- Escaping JSON:
- При передачі JSON у HTML завжди конвертувати спецсимволи (<, >, /).
- Уникати eval, new Function():
- Вони можуть дати змогу виконати шкідливий код.
- Для SPA/React/Vue:
- Використовувати безпечні API (dangerouslySetInnerHTML у React тільки з довірою).
Ключова ідея: захист від XSS = валідація вводу + escaping + CSP + безпечні заголовки.
53. Що таке змінні оточення (environment variables) і як їх можна використовувати у Node.js?
Змінні оточення — це ключ-значення, які зберігають конфігурацію додатку поза кодом.
Приклади: PORT, DB_HOST, JWT_SECRET.
Використання у Node.js:
- Доступ через process.env:
const port = process.env.PORT || 3000;
- Для локальної розробки часто використовують пакет dotenv:
require('dotenv').config();
console.log(process.env.DB_HOST);
Навіщо потрібні:
-
Відокремлення конфігурації від коду (12-factor principle).
-
Безпечне зберігання секретів (API keys, tokens).
-
Різні значення для dev / staging / production середовищ.
Ключова ідея: змінні оточення = спосіб зробити застосунок гнучким, безпечним і конфігурованим без змін у коді.
54. Що таке WebSockets і як вони працюють у Node.js?
WebSockets — це протокол для встановлення постійного двонаправленого з’єднання між клієнтом і сервером поверх TCP.
Як працює:
-
Клієнт надсилає HTTP-запит із заголовком Upgrade: websocket.
-
Сервер відповідає підтвердженням, після чого канал "оновлюється" з HTTP → WebSocket.
-
Встановлюється full-duplex з’єднання, де і клієнт, і сервер можуть надсилати повідомлення у будь-який момент.
Node.js реалізація:
-
Вбудованого WebSocket-сервера немає, але використовуються пакети:
-
ws (найпопулярніший lightweight-пакет).
-
socket.io (більш високорівневий, з fallback на long-polling).
-
Приклад із ws:
const WebSocket = require('ws');
const wss = new WebSocket.Server({ port: 8080 });
wss.on('connection', ws => {
ws.on('message', msg => console.log(`Received: ${msg}`));
ws.send('Hello from server!');
});
Ключова ідея: WebSockets у Node.js дають можливість будувати real-time застосунки (чати, ігри, live-нотифікації) з постійним з’єднанням замість постійних HTTP-запитів.
55. Як налаштувати WebSocket-сервер у Node.js?
- Використати пакет ws:
- Це найпопулярніший і легковаговий модуль для WebSocket у Node.js.
- Код прикладу:
// Встановити: npm install ws
const WebSocket = require('ws');
// Створюємо WebSocket-сервер на порту 8080
const wss = new WebSocket.Server({ port: 8080 });
wss.on('connection', ws => {
console.log('Клієнт підключився');
// Отримання повідомлень від клієнта
ws.on('message', msg => {
console.log(`Отримано: ${msg}`);
});
// Відправлення повідомлення клієнту
ws.send('Привіт від сервера!');
});
- Підключення клієнта (у браузері):
const socket = new WebSocket('ws://localhost:8080');
socket.onopen = () => socket.send('Hello Server');
socket.onmessage = event => console.log(event.data);
Ключова ідея: налаштування WebSocket-сервера в Node.js = підключаємо ws, створюємо сервер і слухаємо події connection, message, close.
56. Як задеплоїти Node.js застосунок у продакшн?
- Підготовка застосунку:
-
Оптимізувати код, мінімізувати залежності.
-
Використати process.env для конфігурації (порти, БД, ключі).
- Вибір середовища виконання:
-
PM2 або forever для керування процесами.
-
Docker для контейнеризації.
- Інфраструктура:
-
Хмарні сервіси: AWS, GCP, Azure, DigitalOcean, Heroku, Render.
-
Операційна система: Linux (Ubuntu, Debian).
- Зворотний проксі (reverse proxy):
-
Використати NGINX або Apache для:
-
HTTPS (TLS-термінація).
-
Балансування навантаження.
-
Сервісу статичних файлів.
-
- Масштабування:
-
Використати Cluster API або PM2 cluster mode для багатоядерних CPU.
-
У хмарі — Kubernetes чи Docker Swarm.
- Моніторинг і логування:
- PM2 monit, Winston, Pino, APM (Datadog, New Relic).
Ключова ідея: продакшн-деплой Node.js = керування процесами (PM2), проксі (NGINX), контейнеризація (Docker), моніторинг і масштабування.
57. Що таке PM2 і як його використовують у Node.js?
- PM2 — це менеджер процесів для Node.js, який допомагає запускати застосунки в продакшн.
-
Автоматичний рестарт при падінні застосунку.
-
Cluster mode — запуск кількох інстансів Node.js для використання всіх ядер CPU.
-
Моніторинг: pm2 monit для CPU, пам’яті, логів.
-
Логування: збереження stdout/stderr у файли.
-
Зручне керування: запуск, зупинка, перезапуск процесів.
-
Startup scripts: автостарт після перезавантаження сервера.
# Встановлення глобально
npm install -g pm2
# Запуск застосунку
pm2 start app.js
# Запуск у кластерному режимі на всіх ядрах
pm2 start app.js -i max
# Перегляд статусу
pm2 list
# Моніторинг
pm2 monit
Ключова ідея: PM2 = production-ready process manager для Node.js, що спрощує деплой, масштабування та моніторинг.
58. Поясніть, як ви б використали Docker із Node.js застосунком.
Навіщо Docker:
-
Створює ізольоване середовище з усіма залежностями.
-
Гарантує однакову роботу застосунку на dev/staging/production.
-
Спрощує деплой та масштабування (Kubernetes, Docker Swarm).
Кроки використання:
- Створити Dockerfile:
# Базовий образ
FROM node:18-alpine
# Робоча директорія
WORKDIR /usr/src/app
# Копіюємо package.json та встановлюємо залежності
COPY package*.json ./
RUN npm install --production
# Копіюємо код застосунку
COPY . .
# Виставляємо порт
EXPOSE 3000
# Команда запуску
CMD ["node", "app.js"]
- Зібрати образ:
docker build -t my-node-app .
- Запустити контейнер:
docker run -p 3000:3000 my-node-app
- (Опційно) Docker Compose:
- Використати для підняття Node.js + база даних + кеш разом.
version: '3'
services:
app:
build: .
ports:
- '3000:3000'
depends_on:
- db
db:
image: postgres:15
environment:
POSTGRES_USER: user
POSTGRES_PASSWORD: pass
POSTGRES_DB: mydb
Ключова ідея: Docker із Node.js = ізоляція середовища + легкий деплой + масштабування у хмарі.
59. Як ви керуєте версіонуванням Node.js API?
- URL-версіонування (найпоширеніше):
- Додавання версії в endpoint:
GET /api/v1/users
GET /api/v2/users
- Простий спосіб паралельно підтримувати старі та нові версії.
- Заголовки (Header versioning):
- Версія API передається в HTTP-заголовку:
Accept: application/vnd.myapp.v2+json
- Дає більше контролю, але складніше для клієнтів.
- Query parameters (рідше):
GET /api/users?version=2
- Легко реалізувати, але не RESTful.
- Практики:
-
Використовувати Semantic Versioning (semver) для змін у контрактах.
-
Документувати API (Swagger / OpenAPI).
-
Забезпечити deprecation strategy: попереджати клієнтів про застарілі версії.
Ключова ідея: найкраща практика — версія в URL (v1, v2), бо це просто, зрозуміло й легко підтримувати.
60. Що таке семантичне версіонування (semver) і чому воно важливе у Node.js розробці?
Semantic Versioning (semver) — це система нумерації версій у форматі:
MAJOR.MINOR.PATCH
-
MAJOR – несумісні зміни (breaking changes).
-
MINOR – новий функціонал без порушення сумісності.
-
PATCH – виправлення багів і невеликі зміни без впливу на API.
Приклад:
2.5.3
↑ ↑ ↑
│ │ └─ PATCH (bugfix)
│ └───── MINOR (new feature, backward-compatible)
└───────── MAJOR (breaking changes)
Важливість у Node.js:
- Керування залежностями: npm використовує semver для автоматичного визначення, які версії пакетів можна безпечно оновити.
-
^1.2.3
→ оновлює до останньої MINOR/ PATCH (але не до 2.0.0). -
~1.2.3
→ оновлює тільки PATCH.
-
Прогнозованість: розробники знають, чи зміни можуть зламати застосунок.
-
Командна робота: полегшує оновлення бібліотек у великих проєктах.
-
Довіра до пакетів: чітке версіонування = надійність екосистеми npm.
Ключова ідея: semver = прозорість і безпечність оновлень. Це стандарт, який робить Node.js екосистему стабільною.
61. У чому різниця між exports і module.exports у Node.js?
module.exports
— це реальний об’єкт, який повертається при require().
exports
— це лише посилання на module.exports. Якщо ми змінюємо властивості
через exports.prop = ...
, усе працює. Але якщо ми робимо exports = ...
,
зв’язок рветься, і експортуватись буде лише module.exports
.
Коротко: завжди використовуйте module.exports
для експорту цілого
об’єкта/класу/функції, а exports
— лише для додавання властивостей.
62. Як створити простий TCP-сервер у Node.js?
У Node.js для цього використовується вбудований модуль net
.
-
Створюємо сервер через
net.createServer()
. -
Підписуємось на подію
connection
, щоб обробляти клієнтів. -
Викликаємо
server.listen(port)
для запуску.
const net = require('net');
const server = net.createServer((socket) => {
console.log('Client connected');
socket.write('Hello from server!\n');
socket.on('data', (data) => {
console.log('Received:', data.toString());
});
socket.on('end', () => {
console.log('Client disconnected');
});
});
server.listen(3000, () => {
console.log('TCP server listening on port 3000');
});
63. Що таке REPL у Node.js?
REPL (Read–Eval–Print–Loop) — це інтерактивне середовище Node.js, яке дозволяє писати й одразу виконувати JavaScript-код у консолі.
-
Read: зчитує введений код.
-
Eval: виконує його.
-
Print: показує результат.
-
Loop: чекає наступне введення.
Використовується для швидкого тестування коду, відладки, роботи з API. Запускається командою node у терміналі без параметрів.
64. Поясніть роль реверс-проксі у Node.js застосунках.
Реверс-проксі (наприклад, Nginx або HAProxy) стоїть перед Node.js-сервером і виконує роль посередника між клієнтом та додатком. Основні функції:
-
Балансування навантаження між кількома інстансами Node.js.
-
SSL/TLS термінація — обробка HTTPS, щоб зняти цю відповідальність із Node.js.
-
Кешування та стиснення для зменшення навантаження.
-
Безпека — приховує прямий доступ до Node.js, додає фільтрацію запитів.
-
Маршрутизація — перенаправлення запитів на різні сервіси чи мікросервіси.
Коротко: реверс-проксі робить Node.js-додатки більш продуктивними, безпечними й масштабованими.
65. Як стріми (streams) у Node.js підвищують продуктивність?
Streams дозволяють працювати з даними по частинах (chunk-ами), не завантажуючи весь файл чи відповідь у пам’ять. Це:
-
Економія пам’яті — дані обробляються поступово.
-
Швидший респонс — клієнт може почати отримувати результат ще до завершення всього процесу.
-
Пайплайнінг — можна передавати дані з одного стріму в інший (readable.pipe(writable)), зменшуючи оверхед.
-
Зручна робота з великими файлами/HTTP-запитами.
Коротко: стріми підвищують ефективність і масштабованість, дозволяючи обробляти великі обсяги даних без перевантаження пам’яті.
66. Опишіть деякі популярні фреймворки та бібліотеки в екосистемі Node.js.
-
Express.js — мінімалістичний фреймворк для веб-додатків та API.
-
NestJS — модульний фреймворк з архітектурою, схожою на Angular (TypeScript first).
-
Koa.js — створений командою Express, більш легковаговий і сучасний.
-
Socket.io — для реалізації WebSockets і реального часу (чат, нотифікації).
-
Mongoose — ODM для MongoDB.
-
Sequelize / Prisma — ORM для SQL-баз.
-
Jest / Mocha / Chai — для тестування.
-
Passport.js — аутентифікація та авторизація.
Коротко: Express — дефолт для REST, NestJS — для масштабних проєктів, Socket.io — для real-time, Mongoose/Prisma — для роботи з БД.
67. Чим Koa відрізняється від Express.js?
-
Розробники: Koa створили ті самі автори, що й Express.
-
Архітектура: Koa більш мінімалістичний, ядро маленьке, більшість функцій підключаються як middleware.
-
Async/await: Koa з самого початку спроєктований для роботи з async/await, тому код виглядає чистіше, ніж у Express з callback-ами.
-
Контекст: у Koa є єдиний ctx (context), що поєднує req та res.
-
Middleware: у Koa middleware працює за принципом «洋 цибулини» (onion model), де можна виконати код до і після наступного middleware.
Коротко: Express простіший і з коробки дає більше, Koa — легший, сучасніший і більш гнучкий, але вимагає більше налаштувань.
68. Що таке NestJS і коли ви б обрали його для свого Node.js проєкту?
NestJS — це прогресивний фреймворк для Node.js, побудований на TypeScript. Він базується на модульній архітектурі та використовує концепції з Angular: декоратори, DI (dependency injection), модулі, контролери, сервіси.
-
Для великих корпоративних проєктів з чіткою структурою.
-
Коли потрібна масштабованість і зрозумілий поділ на модулі.
-
Якщо команда працює з TypeScript і знайома з Angular підходами.
-
Для мікросервісної архітектури (NestJS має готові модулі для RabbitMQ, Kafka тощо).
-
Коли важливі тестованість і підтримуваність.
Коротко: NestJS — це вибір для середніх і великих проєктів, де важлива структура, модульність і strong typing.
69. Які переваги використання TypeScript із Node.js?
-
Статична типізація — помилки ловляться ще на етапі компіляції.
-
Кращий автокомпліт і рефакторинг у IDE.
-
Модульність та архітектурна дисципліна — код стає більш структурованим.
-
Сумісність з сучасним JS — TS компілюється у чистий JavaScript.
-
Легше масштабування — великі команди працюють з кодом без хаосу.
-
Інтеграція з популярними фреймворками (NestJS, Angular, React).
Коротко: TypeScript робить Node.js код більш безпечним, зрозумілим і придатним для масштабування.
70. Як ви інтегруєте Node.js застосунок зі стороннім API?
-
Використати HTTP-клієнт: fetch, axios, node-fetch.
-
Організувати сервісний шар (service), який відповідає за виклики до API.
-
Обробити автентифікацію (API keys, OAuth2, JWT).
-
Додати error handling (timeouts, retries, rate limits).
-
Використати кешування для зменшення кількості викликів (наприклад, Redis).
-
Захистити секрети через env-змінні або Vault.
Коротко: робимо окремий сервісний модуль для API, захищаємо ключі, додаємо обробку помилок і кешування для продуктивності.
71. Що таке Socket.IO і як він працює з Node.js?
Socket.IO — це бібліотека для Node.js, яка забезпечує реальний час (real-time) між сервером і клієнтом через WebSockets або fallback механізми.
-
Сервер піднімається через const io = require('socket.io')(server).
-
Клієнт підключається через io.connect().
-
Використовуються події (emit / on) для обміну даними у реальному часі.
-
Підтримує rooms, namespaces, broadcasting, що зручно для чатів, ігор, нотифікацій.
Коротко: Socket.IO додає двосторонній зв’язок real-time поверх Node.js сервера, спрощує WebSocket-роботу і автоматично обробляє fallback.
72. Як можна використовувати GraphQL з Node.js?
GraphQL — це мова запитів і runtime для API, яка дозволяє клієнту запитувати тільки потрібні дані.
-
Використати бібліотеки: graphql, apollo-server, express-graphql.
-
Визначити схему (type definitions) та резолвери для обробки запитів.
-
Сервер отримує запит від клієнта, викликає резолвери і повертає точні дані.
-
Підтримує запити, мутації, підписки (subscriptions) для real-time.
Коротко: GraphQL у Node.js замінює REST API, дозволяє гнучкі запити, мінімізує передачу зайвих даних і спрощує роботу з клієнтом.
73. Як Node.js взаємодіє з фронтенд-фреймворками, такими як Angular або React?
Node.js виступає бекендом, а Angular/React — фронтендом. Взаємодія відбувається через:
-
HTTP API (REST) — фронтенд робить запити (fetch / axios) до Node.js сервера.
-
GraphQL API — фронтенд отримує точні дані за запитом.
-
WebSockets / Socket.IO — для real-time оновлень.
-
Node.js також може бути сервером збірки фронтенду (наприклад, через express.static) або запускати SSR (Server-Side Rendering) для React/Nuxt.
Коротко: Node.js обробляє запити, бізнес-логіку і дані, а фронтенд через HTTP/GraphQL/WebSocket взаємодіє з сервером.
74. Що таке server-side rendering (SSR) і як його реалізувати з Node.js?
Server-Side Rendering — це процес, коли HTML генерується на сервері, а не в браузері, і відправляється готовим клієнту. Це покращує SEO, швидкість первинного рендеру і UX.
-
React SSR: використати ReactDOMServer.renderToString() у Node.js (Express/NestJS).
-
Next.js: фреймворк на Node.js для React з готовим SSR і SSG (Static Site Generation).
-
Angular Universal: для Angular-проєктів SSR через Node.js.
-
Сервер отримує запит, рендерить HTML, відправляє клієнту, а React/Angular потім «гідрує» сторінку.
Коротко: SSR на Node.js робить сторінки швидкими та SEO-дружніми, генерує HTML на сервері замість клієнта.
75. Які існують кодові конвенції та найкращі практики у Node.js?
-
Модульність: розділяти код на окремі модулі, сервіси, контролери.
-
Асинхронність: використовувати async/await замість callback-ів.
-
Обробка помилок: завжди обробляти помилки (try/catch, error middleware).
-
Структура проекту: чітка організація папок (controllers, services, routes, models).
-
Конфігурація через env: секрети та параметри середовища через .env.
-
Логування: використання winston, pino для структурованих логів.
-
Стиль коду: дотримання стандартів (ESLint, Prettier).
-
Безпека: санітизація вводу, Helmet, rate limiting, уникати eval.
-
Тестування: писати unit та integration тести (Jest, Mocha, Supertest).
-
Документація API: Swagger/OpenAPI для REST, GraphQL docs для GraphQL.
Коротко: модульність, асинхронність, обробка помилок, безпека та тестування — ключ до чистого й підтримуваного Node.js коду.
76. Як забезпечити, щоб ваш Node.js застосунок відповідав принципам Twelve-Factor App?
Основні кроки для Node.js:
-
Codebase — один репозиторій для одного застосунку.
-
Dependencies — всі залежності у package.json, встановлюються через npm install.
-
Config — конфігурація через environment variables (process.env).
-
Backing services — підключення до БД, кешу, черг як до ресурсів, які можна змінювати.
-
Build, release, run — розділення етапів: збірка, реліз, запуск.
-
Processes — застосунок запускається як один чи кілька stateless процесів.
-
Port binding — застосунок сам слухає порт (process.env.PORT).
-
Concurrency — масштабування через кілька процесів або контейнерів.
-
Disposability — швидкий старт і graceful shutdown.
-
Dev/prod parity — середовище розробки максимально наближене до продакшну.
-
Logs — логування як потік в stdout/stderr, збір через зовнішні сервіси.
-
Admin processes — одноразові задачі (migrations, скрипти) виконуються як окремі процеси.
Коротко: дотримуватися принципів через env-змінні, stateless процеси, порт-біндінг, централізоване логування і чітку структуру деплою.
77. Що таке лінтінг коду і як його застосовують у Node.js?
Лінтінг — це автоматична перевірка коду на відповідність стилю та виявлення потенційних помилок.
-
Використовують інструменти: ESLint, JSHint, Prettier.
-
Налаштовують правила стилю (airbnb, standard, власні).
-
Інтегрують у IDE або запускають як скрипт (npm run lint).
-
Поєднують з CI/CD, щоб код не потрапляв у репозиторій з помилками.
Коротко: лінтінг забезпечує чистий, підтримуваний код, запобігає помилкам і стандартизує стиль у команді.
78. Які існують стратегії масштабування Node.js застосунків?
-
Кластеризація — використовувати модуль cluster або PM2 для запуску кількох процесів на одному сервері.
-
Load Balancing — розподіл навантаження між кількома серверами через Nginx, HAProxy або cloud LB.
-
Microservices / Service-oriented Architecture — розділити великий моноліт на незалежні сервіси.
-
Horizontal Scaling — додавання нових серверів/контейнерів замість збільшення ресурсів одного процесу.
-
Caching — Redis, Memcached для зменшення звернень до БД та прискорення відповіді.
-
Queue / Message Broker — RabbitMQ, Kafka для асинхронної обробки завдань.
-
CDN для статичних ресурсів — зменшення навантаження на Node.js сервер.
Коротко: масштабування Node.js комбінує кластеризацію, балансування, мікросервіси та кешування для підвищення продуктивності та стійкості.
79. Як керувати сесіями у масштабованому Node.js застосунку?
У масштабованому середовищі не можна зберігати сесію в пам’яті одного процесу. Основні стратегії:
- Centralized session store
-
Зберігати сесії у Redis, Memcached або базі даних.
-
Node.js процеси звертаються до одного спільного сховища.
- JWT (JSON Web Tokens)
-
Сесія зберігається на клієнті у токені.
-
Сервер валідовує токен без необхідності централізованого сховища.
- Sticky sessions (якщо використовуєте load balancer)
-
Балансувальник направляє клієнта завжди на той самий сервер.
-
Менш гнучкий, підходить для невеликих кластерів.
Коротко: у великих системах краще використовувати Redis для централізованих сесій або JWT, щоб забезпечити масштабованість та stateless процеси.
80. Як використання мікросервісів впливає на масштабованість Node.js застосунку?
Мікросервіси розділяють моноліт на незалежні сервіси з власними процесами та БД. Це дає такі переваги для масштабованості:
-
Гранулярне масштабування — можна масштабувати лише ті сервіси, які завантажені найбільше, а не весь застосунок.
-
Незалежний деплой — сервіси можна оновлювати без зупинки інших.
-
Fault isolation — збій одного сервісу не впливає на весь застосунок.
-
Легше інтегрувати нові технології — кожен сервіс може використовувати оптимальні інструменти.
Коротко: мікросервіси підвищують ефективність масштабування і стійкість, але ускладнюють комунікацію та управління інфраструктурою.
81. Що таке черги повідомлень (message queues) і як їх використовують у Node.js?
Message queue — це система для асинхронної обробки завдань через передачу повідомлень між продюсером і консюмером.
-
Для асинхронних завдань (відправка email, обробка файлів, notifications).
-
Для розподілу навантаження між процесами або серверами.
-
Популярні інструменти: RabbitMQ, Kafka, Bull (Redis-based).
-
Node.js сервіс виступає продюсером, який ставить повідомлення у чергу, або консюмером, який обробляє їх.
Коротко: message queues дозволяють Node.js обробляти великі обсяги роботи асинхронно, підвищуючи продуктивність і стійкість.
82. Як реалізувати RabbitMQ у Node.js?
- Встановлення бібліотеки: найчастіше використовують amqplib.
npm install amqplib
- Підключення до RabbitMQ:
const amqp = require('amqplib');
async function connect() {
const connection = await amqp.connect('amqp://localhost');
const channel = await connection.createChannel();
const queue = 'tasks';
await channel.assertQueue(queue);
// Відправка повідомлення
channel.sendToQueue(queue, Buffer.from('Hello RabbitMQ!'));
console.log('Message sent');
// Отримання повідомлень
channel.consume(queue, (msg) => {
if (msg !== null) {
console.log('Received:', msg.content.toString());
channel.ack(msg);
}
});
}
connect().catch(console.error);
- Принцип роботи:
-
Продюсер ставить повідомлення в чергу.
-
Консюмер читає повідомлення і обробляє асинхронно.
-
Підтримує асинхронність, балансування та повторну обробку у разі помилок.
Коротко: RabbitMQ + Node.js дозволяє ефективно реалізувати асинхронну обробку завдань і масштабування через черги.
83. Яке значення має ZeroMQ у Node.js застосунках?
ZeroMQ — це високопродуктивна бібліотека для асинхронного обміну повідомленнями між процесами та серверами.
-
Легка і швидка комунікація між процесами, серверами або мікросервісами.
-
Підтримка різних шаблонів повідомлень: pub/sub, request/reply, pipeline.
-
Не потребує окремого брокера (як RabbitMQ) — P2P-підхід.
-
Використовується для real-time систем, високонавантажених сервісів, розподілених систем.
-
Інтегрується через пакети на Node.js (zeromq / zeromq.js).
Коротко: ZeroMQ в Node.js забезпечує швидкий, легкий і гнучкий обмін повідомленнями, особливо коли потрібна низька затримка і масштабованість без центрального брокера.
84. Як хмарні платформи (AWS, Azure, GCP) полегшують деплой Node.js застосунків?
Хмарні платформи надають готову інфраструктуру для розгортання, масштабування та моніторингу Node.js:
-
Compute: EC2 / Azure VM / GCP Compute Engine для запуску Node.js серверів.
-
Serverless: AWS Lambda / Azure Functions / GCP Cloud Functions для безсерверного виконання коду.
-
Container Services: ECS, EKS, AKS, Cloud Run для запуску Docker-контейнерів Node.js.
-
Load Balancing & Auto Scaling: автоматичне балансування навантаження та масштабування інстансів.
-
Managed Databases & Storage: RDS, DynamoDB, Cloud SQL, S3 для зберігання даних і файлів.
-
CI/CD & Monitoring: CodePipeline, DevOps, Stackdriver, CloudWatch для автоматичного деплою та логування.
Коротко: хмари спрощують розгортання, масштабування, управління і моніторинг Node.js додатків, дозволяючи фокусуватися на бізнес-логіці, а не на інфраструктурі.
85. Що таке serverless-архітектура і як вона пов’язана з Node.js?
Serverless — це модель, де розробник пише код, але не управляє серверами; провайдер хмари автоматично запускає і масштабує функції.
-
Node.js часто використовується для serverless functions (AWS Lambda, Azure Functions, GCP Cloud Functions).
-
Код виконується по запиту (HTTP, події з черги, cron).
-
Платформа автоматично масштабує, платить лише за час виконання.
-
Підходить для API, webhook’ів, обробки подій, асинхронних задач.
Коротко: serverless + Node.js дозволяє швидко запускати функції без управління інфраструктурою, з автоматичним масштабуванням та оплатою за фактичне використання.
86. Як керувати кількома версіями Node.js на одній машині?
- nvm (Node Version Manager) — найпопулярніший інструмент для Linux/macOS:
nvm install 18
nvm use 18
nvm alias default 18
-
nvm-windows — аналог для Windows.
-
Volta — швидкий менеджер версій для Node.js, NPM та Yarn.
-
fnm (Fast Node Manager) — альтернативний легкий менеджер версій.
Коротко: використовують менеджери версій (nvm, Volta, fnm), щоб встановлювати, перемикати і фіксувати версії Node.js для різних проєктів.
87. Що таке .env файли і як вони працюють у Node.js застосунку?
.env
файли зберігають конфіденційні налаштування та змінні середовища (API
ключі, порти, URL баз даних) окремо від коду.
- Використовують пакет dotenv .
npm install dotenv
- Створюють .env файл у корені проєкту:
PORT=3000
DB_URL=mongodb://localhost:27017/mydb
API_KEY=123456
- Підключають у коді:
require('dotenv').config();
console.log(process.env.PORT); // 3000
console.log(process.env.DB_URL);
-
Змінні доступні через process.env.
-
.env
файли не комітять у Git (.gitignore) для безпеки.
Коротко: .env дозволяє зручно конфігурувати застосунок без хардкоду, підтримує різні середовища (dev, prod, test).
88. Опишіть використання модуля config у Node.js.
Модуль config допомагає керувати конфігурацією застосунку для різних середовищ (development, production, test).
- Встановлення:
npm install config
- Створення папки config у корені проєкту:
config/
├─ default.json
├─ production.json
├─ development.json
- Приклад default.json:
{
"port": 3000,
"db": {
"host": "localhost",
"name": "mydb"
}
}
- Використання у коді:
const config = require('config');
const port = config.get('port');
const dbHost = config.get('db.host');
console.log(`Server on port ${port}, DB host: ${dbHost}`);
-
Автоматично вибирає конфігурацію залежно від NODE_ENV (development, production, test).
-
Підтримує структуровані дані, масиви, вкладені об’єкти.
Коротко: config робить керування налаштуваннями централізованим, зручним та безпечним, особливо для різних середовищ і масштабованих Node.js проєктів.
89. Що таке Continuous Integration / Continuous Deployment (CI/CD) і як його реалізувати для Node.js застосунків?
CI/CD — це практика автоматизації збірки, тестування та деплою застосунку, щоб швидко і безпечно доставляти код у продакшн.
- Continuous Integration (CI):
-
Використовують GitHub Actions, GitLab CI, Jenkins, CircleCI.
-
Автоматично:
-
Встановлюють залежності (npm install).
-
Запускають тести (npm test).
-
Перевіряють стиль коду (ESLint).
-
- Continuous Deployment (CD):
-
Після проходження CI, код деплоїться на сервер/хмару.
-
Використовують: AWS Elastic Beanstalk, Heroku, Docker + Kubernetes, сервери через SSH.
-
Можна додати міні-тести на staging, а потім автоперехід у продакшн.
- Бонуси для Node.js:
-
Легко інтегрувати Docker-контейнери.
-
Використовувати npm скрипти для автоматизації.
-
Вбудувати lint, unit/integration тестування та збірку фронтенду (якщо fullstack).
Коротко: CI/CD у Node.js забезпечує швидкий, надійний і автоматизований процес доставки коду, з мінімізацією людських помилок.
90. Як налаштувати CI/CD пайплайн для Node.js проєкту?
Найпростіший підхід на прикладі GitHub Actions:
- Створити конфіг файл .github/workflows/ci-cd.yml:
name: Node.js CI/CD
on:
push:
branches: [main]
pull_request:
branches: [main]
jobs:
build-and-deploy:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
- name: Setup Node.js
uses: actions/setup-node@v3
with:
node-version: '18'
- name: Install dependencies
run: npm install
- name: Run lint
run: npm run lint
- name: Run tests
run: npm test
- name: Build project
run: npm run build
- name: Deploy to server
uses: easingthemes/ssh-deploy@v2
with:
ssh-private-key: ${{ secrets.SSH_KEY }}
remote-user: ubuntu
server-ip: ${{ secrets.SERVER_IP }}
remote-path: /var/www/my-node-app
local-path: .
- Особливості:
-
lint і test перевіряють код на помилки перед деплоєм.
-
build компілює TypeScript/фронтенд.
-
Деплой на сервер через SSH або хмару.
-
Секрети (SSH_KEY, SERVER_IP) зберігаються у GitHub Secrets.
- Можна додати:
-
Стейджинг середовище перед продакшном.
-
Docker-контейнеризацію.
-
Авто-рестарт сервера через PM2.
Коротко: пайплайн автоматизує установку, перевірку, тестування і деплой Node.js додатку при кожному пуші.
91. Як усунути проблеми з повільною роботою Node.js застосунку?
Основні кроки для діагностики та оптимізації:
- Моніторинг ресурсів
- CPU, пам’ять, I/O через top, htop, pm2 monit або APM (New Relic, Datadog).
- Локалізація вузьких місць (bottlenecks)
-
Використовувати профайлінг Node.js (node --inspect, clinic.js, 0x).
-
Аналіз асинхронних операцій та блокуючого коду.
- Оптимізація коду
-
Перевірити блокуючі синхронні операції (fs.readFileSync, цикли з великим обсягом даних).
-
Використовувати стріми для великих файлів або потоків даних.
- Оптимізація запитів до БД
- Використовувати індекси, обмежувати SELECT, кешувати часті запити (Redis).
- Масштабування
-
Кластеризація через PM2/cluster.
-
Балансування навантаження між кількома інстансами.
- Логування та аналіз
-
Логи допомагають знайти повільні запити та довгі обробки.
-
Інструменти: Winston, Pino, ELK stack.
Коротко: профайлінг + аналіз блокуючого коду, оптимізація БД і використання асинхронності + масштабування.
92. Як обробляти завантаження файлів у Node.js застосунку?
- Використання middleware
- Найпопулярніший пакет:
multer
.
npm install multer
- Налаштування Multer:
const express = require('express');
const multer = require('multer');
const app = express();
// Зберігання файлів у папку 'uploads'
const storage = multer.diskStorage({
destination: (req, file, cb) => cb(null, 'uploads/'),
filename: (req, file, cb) => cb(null, Date.now() + '-' + file.originalname)
});
const upload = multer({ storage });
// Маршрут для завантаження одного файлу
app.post('/upload', upload.single('file'), (req, res) => {
res.send('File uploaded: ' + req.file.filename);
});
app.listen(3000);
- Поради та практики:
-
Обмежувати розмір файлу (
limits: { fileSize: 5 * 1024 * 1024 }
). -
Фільтрувати типи файлів через
fileFilter
. -
Зберігати великі файли у хмарні сервіси (S3, Google Cloud Storage).
-
Використовувати асинхронну обробку та стріми для великих файлів.
Коротко: для Node.js завантаження файлів найзручніше реалізувати через Multer, обробляючи валідацію, розмір та місце зберігання.
93. Як обробляти важкі обчислювальні задачі у Node.js застосунку?
Node.js однопотоковий, тому важкі обчислення можуть блокувати Event Loop. Основні стратегії:
- Worker Threads (
worker_threads
)
- Виконання CPU-інтенсивних задач у окремих потоках.
const { Worker } = require('worker_threads');
const worker = new Worker('./heavy-task.js');
worker.on('message', result => console.log(result));
- Child Processes (
child_process
)
- Запуск окремих процесів для паралельних обчислень.
const { fork } = require('child_process');
const compute = fork('compute.js');
compute.send({ data: 1000000 });
compute.on('message', result => console.log(result));
- External services / Queue
- Виносити важкі задачі у черги повідомлень (RabbitMQ, Bull + Redis) і обробляти асинхронно.
- Native addons
- Для надшвидких обчислень використовують C++ addons через N-API або node-gyp.
Коротко: важкі обчислення в Node.js виконують окремими потоками або процесами, або делегують зовнішнім сервісам, щоб не блокувати Event Loop.
94. Яка роль Node.js застосунку у DevOps?
Node.js у DevOps виконує кілька ключових ролей:
- Розробка API та сервісів
- Node.js швидко створює REST/GraphQL API для мікросервісів і бекенд-сервісів.
- Automation / Scripting
-
Використовується для скриптів деплою, CI/CD, моніторингу та інтеграції.
-
Приклади: обробка логів, генерація звітів, управління хмарними ресурсами через SDK.
- Мікросервіси та сервери реального часу
- Node.js підходить для систем сповіщень, обробки черг і подій у DevOps-процесах.
- Інструменти DevOps
- Багато утиліт DevOps (PM2, Serverless Framework, Terraform scripts) використовують Node.js.
- Monitoring & Observability
- Node.js інтегрується з Prometheus, Grafana, Elastic Stack для збору метрик і логів.
Коротко: Node.js у DevOps — це швидкий бекенд для сервісів, автоматизації, скриптів і мікросервісів, який спрощує CI/CD, моніторинг і інтеграцію інфраструктури.
95. Що таке контейнеризація і які її переваги для Node.js застосунків?
Контейнеризація — це процес упаковки застосунку разом з усіма його залежностями та середовищем виконання у ізольований контейнер, який можна запускати на будь-якій машині з підтримкою контейнерів (наприклад, Docker).
-
Консистентність середовища – код працює однаково на локальній машині, staging і продакшн.
-
Ізоляція залежностей – уникнення конфліктів між пакетами та версіями Node.js.
-
Масштабування – легко запускати кілька контейнерів одночасно та балансувати навантаження.
-
Швидкий деплой та rollback – готовий образ можна швидко запустити або відкотити.
-
Легка інтеграція з CI/CD – автоматична збірка і деплой через пайплайни.
-
Контроль ресурсів і безпека – обмеження пам’яті, CPU та мережі контейнера.
Коротко: контейнеризація робить Node.js застосунки портативними, масштабованими, ізольованими та простими у деплої.
96. Як Node.js використовується в IoT (Internet of Things)?
Node.js підходить для IoT завдяки легкому, асинхронному і подієво-орієнтованому виконанню. Основні сценарії:
- Обробка даних з сенсорів у реальному часі
- Node.js швидко отримує дані через TCP, MQTT або WebSockets.
- IoT сервери та шлюзи
- Сервери Node.js збирають дані з пристроїв, обробляють їх і пересилають у бази даних або хмару.
- Підключення до хмарних сервісів
- AWS IoT, Azure IoT Hub, Google Cloud IoT мають SDK для Node.js для керування пристроями і обробки повідомлень.
- Мікросервіси для обробки подій
- Node.js чудово підходить для подієво-орієнтованих сценаріїв: обробка повідомлень від пристроїв через message queues (MQTT, RabbitMQ, Kafka).
- Розробка lightweight клієнтів
- На Raspberry Pi або інших edge-пристроях Node.js використовується для простих контролерів і збору даних.
Коротко: Node.js у IoT забезпечує реальний час, легкі сервери, обробку подій і інтеграцію з хмарою завдяки асинхронній архітектурі.
97. Що слід враховувати при розробці Node.js застосунку для IoT-пристроїв?
При розробці Node.js для IoT важливо враховувати:
- Обмежені ресурси пристрою
- CPU, пам’ять та енергоспоживання обмежені, тому код має бути легким і ефективним.
- Асинхронність і подієво-орієнтована архітектура
- Для обробки великої кількості повідомлень від сенсорів без блокування Event Loop.
- Надійність і обробка відключень
- Потрібна повторна відправка даних, черги повідомлень (MQTT, RabbitMQ) та кешування на edge-пристрої.
- Безпека
- Шифрування повідомлень (TLS/SSL), автентифікація пристроїв, безпечне зберігання ключів.
- Масштабованість та інтеграція з хмарою
- Використовувати хмарні платформи для зберігання та обробки великих потоків даних (AWS IoT, Azure IoT Hub).
- Моніторинг і логування
- Відстеження стану пристроїв, відправка логів і метрик для аналізу та віддаленої підтримки.
- Протоколи зв’язку
- Вибір між HTTP, WebSockets, MQTT, CoAP залежно від частоти і обсягу даних.
Коротко: при Node.js для IoT ключові моменти — легкість, асинхронність, безпека, надійність і масштабованість.
98. Чи можна використовувати Node.js для машинного навчання? Якщо так, то як?
Так, Node.js можна використовувати для машинного навчання, хоча він не є основним середовищем (як Python). Основні підходи:
- JavaScript ML-бібліотеки
-
TensorFlow.js — тренування і інференс моделей прямо в Node.js або в браузері.
-
Brain.js — прості нейронні мережі для класифікації та регресії.
-
Synaptic, ML.js — легкі бібліотеки для експериментів.
- Використання готових моделей
- Node.js може завантажувати попередньо навчені моделі та робити inference (класифікація, NLP, обробка зображень).
- Інтеграція з Python ML-сервісами
- Запуск Python скриптів через child_process або REST API, якщо потрібне тренування великих моделей.
- Edge ML
- Node.js на Raspberry Pi або IoT-пристроях для inferencing легких моделей у реальному часі.
Коротко: Node.js підходить для інференсу, легких ML-моделей та інтеграції з Python ML, а основне тренування великих моделей зазвичай роблять у Python.
99. Які існують бібліотеки або інструменти для машинного навчання у Node.js?
Популярні бібліотеки та інструменти для ML у Node.js:
-
TensorFlow.js – тренування і inferencing нейронних мереж прямо у Node.js або браузері.
-
Brain.js – легкі нейронні мережі для класифікації, регресії, прогнозування.
-
ML.js – базові алгоритми машинного навчання (регресія, кластеризація, PCA).
-
Synaptic – гнучка бібліотека для створення нейронних мереж.
-
Keras.js – inference для моделей Keras у Node.js.
-
ONNX Runtime for Node.js – запуск попередньо навчених моделей у форматі ONNX.
-
Natural – бібліотека для NLP (обробка тексту, токенізація, класифікація).
-
Compromise / wink-nlp – легкі інструменти для NLP задач.
Коротко: Node.js підходить для легких ML завдань, NLP та inferencing, а для тренування великих моделей краще інтегрувати Python-ML сервіси.
100. Які кращі практики для розробки RESTful API у Node.js?
Основні best practices:
- Структура та маршрути
-
Використовувати субстантиви для ресурсів (/users, /orders) і HTTP методи (GET, POST, PUT, DELETE).
-
Використовувати nested routes для пов’язаних ресурсів (/users/:id/orders).
- Статуси HTTP та помилки
-
Відповідати коректними кодами (200, 201, 204, 400, 404, 500).
-
Стандартизовані повідомлення про помилки у форматі JSON.
- Валідація та санітизація даних
-
Використовувати Joi, Yup, express-validator.
-
Захист від некоректних або шкідливих даних.
- Аутентифікація та авторизація
-
JWT або OAuth2 для безпечного доступу.
-
Розділяти ролі та права доступу.
- Пагінація, сортування, фільтри
-
Для GET запитів великих наборів даних.
-
Query-параметри: /users?page=2&limit=20&sort=name.
- Логування та моніторинг
- Winston, Pino для логів, інтеграція з APM (New Relic, Datadog).
- Документація
- Swagger / OpenAPI для опису API, генерації клієнтів та тестування.
- Стандарти та чистота коду
- Використовувати async/await, обробку помилок через middleware, модульність коду.
Коротко: чіткі маршрути, правильні статуси, валідація, безпека, пагінація, логування і документація — ключ до якісного RESTful API у Node.js.