Чому 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, чат у реальному часі та передача даних. Завдання, залежні від процесора, є його слабкою стороною, а великі додатки містять багато таких завдань.
Друга причина: мікросервіси дозволяють кожній команді самостійно вибирати
Великі компанії переважно припинили створювати моноліти. Моноліт об’єднує функції автентифікації, оплат, сповіщень та рекомендацій у одну базу коду. Архітектура мікросервісів розділяє їх на незалежні сервіси, які взаємодіють через мережу.
Це розділення дозволяє кожній команді обирати мову на свій розсуд. Команда з операціями оплати може обрати 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 лише через те, що це модно, не розглядається. CTO великої корпорації не буде ризикувати системою оплат, яка безпосередньо приносить дохід, через нову мову лише тому, що вона популярна серед розробників у Інтернеті.
Чому React є винятком
Ці самі компанії обрали React тому, що він вирішив реальну проблему. До його появи створення складних інтерфейсів було складним: заплутаний jQuery, заплутані патерни Backbone, цикл обробки даних у Angular 1.x. React приніс архітектуру компонентів, віртуальний DOM для покращення продуктивності, декларативний підхід до інтерфейсів та величезну екосистему, що включає Next.js та React Native. Він переміг, тому що був кращим за альтернативи.
У Node ніколи не було еквівалентного критичного моменту на сервері. Це гарний та надійний вибір для певних завдань, але для більшості серйозних завдань на бекенді він не є явно кращим за Java, Go чи Python, тому не є автоматичним вибором.
Як будується велика додаток
Типова схема включає фронтенд на React, який звертається до API-шлюза, а роутер направляє кожен запит до відповідного сервісу бекенду. За ними:
- Сервіс Node.js backend-for-frontend обробляє логіку, специфічну для фронтенду, агрегацію API та події в реальному часі. Саме тут Node проявляє себе найкраще.
- Основні сервіси на 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, похідний стан, багатошаровий код, легкі пакети даних та послідовні помилки.