Пошук уроків, статей та іншого контенту
Розберемо складові Node.js Runtime, роль рушія V8 та взаємодію JavaScript із системними API.
Node.js Runtime — це середовище виконання JavaScript поза браузером. Воно дає змогу запускати JavaScript-програми на сервері, у командному рядку та в інших системних середовищах.
У браузері JavaScript взаємодіє з вебсторінкою та API браузера. У Node.js JavaScript може працювати з:
файлами;
мережевими з’єднаннями;
операційною системою;
процесами;
змінними середовища;
потоками даних.
Node.js не є окремою мовою програмування. Це платформа, яка поєднує рушій виконання JavaScript із системними можливостями.
Спрощено Node.js можна уявити як поєднання кількох компонентів:
V8 — виконує JavaScript-код.
Node.js Core API — надає модулі та об’єкти для роботи з файлами, мережею, процесами тощо.
libuv — допомагає виконувати асинхронні операції та взаємодіяти з операційною системою.
Bindings — внутрішній зв’язок між JavaScript-кодом і системними можливостями, реалізованими на нижчому рівні.
Спрощена схема роботи:
JavaScript-код
↓
Node.js API
↓
V8 та внутрішні bindings
↓
libuv і операційна система
↓
Файли, мережа, процеси та інші ресурсиЦя схема спрощена, але вона допомагає зрозуміти загальний напрямок взаємодії.
V8 — це рушій JavaScript, розроблений компанією Google. Він використовується в браузері Google Chrome і в Node.js.
V8 відповідає за:
читання та виконання JavaScript-коду;
створення об’єктів і значень у пам’яті;
оптимізацію виконання коду;
автоматичне очищення пам’яті за допомогою garbage collector.
Наприклад, коли Node.js запускає цей код:
const message = "Hello, Node.js";
console.log(message);V8:
аналізує JavaScript-код;
створює змінну message;
виконує виклик console.log;
передає результат для виведення в термінал через можливості Node.js.
V8 розуміє JavaScript, але сам по собі не надає повноцінного доступу до файлової системи або мережі. Для цього Node.js додає власні API.
Важливо розрізняти V8 і Node.js:
V8 виконує JavaScript;
Node.js додає середовище та API для взаємодії із системою.
Наприклад, метод JSON.parse() належить до стандартних можливостей JavaScript, які реалізує V8:
const text = '{"name":"Olena"}';
const user = JSON.parse(text);
console.log(user.name);А модуль node:fs є API Node.js:
const fs = require("node:fs");
const content = fs.readFileSync("note.txt", "utf8");
console.log(content);V8 не знає, як самостійно відкрити файл операційної системи. Node.js надає для цього модуль fs.
Node.js містить вбудовані модулі, які можна використовувати без встановлення додаткових пакетів.
Приклади:
node:fs — робота з файлами;
node:path — робота зі шляхами;
node:os — інформація про операційну систему;
node:http — створення HTTP-серверів;
node:process — інформація про поточний процес;
node:events — робота з подіями.
Префікс node: явно показує, що використовується вбудований модуль Node.js:
const os = require("node:os");
console.log(os.platform());У сучасному Node.js також можна використовувати синтаксис import, якщо проєкт налаштований для ES-модулів:
import os from "node:os";
console.log(os.platform());У прикладах цього уроку використовується CommonJS-синтаксис із require, який працює у звичайному .js-файлі без додаткового налаштування.
Розглянемо програму, яка:
отримує інформацію про операційну систему;
створює текстовий файл;
читає цей файл;
виводить результат у термінал.
const fs = require("node:fs/promises");
const os = require("node:os");
async function main() {
const fileName = "runtime-info.txt";
const content = [
`Платформа: ${os.platform()}`,
`Архітектура: ${os.arch()}`,
`Версія Node.js: ${process.version}`,
].join("\n");
await fs.writeFile(fileName, content, "utf8");
const savedContent = await fs.readFile(fileName, "utf8");
console.log("Інформація з файлу:");
console.log(savedContent);
}
main().catch((error) => {
console.error("Сталася помилка:", error);
process.exitCode = 1;
});Збережіть код у файл runtime.js і запустіть:
node runtime.jsПісля запуску програма створить файл runtime-info.txt і прочитає його вміст.
Під час виконання:
V8 виконує JavaScript-код.
Node.js надає модулі node:fs/promises, node:os і node:process.
os.platform() та os.arch() отримують дані про операційну систему.
fs.writeFile() передає операцію запису файлу до внутрішніх механізмів Node.js.
Node.js взаємодіє з операційною системою.
Після завершення операції Promise переходить у виконаний стан.
await дозволяє продовжити виконання функції після завершення операції.
V8 виконує наступні інструкції JavaScript.
JavaScript-код не відкриває файл безпосередньо. Він викликає API Node.js, а Node.js організовує взаємодію з операційною системою.
libuv — це внутрішня бібліотека, яку Node.js використовує для асинхронних операцій і роботи з подіями.
Вона допомагає Node.js працювати з такими операціями, як:
читання та запис файлів;
мережеві з’єднання;
таймери;
деякі операції операційної системи.
Завдяки цьому JavaScript-код може запустити операцію, не блокуючи виконання всієї програми на час очікування.
Наприклад:
const fs = require("node:fs");
console.log("Початок");
fs.readFile("note.txt", "utf8", (error, data) => {
if (error) {
console.error("Не вдалося прочитати файл:", error.message);
return;
}
console.log("Вміст файлу:", data);
});
console.log("Кінець");Якщо файл існує, типовий порядок виведення буде таким:
Початок
Кінець
Вміст файлу: ...Виклик fs.readFile запускає операцію читання, але програма не зупиняється на цьому рядку. Після завершення читання Node.js викликає передану функцію.
Операції Node.js можуть бути синхронними або асинхронними.
const fs = require("node:fs");
const content = fs.readFileSync("note.txt", "utf8");
console.log(content);readFileSync блокує подальше виконання коду, доки файл не буде прочитано.
const fs = require("node:fs/promises");
async function readNote() {
const content = await fs.readFile("note.txt", "utf8");
console.log(content);
}
readNote().catch((error) => {
console.error(error.message);
});readFile повертає Promise. Ключове слово await очікує завершення операції всередині асинхронної функції, не блокуючи весь Node.js Runtime.
Для невеликих одноразових скриптів синхронний код іноді є достатнім. У серверних програмах частіше використовують асинхронні API, щоб не блокувати обробку інших запитів.
Між JavaScript і операційною системою є кілька рівнів:
Розробник викликає зрозумілий метод:
await fs.readFile("note.txt", "utf8");Node.js обробляє виклик модуля fs і готує системну операцію.
Node.js використовує внутрішні bindings і libuv для взаємодії з операційною системою.
Операційна система читає файл із диска та повертає результат.
Node.js передає результат назад у JavaScript як значення Promise або викликає callback.
Розробнику зазвичай не потрібно працювати з низькорівневими деталями. Достатньо знати, який API надає Node.js і як обробляти результат або помилку.
Node.js надає кілька глобальних об’єктів, доступних у програмі без імпорту.
processОб’єкт process містить інформацію про поточний процес Node.js:
console.log("Версія Node.js:", process.version);
console.log("Поточна директорія:", process.cwd());
console.log("Аргументи:", process.argv);process.argv містить аргументи командного рядка. Наприклад, для команди:
node app.js helloзначення hello буде одним із елементів process.argv.
consoleconsole використовується для виведення інформації:
console.log("Звичайне повідомлення");
console.error("Повідомлення про помилку");Виведення в термінал також реалізоване Node.js, а не самим стандартом JavaScript у відриві від середовища.
JavaScript-код залежить від середовища, у якому він виконується.
У браузері доступні, наприклад:
window;
document;
DOM API;
localStorage.
У Node.js доступні, наприклад:
process;
require;
модулі node:fs, node:os, node:http;
доступ до файлової системи та мережі.
Наприклад, такий код працює в браузері:
document.querySelector("h1").textContent = "Привіт";А такий код орієнтований на Node.js:
const os = require("node:os");
console.log(os.homedir());V8 може бути присутнім в обох середовищах, але набір доступних API визначає конкретне середовище виконання.
Коли виконується команда:
node app.jsвідбувається приблизно таке:
операційна система запускає процес Node.js;
Node.js налаштовує Runtime;
V8 завантажує та аналізує JavaScript-файл;
виконуються імпорти або require;
виконується код програми;
Node.js обробляє асинхронні операції;
після завершення роботи процес завершується, якщо не залишилося активних операцій.
Наприклад, таймер утримує процес активним до завершення:
console.log("Програма запущена");
setTimeout(() => {
console.log("Таймер завершився");
}, 1000);Node.js не завершує процес одразу після першого console.log, бо в Runtime залишився активний таймер.
V8 лише виконує JavaScript. Доступ до файлів, мережі та процесів надає Node.js.
У Node.js немає DOM за замовчуванням. Об’єкти window і document не є частиною Node.js Runtime.
Файл може не існувати, не мати потрібних дозволів або бути недоступним. Асинхронні операції потрібно обробляти через try...catch, .catch() або callback із перевіркою error.
Основний JavaScript-код виконується послідовно. Асинхронні API дають змогу не блокувати виконання під час очікування системних операцій, а Node.js повідомляє програму, коли результат готовий.
readFileSync зручний у простих скриптах, але тривала синхронна операція блокує подальше виконання JavaScript-коду.
Node.js Runtime запускає JavaScript поза браузером.
V8 відповідає за виконання JavaScript, керування пам’яттю та оптимізацію коду.
Node.js додає API для роботи з файлами, мережею, процесами та операційною системою.
libuv допомагає Node.js виконувати асинхронні операції.
JavaScript взаємодіє із системою через API Node.js, а не безпосередньо.
Браузер і Node.js можуть використовувати V8, але мають різні доступні API.
Асинхронні операції дають змогу не блокувати виконання програми під час очікування системних ресурсів.