Почему React победил в разработке фронтенда, но бэкенд остался мультиязычным.
Почему крупные компании сочетают React с сервисами на Java, Go и Python, а для слоев BFF используют Node.js, вместе с рекомендациями для начинающих разработчиков относительно дальнейшего обучения.
Источники: Why Your Favorite Apps Use React on the Frontend, but Not Node.js on the Backend
React однозначно завоевал лидерство в фронтенде. В бэкенде такого соперника у него не появилось, и те, кто переходит с курсов по MERN-stack в компанию с реальным трафиком, быстро это замечают.
Буткэмпы часто представляют Mongo, Express, React и Node как единое целое: один язык для всей стек-архитектуры, что позволяет создавать полноценные приложения. Прикладные проекты и небольшие реализации с функциями CRUD, кажется, подтверждают это. Однако первая работа в компании с миллионами пользователей показывает совершенно другую картину. Интерфейс, как и ожидается, построен на React. Основные сервисы работают на Java, микросервисы с высокой пропускной способностью — на Go, а пайплайн машинного обучения — на Python. Node.js используется в основном в небольшом слое для агрегации API для фронтенда. В масштабах он выступает в роли вспомогательного инструмента для мощных бэкендов, и причины этого конкретны.
Первая причина: одна потоковая обработка, множество задач
Node.js выполняет JavaScript в одном потоке. Он отлично справляется с операциями ввода-вывода, но одновременно может выполнять только одну задачу, требующую больших вычислительных ресурсов. Представьте ресторан с одним чрезвычайно быстрым официантом: принятие заказов, что соответствует работе с базами данных и сетями, не представляет труда. Но если клиент заказывает блюда из пяти блюд, на приготовление которых уходит тридцать минут — что символизирует работу процессора — этот официант замерзает, в то время как все остальные вынуждены ждать.
Платформа для видео показывает, что это означает в реальных условиях. Пользователь загружает файл 4K, и сервер должен:
- Получить файл.
- Перекодировать его в несколько разрешений, таких как 1080p, 720p и 480p.
- Сгенерировать миниатюры.
- Извлечь метаданные.
- Хранить результаты в соответствующих местах.
Выполнение всего этого внутри процесса Node блокирует его цикл событий. Другие загрузки ожидают, другие запросы к API становятся в очередь, и приложение перестаёт отвечать. Java и Go используют несколько потоков, поэтому один может обрабатывать видео, в то время как другие обслуживают трафик API и задачи аутентификации. Node отлично подходит для задач, зависящих от ввода-вывода, таких как API, реальное время чатов и потоковая передача данных. Задачи, зависящие от производительности CPU, являются его слабым местом, а крупные приложения содержат множество таких задач.
Вторая причина: микросервисы позволяют каждой команде самой выбирать
Крупные компании в основном прекратили создание монолитов. Монолит объединяет в одной базе кода функции аутентификации, оплаты, уведомлений и рекомендаций. Архитектура микросервисов разделяет их на независимые сервисы, которые взаимодействуют друг с другом через сеть.
Такое разделение позволяет каждой команде самостоятельно выбирать язык. Команда, занимающаяся платежами, может выбрать Java из-за его проверенной эффективности в финансовых транзакциях. Команда, отвечающая за реальное время общения, может выбрать Go благодаря его способности поддерживать тысячи одновременных соединений. Команда, разрабатывающая рекомендации, может выбрать Python из-за наличия у него библиотек машинного обучения. Node остается лишь одним из вариантов среди многих и редко становится стандартным выбором.
Почему доминируют Go и Java
Go был создан в Google с целью устранения недостатков более ранних языков. Его преимущества:
- Конкурентность. Горутины позволяют поддерживать огромное количество одновременных соединений при минимальном использовании памяти.
- Запуск. Программы компилируются в нативный машинный код и запускаются практически мгновенно.
- Развертывание. Достаточно одного бинарного файла без зависимостей во время выполнения.
Uber использует его для некоторых из своих самых загруженных сервисов, Twitch — для реального времени чата, а Dropbox сообщил о значительном улучшении производительности после перевода части своей инфраструктуры с Python.
Java уже более 25 лет является стандартом в корпоративном секторе. Он устарел, но надежен:
- Он проверен в банковской сфере, авиакомпаниях и крупных интернет-магазинах.
- Его экосистема включает Spring Boot, Hibernate и тысячи библиотек.
- Статическая типизация позволяет выявлять множество ошибок на этапе компиляции, еще до запуска в производство.
- Инструменты для профилирования, мониторинга и отладки совершенствуются уже десятилетиями.
Netflix, Amazon и Airbnb используют его для ключевых компонентов своего бэкенда. Эти организации нуждаются в надежности в огромных масштабах и не следуют трендам.
Третья причина: наследие и инерция
У крупных компаний долгая история. Amazon была основана в 1994 году, Netflix — в 1997 году, Google — в 1998 году. У них есть миллионы строк кода на языках Java, C++ и Python, инфраструктура, построенная на протяжении десятилетий, а также инженеры, являющиеся экспертами в этих языках. Переписывание кода на Node только потому, что это модно, даже не рассматривается. Технический директор крупной корпорации не станет рисковать платежной системой, той частью бизнеса, которая напрямую приносит доход, ради нового языка только из-за его популярности среди разработчиков в интернете.
Почему React является исключением
Эти же компании приняли React потому, что он решил реальную проблему. До его появления создание сложных интерфейсов было сложным: запутанный jQuery, непонятные паттерны Backbone, цикл обработки данных в Angular 1.x. React ввел архитектуру компонентов, виртуальный DOM для повышения производительности, декларативный подход к интерфейсам и огромную экосистему, включая Next.js и React Native. Он победил, потому что был лучше альтернатив.
У Node.js никогда не было аналогичного обязательного момента применения на сервере. Он хорош и является надежным выбором для определенных задач, но для большинства серьезных задач бэкенда он явно не превосходит Java, Go или Python, поэтому не является автоматическим выбором.
Как строится крупное приложение
Типичная схема представляет собой фронтенд на React, который обращается к шлюзу API, а роутер направляет каждый запрос в соответствующий сервис бэкенда. За ними:
- Сервис Node.js backend-for-frontend обрабатывает логику, специфичную для фронтенда, агрегацию API и события в реальном времени. Именно здесь Node.js показывает себя с лучшей стороны.
- Основные сервисы на Java обрабатывают оплаты, заказы, аутентификацию пользователей и управление запасами — те компоненты, которые не могут выйти из строя.
- Сервисы на Go отвечают за чат в реальном времени, стриминг и любые задачи, требующие высокой конкурентоспособности.
- Сервисы на Python занимаются рекомендациями, обработкой изображений и аналитикой.
Каждый сервис имеет собственные базы данных, и сервисы взаимодействуют друг с другом через gRPC, WebSockets или очереди сообщений, такие как Kafka. У фронтенда есть один явный лидер. Бэкенд мультиязычен, и для выполнения задач выбирается подходящий инструмент.
Краткое сравнение языков
- Node.js подходит для стартапов, MVP и слоев BFF. Разработка происходит быстро, экосистема npm огромна, а разработчиков JavaScript много повсюду. Однако он плохо подходит для обработки видео или финансовых транзакций.
- Java — надежный рабочий инструмент. У него крутой угол обучения и медленный запуск, но его следует выбирать, когда сбои в 3 часа ночи в День чёрной пятницы недопустимы.
- Go — это тот вариант языка бэкенда, который мог бы существовать, если бы его спроектировали заново сегодня: быстрый, простой и поддерживающий одновременную обработку задач. Его недостаток — более молодая экосистема по сравнению с Java.
- Python доминирует в области науки о данных и машинного обучения. Однако для API с высокой конкурентностью Global Interpreter Lock представляет собой серьезное ограничение.
- C++ подходит для сценариев, требующих максимальной скорости, таких как игровые движки, встраиваемые системы и торговля с высокой частотой. Он не предназначен для веб-API.
Что это значит для младших разработчиков
Все это не делает Node плохим выбором. Он по-прежнему остается отличным решением для стартапов и MVP, где важна скорость вывода продукта на рынок, для слоев backend для frontend, для функций реального времени, таких как чаты и обновления в прямом эфире, для безсерверных функций на AWS Lambda или Vercel Edge, а также для прототипов, предназначенных для тестирования идей перед переходом на более сложные технологии.
Те, кто стремится работать в крупных компаниях, не должны полагаться исключительно на технологии MERN. Более полезной привычкой является изучение принципов работы систем, чтобы можно было выбирать подходящий инструмент для каждой задачи. Неверное мнение заключается в том, что знание JavaScript означает способность делать всё.
Самые сильные разработчики не привязаны к одному языку программирования. Один человек может писать код на JavaScript для интерфейса, использовать сервисы на Java при их анализе, понимать, почему команда выбрала Go для микросервиса, и определять, когда Python будет более подходящим решением. Они являются полиглотами из-за понимания того, что разные проблемы требуют разных решений, а не из желания показаться лучше других.
Подходящий инструмент для каждой задачи
React победил в сфере интерфейсов, и каждая крупная компания использует его по веской причине. Бэкенд лучше описывать как экосистему, чем как конкурентную борьбу. У Java, Go, Python, C++, Rust и Node есть свои ниши, и компании, создающие повседневные приложения, не пытаются заменить все на один язык.
Цель разработчика — решать проблемы, а не использовать тот язык, который ему уже знаком, и иногда это означает изучение чего-то нового. Младший разработчик с сертификатом MERN не должен паниковать. Node — отличная отправная точка. Продолжайте в том же духе: изучите проект на Java Spring Boot, напишите небольшой микросервис на Go и выясните, почему платежный сервис компании написан на Java, а не на JavaScript. Лучшие инженеры — это не те, кто знает больше всего языков, а те, кто понимает, зачем существует каждый из них и когда его следует использовать.
Связанные статьи
- Настройка фронтенда на React с использованием Node, npm и Vite — Перенос инструментов в стиле Python на стек React + Vite: установка Node, игнорирование папки node_modules, создание структуры проекта с помощью Vite и запуск локального сервера разработки.
- Что делать за пределами CRUD: десять архитектурных привычек, сохраняющих приложения MERN в рабочем состоянии — Ознакомьтесь с привычками на уровне всей системы, которые помогают поддерживать приложения MERN в хорошем состоянии по мере их роста: ответственность за данные, контракты API, производные состояния, многоуровневый код, компактные пакеты данных и последовательные сообщения об ошибках.