React — всё? Стоит ли переходить на Svelte и SolidJS
А вы тоже в последнее время всё чаще слышите о Svelte и SolidJS? В этой статье рассмотрим, какие у них преимущества перед React, разберемся, для каких типов проектов подходят лучше классических React-решений и стоит ли вообще переходить на них как на основной инструмент разработки.
93 открытий300 показов
React вышел в бородатые времена, когда работа с DOM в сложных проектах была той еще пыткой. Код пестрил событиями и коллбеками, интерфейсы часто содержали повторяющие элементы, но стандартного способа их использовать не было, а синхронизация фронтенда с данными часто приводила к куче ошибок.
Такой код сложно поддерживать: DOM рендерился со скоростью улитки, а засунуть много интерактивных элементов на одну страницу было равносильно самоубийству.
React решил эти проблемы. Разработчики получили виртуальный DOM, который ускорял отрисовку веб-страниц. Благодаря компонентам стало удобнее верстать сайты и веб-приложения, а реактивность помогла эффективнее внедрять интерактивные элементы. Да, рeact действительно крутой, однако он не лишён недостатков в сравнении с некоторыми более новыми фреймворками.
При написании статьи консультировался с Денисом Черновым, ведущим разработчиком платформенной команды Спортмастера (а то я чуть не убил Реакт), а также Мишей Родштейном, руководителем разработки в Дизайн-бюро «Интуиция», и Александром Гузенко, руководителем фронтенд-разработки отдела R&D в крупной европейской компании (к сожалению, под NDA).
Почему разработчики ищут замену React?
Спорный JSX
В обзорных статьях и видео React часто критикуют за JSX код. JSX — это плод любви HTML и JS, который выглядит как HTML, но таковым не является. У нас в JSX коде смешивается логика и верстка. В итоге получаем кашу.
Пример JSX кода:
Такой код немного хуже читается, чем обычные решения на HTML + JS, и может сбивать с толку новичков. Но стоит сделать ремарку, что некоторым разработчикам он нравится.
Виртуальный DOM как устаревший подход к оптимизации
DOM — еще одна крутая фишка React, которая со временем стала недостатком на фоне других фреймворков. Когда пользователь взаимодействует с интерактивным элементом, на его стороне сперва рендерится виртуальный DOM, после чего он сравнивается с главным DOM и перезаписывает данные на сервере.
Этот костыль был создан, чтобы ускорять обновление интерфейсов на стороне клиента, но сейчас есть другие, куда более шустрые подходы. Например, в тех же Svelte и SolidJS виртуальный DOM уже не нужен из-за компиляции, но это так, спойлеры.
Зависимость от сторонних библиотек
Изначально React вышел в свет как библиотека. Он быстро стал популярным, оброс сторонними библиотеками, кто-то его даже называет фреймворком. Но фреймворком его можно считать с большой натяжкой, поскольку при разработке часто приходится устанавливать сторонние библиотеки, а это увеличивает размер проекта и усложняет его поддержку.
В итоге мы получаем крутой инструмент, но с недостатками в виде не самого чистого кода, весомого бандла, зависимости от сторонних библиотек, трудностей в поддержке и не самой быстрой реализации рендеринга DOM.
Краткое знакомство с Svelte и SolidJS
Что такое Svelte: основные принципы, чем выделяется
Производительность из-за компиляции
Философия Svelte сводится к тому, чтобы получать больше за счет меньшего. Как и в случае с React, Svelte не совсем фреймворк. Разработчики позиционируют его как компилятор, и это именно так.
Благодаря компиляции кода, проекты на Svelte получаются более производительными и меньше весят. Здесь не нужны костыли в виде виртуального DOM.
Отсутствие JSX-кода и модифицированный HTML
Код в Svelte пишется на HTML, CSS и JS, причем HTML здесь модифицированный. Например, при верстке мы можем использовать директивы:
- bind: для двустороннего связывания данных (например,
<input bind:value={name} />
). - on: для добавления обработчиков событий (например,
<button on:click={handleClick}>
). - class: для условного добавления классов (например,
<div class:active={isActive}>
).
Вот пример простого кода — он создает интерактивный интерфейс, который реагирует на ввод пользователя и переключение состояния:
Значение в поле ввода связано с переменной name при помощи bind:value
. Когда пользователь вводит текст, значение name обновляется, и это изменение отражается в приветствии ниже.
Инкапсуляция стилей
В Svelte поддерживается инкапсуляция стилей на уровне самого компилятора. Если мы определяем стили внутри компонента, то они будут работать только в рамках него.
Например:
Svelte при компиляции присваивает атрибутам внутри элемента идентификатор — так он реализует инкапсуляцию стилей.
Вот пример идентификатора для тега «p»:
А вот для стилей:
Если нам нужно, чтобы стиль был глобальным, то нужно использовать :global:
Анимации из коробки
Если в react анимации и переходы можно подключить только через сторонние библиотеки, то в Svelte они уже доступны из коробки.
Здесь есть:
- fade — плавное появление/исчезновение элемента за счет изменения прозрачности.
- fly — плавное перемещение элемента с одного места в другое (можно указать направление и расстояние).
- scale — изменение размера элемента, создаёт эффект увеличения или уменьшения.
- slide — плавное скольжение элемента с одного края экрана в другой (например, слева или сверху).
- draw — анимация, которая используется для рисования элементов, например, для SVG-изображений.
- blur — плавное размытие элемента, создаёт эффект фокусировки/размытия.
Пример анимации с использованием fly:
В этом примере элемент будет плавно перемещаться по горизонтальной оси (ось X), когда он появляется на экране.
По умолчанию анимации в Svelte работают локально, внутри компонента, как и стили. Но их можно сделать глобальными при помощи директивы :global:
Встроенные анимации в Svelte — это удобно. Благодаря компиляции они работают быстрее, чем в React, и нам не надо для этого использовать сторонние библиотеки. Хотя такая опция тоже остается.
SolidJS: чем уникален, ключевые особенности
Компиляция вместо VDOM
SolidJS похож на React. Тут тоже есть компоненты, реактивность и JSX. Но в отличие от своего старшего собрата он не поддерживает VDOM. Это здесь просто не нужно по той же причине, что и в Svelte. SolidJS более эффективно компилирует проект в чистый JS-код. В итоге страница рендерится быстрее, чем при работе в React с его виртуальным DOM.
Гранулярная реактивность
Реактивность в SolidJS работает при помощи сигналов. Сигналы хранят в себе данные и отслеживают их изменения. Если данные меняются, то происходит рендер только тех участков компонентов, с которыми эти сигналы связаны. Сам компонент целиком не рендерится в DOM, только его часть.
Пример кода с сигналами:
Здесь мы перерисовываем только элемент с данными внутри кнопки, а не саму кнопку. Так мы избегаем избыточной отрисовки лишних элементов интерфейса и оптимизируем производительность.
Реактивные хранилища
Реактивные хранилища напоминают сигналы, но на максималках. Если сигналы хранят и отслеживают единичные значения, то в хранилищах могут быть другие сигналы, массивы, объекты, обычные переменные, коллекции и состояния.
Пример создания реактивного хранилища:
При помощи реактивных хранилищ нам будет удобнее управлять состоянием и синхронизацией данных в приложении.
Сравнение: Svelte, SolidJS и React
Производительность
Проблемы реактивности в React
Реактивность в React реализована таким образом, что у нас обновляется не весь DOM, а только конкретный компонент через виртуальный DOM. В свое время это было прорывным решением. Если пользователь кликнул по кнопке, то у него изменялся не весь сайт, а только эта кнопка.
С выходом SolidJS и Svelte появились более производительные решения рендеринга интерактивных элементов. Всё благодаря компиляции кода без VDOM. Из-за такой реализации работы с DOM SolidJS и Svelte показывают большую производительность в бенчмарках.
Сравниваем производительность SolidJS, Svelte и React в бенчмарках
Для сравнения фреймворков я взял результаты тестов из бенчмарка js-framework-benchmark results для Chrome 130.0.6723.58. Использовались следующие версии фреймворков:
- Solid 1.8.15
- Svelte 5.0.5
- React 18.2.0
Результаты тестов записаны в миллисекундах. В качестве режима отображения выбрано медианное значение. Когда мы видим запись 38.8 ± 0.2, она означает, что есть погрешность в 0.2 миллисекунды и разброс может быть от 38.6 до 39.
Общая производительность
Видно, что SolidJS — самый производительный из всей троицы. Следом идет Svelte с незначительным отставанием. React гораздо более медленный, в некоторых тестах он многократно уступает другим фреймворкам.
Несмотря на такое существенное превосходство Solid и Svelte над React в производительности, стоит учитывать, что речь идет о миллисекундах. В большинстве проектов такая разница будет не очень заметной.
Работа с памятью
React во всех случаях занимает память ощутимо больше, чем Svelte и SolidJS. Svelte незначительно, но уступает Solid.
Как и в случае с производительностью стоит отметить, что современные устройства вряд ли будут испытывать недостаток памяти при взаимодействии с решениями на этих фреймворках. Исключением могут быть кейсы, когда клиент использует плохое интернет-соединение.
Удобство разработки
Простота синтаксиса
Новичкам удобнее всего будет работать в Svelte. Там используется хоть и модифицированный, но более понятный HTML, CSS и JS. Благодаря этому код выглядит чище и проще.
Еще одно преимущество Svelte — декларативный подход к разработке. Мы просто прописываем, что хотим показать в интерфейсе, а все манипуляции выполняются под капотом.
Вот пример кода на Svelte, который создает простой счетчик:
Такой код выглядит минималистичным, его легко читать и поддерживать.
А вот реализация на JSX в React:
Этот код более массивный, для реактивности приходится использовать useState
и вручную вызывать функцию setCount
, чтобы обновить интерфейса.
Теперь сравним с реализацией в SolidJS:
Здесь реактивность работает из коробки, поэтому код выглядит чуть более удобным, чем в React. Но JSX синтаксис по-прежнему проигрывает в массивности и читаемости.
Svelte более удобный для разработки с точки зрения поддержки, читаемости чем React или Solid. К нему будет проще привыкнуть чем к фреймворкам где используют JSX. SolidJS более компромиссное решение. Здесь все под капотом, поэтому код немного лаконичнее, чем в React, но менее гибкий.
Менеджер состояний
В React управление состоянием традиционно строится на хуках, таких как useState
и useReducer
.
React обновляет компоненты при изменении состояния, используя виртуальный DOM, чтобы определить минимально необходимые изменения в реальном DOM. Это эффективно, но не идеально, так как виртуальный DOM требует дополнительных вычислений.
Переменные в компоненте Svelte до 5-ой версии автоматически становились реактивными. Но с пятой версии мы можем гибко управлять реактивностью при помощи специальных функций — рун.
Рассмотрим более подробно код из предыдущего примера со Svelte:
Здесь мы используем руну state(). Она хранит данные, которые автоматически обновляют интерфейс.
SolidJS использует fine-grained reactivity, подобно Svelte, но с еще более детальным контролем. SolidJS отслеживает зависимости на уровне отдельных переменных, обновляя только те части DOM, которые зависят от изменения переменной.
В этом примере Solid перерисовывает только текст внутри кнопки, а не всю кнопку при изменении данных:
SolidJS более тонко работает с состояниями и реактивностью, чем Svelte и React. Зато в последних есть возможность более гибко их настраивать.
Экосистема, документация и трудоустройство
Зрелость React против развивающихся экосистем
React гораздо популярнее, чем SolidJS и Svelte. По данным Statista, React используют 39.5% веб-разработчиков. По своей популярности он уступает только NodeJS с его 40.8% (судя по данным, опрашиваемые могли выбрать несколько вариантов ответов). Для сравнения у Svelte 6.5%, а у SolidJS — 1.2%.
На React кодят больше. Это значит, что под него проще найти учебные материалы и получить ответы на вопросы на форумах. А у работодателей — более широкий пул кандидатов.
Аналогичная ситуация с библиотеками. Под React проще найти решение, чем под Svelte или Solid. Последние, конечно, тоже развиваются, но в плане размеров комьюнити и числа поддерживаемых библиотек им еще далеко до React.
Документация ко всем трём фреймворкам переведена на русский. В целом при подготовке статьи и сборе материалов чувствовалось, что о React есть много информации на русском, о Svelte меньше, а про SolidJS — в разы меньше.
Трудоустройство
На момент написания статьи React упоминают в 2669 вакансиях на hh.ru. Сотрудников без опыта рассматривают в 128 вакансиях. Кстати, в 270 вакансиях зачем-то хотят высшее образование :)
На Svelte нашлось только 43 вакансии и ни одной без опыта.
По запросу «SolidJS» нашлось 508 вакансий. Но многие из них точно не целевые и подразумевают не этот фреймворк. Пример нецелевой вакансии:
Скорее всего, под SolidJS реальных вакансий будет примерно столько же, как и под Svelte, если не меньше.
Ключевые преимущества для разных задач
Svelte лучше подходит для небольших проектов
Хорошо подойдет для малых и средних проектов благодаря лаконичному коду и производительности.
SolidJS отличный выбор для высоконагруженных интерфейсов
Благодаря более точечной реактивности и компилируемости отлично подходит для проектов с высоко нагруженными интерфейсами.
Например, в дашбордах, графиках или редакторах (аналогичных Figma) SolidJS быстро реагирует на изменения данных, сохраняет плавность интерфейса даже под большой нагрузкой.
React — по-прежнему оптимальное решение, но не всегда лучшее
React все ещё подходит для большинства проектов, просто разработка на нем может быть дольше и сложнее из-за JSX. Также его не стоит использовать для проектов, которые предполагают работу в регионах с плохим интернет-соединением или слабым железом.
Мнения экспертов
Большинство старых проектов Бюро сделаны на экспрессе + разный JS на фронте. Такой стек сложно поддерживать и развивать. Поэтому мы начали делать новые проекты на Свелт. Задача была как можно плавнее перевести ребят с разными навыками на современный стек. В итоге проекты на Свелт запускаются гораздо проще и работают в разы быстрее. Это всех подкупает.
С одной стороны, кайф: все, кто верстают — стали верстать быстрее и проще. С другой стороны, разработчики привыкли к одним паттернам, а в Свелт они другие, и приходится это «ломать».
Что касается действующих проектов, я не вижу смысла переезжать на Свелт с Реакта. Вообще не вижу смысла «на скаку» менять фреймворк. У нас был переезд проекта на Свелт, продлился год, и это было непросто. Но мы уткнулись в ограничения старой системы, и нам нужно было их решать.
Смена фреймворка — слишком большой слом налаженных процессов. Это всегда очень больно и долго, и, как правило, того не стоит.
И Svelte, и SolidJS обгоняют React по скорости и весят меньше. В частности, не последнюю роль в этом играет отсутствие Virtual DOM. Но для меня это важно только как часть кругозора. Если у вас в приложении наблюдаются проблемы с производительностью на React, с огромной долей вероятности в этом виноват плохой код, а не сама библиотека. Да, Реакт практически обязывает тащить за собой кучу дополнительных библиотек на все случаи жизни, которые также могут быть проблемой в производительности. Но в целом разница в скорости в пару десятков миллисекунд незаметна. Если у компании/команды есть экспертиза в React и его экосистеме — переходить на другие инструменты без сильной причины (просто для более красивых циферок) не вижу смысла.
Совсем другое дело, когда вы заранее знаете, что ваше приложение обещает быть тяжелым с точки зрения нагрузки или у конечных пользователей слабое железо (например, если вы выпускаете приложение на рынки Африки или Индии, для вас это актуально, тем более если им будут пользоваться с мобильных устройств). Но и здесь я бы не стал слепо отказываться от React’a — у него всё же есть много совместимых библиотек, легче найти решение проблемы. А вот с другими инструментами дела могут обстоять иначе, и не факт, что в лучшую сторону. Да, вы можете получить выигрыш в циферках производительности и веса сборки, но можно наступить на много граблей во время разработки, что сведет все преимущества на нет.
В целом я считаю важным периодически осваивать новые фреймворки и библиотеки, такие как Svelte и SolidJS. У них есть свои преимущества, и о них важно знать. Так, в моменты, когда стоит реализовать именно эти преимущества, вы сможете проявить себя, предложив новый инструмент. Более того, это позволяет поддерживать свой кругозор, как специалиста, и осваивать новые подходы. Рано или поздно эти знания могут пригодиться и в проектах на том же самом React или в любом другом решении. Просто знать, что можно и как разрабатывать — сильно повышает экспертизу разработчика!
Стоит ли уходить с React?
Зависит от проекта и ваших личных планов. Новичкам лучше оставаться на React — под него заточено большинство вакансий. Проект под SolidJS или Svelte будет найти сложнее, а на React уже написано много решений, которые надо поддерживать.
Для более опытных разработчиков Svelte будет лаконичным выбором, если они работают с небольшими проектами, но, опять же, React здесь тоже сгодится. SolidJS подойдет для создания веб-приложений и сайтов с высоконагруженными интерфейсами.
Тем, кто работает над новыми крупными проектами или поддерживает старые, лучше остаться на React. У него большое комьюнити и много библиотек. Да, он уступает другим библиотекам в производительности, но это отставание в большинстве проектов не будет критичным.
А какие фреймворками для разработки интерфейсов используете вы?
93 открытий300 показов