Признаюсь честно: однажды я построил рабочий API, используя только основные модули Node.js. Когда коллеги это увидели, их реакции варьировались от «Ты просто маньяк!» до «Погоди… это и правда работает?». Спойлер: всё работало. Хотя такие фреймворки, как Express или NestJS, — это замечательная страховка, иногда только отказ от них помогает понять, как всё работает на самом деле.
Скрытые издержки удобства фреймворков
Потеря производительности
Фреймворки включают в себя всё, что только можно представить. Тот самый Express-приложе́ние «hello world» размером в 40 КБ? Вот версия на голом Node.js:
const http = require('http');
const server = http.createServer((req, res) => {
res.end('Hello Framework-Free World!');
});
server.listen(3000);
Это 5 строк кода против 15+ в Express. Для микросервисов с высокой нагрузкой такое различие накапливается, как проценты на ростовщической конвенции.
Иллюзия продуктивности
Фреймворки обещают скорость, но отладка сбоев в парсинге req.body
в 2 часа ночи кажется разгадыванием загадок для сфинкса. Из жизни: однажды я потратил 3 часа на отладку конфликта промежуточного ПО в Express, что заняло бы 10 минут с нативным http
.
Опасность атрофии навыков
Полагаться на ReactDOM.render()
, не понимая DOM, — это как использовать кухонный комбайн для нарезки клубники. Когда во время недавнего проекта произошёл сбой в системе синтетических событий React, наше общее молчание на вопрос «Как на самом деле работает всплытие событий в браузере?» было оглушительным.
Когда стоит писать код без фреймворков
Сценарий 1: Микросервисы на стероидах
Создаёте высокопроизводительный аналитический эндпоинт? Сравните:
Подход | Запросы/сек | Использование памяти |
---|---|---|
Express.js | 8 500 | 45 МБ |
Нативный Node.js | 14 200 | 28 МБ |
(Тестировалось на AWS t3.micro, Node 21) |
Нативная версия использует всего 3 модуля: http
, url
и querystring
. Без body-parser
, без cookie-session
, без 57 зависимостей node_modules
.
Сценарий 2: Изучение устройства
Попробуйте такой вызов: создайте REST API без какого-либо фреймворка, а затем воссоздайте его с Express. Этот процесс покажет, что абстрагируют фреймворки — как будто вы видите матрицу за цифровым дождём.
Пошаговое нативное маршрутизирование
- Парсинг URL вручную:
const { pathname, query } = new URL(req.url, `http://${req.headers.host}`);
- Обработка маршрутизации становится явной:
if (pathname === '/users' && req.method === 'GET') {
// Получение пользователей из БД
}
- Промежуточное ПО? Просто функции:
const logger = (req, res, next) => {
console.log(`${new Date().toISOString()} - ${req.method} ${req.url}`);
next(req, res); // Ручной вызов next()
};
Искусство стратегического бунта
Практическое правило
Если в вашем проекте меньше 5 маршрутов и в следующем квартале вам не понадобятся GraphQL/Auth0/WebSockets, пропустите фреймворк.
Исключения, подтверждающие правило
- Создаёте корпоративное SaaS? Используйте фреймворк.
- Срок сдачи через 48 часов? Используйте фреймворк.
- Изучаете WebSockets? Сначала напишите свой, а затем используйте Socket.io.
Заключение: примите осознанную примитивность
Фреймворки похожи на GPS: они прекрасны для неизведанной территории, но иногда нужно ориентироваться по звёздам, чтобы вспомнить, как соединяются континенты. В прошлом месяце наша команда создала WebSocket-сервер без библиотек. Первоначальное разочарование было настоящим, но обнаружение элегантности net.createServer()
было как находка секретной двери в доме детства.
Так что в следующий раз, когда будете выполнять npm install
, спросите себя: «Нужен ли мне этот парашют для прыжка в подвал?» Иногда сырой код не просто легче — он освобождает.