О насБлогКонтакты
Backend разработка15 декабря 2009 г. 5 мин 131Обновлено: 18 мая 2026 г.

Node.js: JavaScript на сервере (2009)

AunimedaAunimeda
📋 Содержание

Node.js: JavaScript на сервере (2009)

В 2009 году стандартный способ написать веб-сервер выглядел так: Apache + PHP, или Tomcat + Java, или Nginx + Python/Ruby. Каждый запрос получал поток из пула. Поток блокировался на I/O - чтении файла, запросе к БД, ожидании сети. Пока поток ждал, он потреблял память (~1MB на поток в Java) ничего не делая.

Это работало. Но при тысячах одновременных соединений - проблема C10K: 10 000 одновременных клиентов требовали 10GB RAM только на потоки.

Райан Даль думал об этой проблеме два года. Его ответ: никаких потоков. Один поток. Event loop. Всё I/O - неблокирующее, через колбэки.

И язык для этого уже существовал. JavaScript из браузера - он и так был однопоточным с event loop. V8 2008 года сделал его достаточно быстрым. Оставалось добавить API для файловой системы, сети, и процессов.


Hello World: 10 строк, 10 000 соединений

// Именно это Даль показал на JSConf EU 2009

var http = require('http');

var server = http.createServer(function(req, res) {
    res.writeHead(200, {'Content-Type': 'text/plain'});
    res.end('Hello World\n');
});

server.listen(8000);
console.log('Server running at http://127.0.0.1:8000/');

// Это - полный веб-сервер.
// Не конфигурационный файл Apache.
// Не XML дескриптор деплоя Tomcat.
// 10 строк JavaScript.

// Тест производительности (Ubuntu, EC2 small, 2009):
// Apache (prefork):  ~1000 req/sec при 1000 concurrent connections, 150MB RAM
// Node.js 0.1:       ~4000 req/sec при 1000 concurrent connections, 15MB RAM

Почему event loop решает C10K

// Традиционный подход - блокирующий I/O:
// (псевдокод, показывающий проблему)

// Поток 1:
var data = fs.readFileSync('big-file.txt');  // СТОП. Поток заблокирован.
response.send(data);                          // Только после этого

// Поток 2 (параллельно, отдельный поток ОС):
var result = db.querySync('SELECT * FROM users');  // СТОП.
response.send(result);

// При 10000 соединениях: 10000 потоков, большинство - просто ждут.

// Node.js - неблокирующий:
fs.readFile('big-file.txt', function(err, data) {
    // Колбэк вызовется когда файл прочитан.
    // Пока файл читается - event loop обрабатывает ДРУГИЕ запросы.
    response.end(data);
});
// Выполнение продолжается НЕМЕДЛЕННО.
// Один поток, но ничего не ждёт впустую.

// Наглядная аналогия, которую использовал Даль:
// Официант в ресторане.
// Плохой официант: принял заказ → стоит на кухне и ждёт → приносит еду.
// Хороший официант: принял заказ → передал на кухню → обслуживает других столиков → 
//                   получил сигнал "готово" → приносит еду.
// Node.js - хороший официант.

Первый Express.js: маршрутизация (2009)

TJ Holowaychuk создал Express.js в конце 2009 года - Rails/Sinatra-подобный фреймворк для Node:

// Express 0.x - декабрь 2009
// npm install express (npm появился одновременно с Node 0.1)

var express = require('express');
var app     = express.createServer();

// Маршруты:
app.get('/', function(req, res) {
    res.send('Главная страница');
});

app.get('/users/:id', function(req, res) {
    var userId = req.params.id;
    // В 2009 - ещё без callback hell middleware
    // Но уже с params - лучше чем парсить URL вручную
    res.send('Пользователь ' + userId);
});

app.post('/api/data', function(req, res) {
    // req.body - только если подключён bodyParser middleware
    res.json({ status: 'ok', data: req.body });
});

app.listen(3000);

// Весь REST API - в одном файле, без XML, без конфигов.
// Для разработчика 2009 года, привыкшего к web.xml - магия.

npm: менеджер пакетов (тоже 2009)

// npm 0.0.1 - Айзек Шлютер, 2009
// Концепция: пакеты с зависимостями, локально в node_modules/

// package.json - структура которую мы используем сегодня:
{
    "name": "my-app",
    "version": "0.0.1",
    "description": "Мой Node.js сервер",
    "dependencies": {
        "express": "0.9.0"
    }
}

// Команды 2009 года:
// npm install express     - установить в ./node_modules
// npm publish             - опубликовать пакет
// npm search express      - найти пакеты

// Принципиальное отличие от CPAN (Perl) и RubyGems:
// Зависимости локальны для проекта, не глобальны.
// Проект A и проект B могут иметь разные версии express.
// Это решило "dependency hell" который мучил Ruby/Python-разработчиков.

// К 2013 году npm стал крупнейшим реестром пакетов в мире.
// К 2023 - более 2 миллионов пакетов.

Callback-модель и её проблемы (видные уже в 2009)

// Паттерн 2009 года - вложенные колбэки
// Читать файл → парсить JSON → запрос к БД → ответ

var fs = require('fs');

fs.readFile('config.json', 'utf8', function(err, data) {
    if (err) {
        console.error('Ошибка чтения конфига:', err);
        return;
    }

    var config;
    try {
        config = JSON.parse(data);
    } catch(e) {
        console.error('Невалидный JSON:', e);
        return;
    }

    var db = require('mysql').createClient({
        host:     config.db.host,
        user:     config.db.user,
        password: config.db.password
    });

    db.query('SELECT * FROM users WHERE active = 1', function(err, results) {
        if (err) {
            console.error('Ошибка БД:', err);
            db.end();
            return;
        }

        // Ответ после двух async операций
        res.json({ users: results });
        db.end();
    });
});

// Это называли "callback hell" или "pyramid of doom".
// Решение появилось позже: Promises (2011), async/await (2017).
// В 2009 году это был единственный способ - и большинство
// программистов считали это нормальным.

Контекст: почему именно сейчас

Node.js не мог существовать в 2005 году. V8 (2008) дал производительность. Но важен и контекст:

Ajax-приложения 2005-2008 создали задачи, которые плохо ложились на традиционные серверы: длинные HTTP-соединения (Comet), real-time обновления, сотни параллельных WebSocket-соединений. PHP/Apache был рождён для request-response, не для persistent connections.

JSON как стандарт - к 2009 году сервер возвращал JSON, браузер потреблял JSON. JavaScript на клиенте и сервере означал: один формат данных, нет конвертации, нет несоответствий типов.

V8 дал скорость. Без V8 Node.js на SpiderMonkey 2007 года был бы нежизнеспособен.

Всё это сошлось 8 ноября 2009 года в Берлине.


Что Node изменил в следующие два года

Node.js не стал заменой PHP или Java для монолитных приложений. Он нашёл нишу:

  • API-серверы с высоким concurrency и низкой вычислительной нагрузкой
  • Real-time: чаты, игры, коллаборативные инструменты
  • Streaming: обработка больших файлов без загрузки в память
  • Microservices (термин появился позже, паттерн - уже тогда)

К 2011 году Node.js использовали LinkedIn (мобильный бэкенд), Yahoo!, и сотни стартапов. Ryan Dahl ушёл из проекта в 2012-м - к тому моменту Node жил без него.

Самое важное, что сделал Node: доказал что JavaScript - серьёзный язык для серверной разработки. Не «скриптовый язык для браузера», а язык. Это изменило то, как индустрия думала о JavaScript навсегда.

Читайте также

Чистая архитектура в Node.js: практическое руководство без академизмаaunimeda
Backend разработка

Чистая архитектура в Node.js: практическое руководство без академизма

Чистая архитектура звучит хорошо в теории. На практике большинство реализаций добавляют сложность без пользы. Показываем паттерн, который реально работает в production Node.js TypeScript проектах - инверсия зависимостей, use cases, repository pattern с рабочим кодом.

Node.js vs Bun vs Deno 2026: какой JavaScript runtime выбратьaunimeda
Backend разработка

Node.js vs Bun vs Deno 2026: какой JavaScript runtime выбрать

Bun 1.x стабилен в production. Deno 2.0 поддерживает npm. Node.js 22 запускает TypeScript нативно. Реальные бенчмарки, сравнение экосистем и конкретные рекомендации - для новых и существующих проектов.

WebSocket-сервер на 100,000 соединений: архитектура и реальные подводные камниaunimeda
Backend разработка

WebSocket-сервер на 100,000 соединений: архитектура и реальные подводные камни

Как масштабировать WebSocket от 100 до 100k+ соединений: uWebSockets.js vs ws, Redis Pub/Sub между инстансами, heartbeat и reconnect логика, memory leak на неочищенных обработчиках.

Нужна IT-разработка для вашего бизнеса?

Разрабатываем сайты, мобильные приложения и AI-решения для бизнеса в России. Бесплатная консультация.

Разработка Telegram-ботов

Получить консультацию Все статьи