Node.js
| Автор | Райан Дал |
|---|---|
| Первый выпуск | май 2009 |
| Разработчик | OpenJS Foundation |
| Движок | V8 (Google) |
| Библиотека ввода-вывода | libuv |
| Написан на | C++, JavaScript |
| Модель | однопоточный цикл событий, неблокирующий I/O |
| Пакетный менеджер | npm |
| Цикл выпусков | чётные версии получают LTS (30 месяцев поддержки) |
| Лицензия | MIT |
Node.js — среда выполнения JavaScript вне браузера, построенная на движке V8 из Google Chrome и библиотеке асинхронного ввода-вывода libuv. Node.js позволяет писать на JavaScript веб-серверы, утилиты командной строки и инструменты сборки; на нём работают npm, сборщики фронтенда и большинство генераторов статических сайтов. Ключевая черта — неблокирующая модель: один поток обслуживает тысячи соединений, не дожидаясь окончания медленных операций.[1]
История
Райан Дал представил Node.js на конференции JSConf EU в 2009 году.[6] Его мотивом была неэффективность серверов «поток на соединение» (как у Apache того времени) при большом числе медленных клиентов: вместо этого Node.js опирался на цикл событий, а JavaScript подходил идеально — в языке не было блокирующего ввода-вывода и уже была культура колбэков. В 2010 году появился пакетный менеджер npm. В 2014-м часть разработчиков, недовольных темпом развития под управлением компании Joyent, создала форк io.js; в 2015 году проекты объединились под эгидой Node.js Foundation (ныне OpenJS Foundation). Сам Дал в 2018 году представил Deno — альтернативу, исправляющую, по его словам, ошибки дизайна Node.js; позже появилась ещё одна среда — Bun.
Архитектура
- V8 компилирует JavaScript в машинный код (JIT).
- libuv реализует цикл событий и абстрагирует системные механизмы асинхронности — epoll в Linux, kqueue в macOS, IOCP в Windows; операции, у которых нет асинхронного системного API (файловая система, DNS-резолвинг, сжатие), выполняются в пуле потоков.[4]
- Привязки на C++ и стандартная библиотека на JavaScript:
fs,http,net,crypto,stream,child_process,worker_threads.
Цикл событий
Код пользователя выполняется в одном потоке. Когда программа запрашивает ввод-вывод, Node.js передаёт операцию libuv и продолжает выполнение; по готовности колбэк попадает в очередь. Цикл проходит фазы: таймеры (setTimeout), ожидающие колбэки, опрос ввода-вывода (poll), setImmediate, закрытия. Между фазами выполняются микрозадачи — разрешённые промисы и process.nextTick.[2] Отсюда главное правило: не блокировать цикл событий. Тяжёлые вычисления (хеширование, разбор большого JSON) останавливают обработку всех запросов, их выносят в worker_threads или отдельные процессы. Подробнее модель асинхронного кода — в статье Промисы и async/await (JS); сходный подход в Python — asyncio.
Пример
// server.mjs — минимальный HTTP-сервер без зависимостей
import { createServer } from "node:http";
import { readFile } from "node:fs/promises";
const server = createServer(async (req, res) => {
if (req.url === "/") {
const html = await readFile("index.html");
res.writeHead(200, { "Content-Type": "text/html; charset=utf-8" });
res.end(html);
} else {
res.writeHead(404).end("not found");
}
});
server.listen(3000, () => console.log("http://localhost:3000"));
node server.mjs
node --watch server.mjs # перезапуск при изменении файлов
node --test # встроенный тест-раннер
Модули
Исторически Node.js использовал систему модулей CommonJS (require, module.exports). С версии 12 поддерживаются стандартные ES-модули (import/export), которые включаются расширением .mjs или полем "type": "module" в package.json. Сосуществование двух систем долго было источником путаницы; в современных версиях ES-модуль можно подключить и через require().
Версии и экосистема
Новая мажорная версия выходит каждые полгода; чётные версии становятся LTS и поддерживаются 30 месяцев, нечётные живут около полугода.[3] За последние годы в ядро вошло многое, что раньше требовало пакетов: fetch, WebSocket-клиент, тест-раннер, режим --watch, загрузка .env-файлов, запуск TypeScript без компиляции и модель разрешений (--permission), ограничивающая доступ к файлам и сети.[5]
Популярные серверные фреймворки — Express, Fastify, NestJS, Hono; полностековые — Next.js, Nuxt, Astro. В продакшене Node.js обычно запускают за обратным прокси и в Docker-контейнере.