- PVSM.RU - https://www.pvsm.ru -
Современный фронтенд шагнул далеко вперед со времен jQuery и обычных HTML страничек. У нас появились сборщики, менеджеры пакетов, компонентный подход, SPA, SSR и много еще чего.
Кажется, что у нас есть все, что нужно для счастья. Но индустрия двигается вперед. Я хочу вам рассказать о компилируемом фреймворке Svelte [1], и какие преимущества у него есть перед аналогами.
Автор изображения Andrew Walpole [2]
Для понимания текущей ситуации во фронтенде я проанализировал популярность запросов в Google Trends [3] по ключевым словам React, jQuery, Vue, Angular в России за последние 5 лет.
Google Trends
За последние 5 лет количество запросов, связанных с jQuery значительно сократилось, уступив место компонентным фреймворкам. Хотя jQuery и сдал позиции, он до сих пор остается популярным средством разработки.
Из этого графика можно сделать вывод, что компонентные библиотеки победили во фронтенде, а лидером в России является React.
Мы пишем код не только для себя, но и за деньги. В основном за деньги. Поэтому рассматривать популярность фреймворков в отрыве от рынка труда глупо.
По количеству вакансий на hh первое место занимает React, за ним следует jQuery и другие компонентные библиотеки. Если мы посмотрим на количество соискателей, которые указали в ключевых навыках рассматриваемые библиотеки, то jQuery знают в 5 раз больше соискателей, чем React. И в 15 раз больше, чем Angular.
Рынок труда
Из этого графика можно сделать следующие выводы:
Итак, компонентные фреймворки победили. Фронтенд решил проблемы, которые стояли перед разработчиками во времена jQuery. Но новые подходы порождают новые неприятности. Какие проблемы вижу я?
В апреле этого года вышла третья версия компилируемого фреймворка Svelte.
Svelte предлагает разработчикам возможность писать высокоуровневый декларативный код, который после компиляции превращается в низкоуровневый императивный код. Еще это дает возможность делать эффективный tree shaking, и в итоге позволяет отправлять клиенту минимальный бандл.
Давайте посмотрим, какие решения Svelte предлагает для озвученных проблем
Поскольку React является самой популярной библиотекой на территории России, дальнейшие примеры будут на React.
Если вы начинаете знакомство с новой библиотекой, то скорее всего начнете тур с ToDo листа. Это достаточно простая задача, которую, зачастую, проще написать на ваниле. Если вы хотите углубиться во фреймворк, то отличным выбором будет обзор Real World Application. Это блог, который, по сути, является клоном Medium. Здесь есть регистрация, авторизация, создание постов, комментирование, лайки. Специалисты по фреймворку пишут реализацию функционала и добавляют в коллекцию Real World Application [4].
На FreeCodeCamp вышла статья о сравнении Real World Application [5], написанных на разных фреймворках.
Если мы посмотрим на размер итогового бандла, то Svelte выигрывает у конкурентов. Клиенту отправляется всего лишь 9.7кб кода. Как результат, это меньше времени на передачу данных, парсинг и обработку вашего кода.
Сравнение размера бандла Real World Application
А еще самый лучший код — это не написанный код.
Если мы посмотрим на количество строк кода, которые необходимы для написания функционала приложения, то на Svelte потребуется около 1 000 строк, а на React около 2 000. Чем меньше кода в вашем приложении, тем меньше в нем багов и проще поддержка.
Сравнение размера объема кода Real World Application
Давайте посмотрим на производительность. js-framework-benchmark [6] предлагает сравнение производительности рендеринга среди фронтенд фреймворков. Тест заключается в отрисовке таблицы с большим количеством строк. Далее производятся манипуляции с этой таблицей: частичное или полное обновление, создание, очистка, удаление строк.
По времени обновления Svelte показывает лучшее, либо сопоставимое время. Svelte очень сбалансирован, нет перекосов при выполнении разных типов операций.
Сравнение времени выполнения обновления, мс
Если мы посмотрим на объем потребляемой памяти, то Svelte является наименее прожорливым среди рассматриваемых библиотек.
Сравнение объема потребляемой памяти, мб
Я не привык верить на слово и решил проверить все сам. Я нашел реализацию бенчмарка DBMonster [7] для фронтенда и переписал реализацию на React 16.8 и Svelte 3. Тест заключается в рендеринге таблицы и последующим обновлении строк.
Как выглядит тест DBMonster
В ходе теста Svelte потреблял на 10мб памяти меньше и производил обновления на 10 мс быстрее, чем React.
Svelte / React
Приведенные тесты являются синтетическими, но из них можно сделать вывод, что при разработке на Svelte из коробки вы получите:
Если мы посмотрим на самый простой компонент на React, то вам потребуется импортировать сам React, написать функцию, которая вернет разметку и экспортировать ваш компонент. Итого 3 строчки кода.
import React from 'react';
const Component = () => (<div>Hello</div>);
export default Component;
Если мы посмотрим на самый простой пример компонента на svelte, то вы просто пишете разметку. Итого 1 строка кода.
<div>Hello</div>
Строго говоря, самый простой Svelte компонент — это пустой файл. Это дает возможность создать шаблон вашего приложения из пустых файлов, а затем начать разработку. При этом ничего не сломается.
Еще вы можете брать верстку, полученную от верстальщика, и сразу использовать ее как Svelte компонент без дополнительных преобразований. Валидный html является Svelte компонентом.
Хочу поделиться примером с собеседования на позицию middle react developer.
setFilter() {
this.switchFlag = !this.switchFlag
}
...
<button onClick={setFilter}>Filter</button>
Кандидат пытался сохранить состояние кнопки фильтрации напрямую в свойство класса. React, несмотря на свое название, недостаточно реактивный, чтобы реагировать на такие изменения. Это говорит о том, что даже middle разработчику сложно даются паттерны обновления состояния, которые использует React.
Давайте разберем пример кнопки, которая по клику увеличивает счетчик.
На React вам потребуется переменная для хранения состояния и функция, которая умеет обновлять состояние. Далее на саму кнопку нужно назначить обработчик для обновления. Итого у меня получилось 8 строк кода.
import React from 'react';
const Component = () => {
const [count, setCount] = React.useState(0)
return <button onClick={() => setCount(count + 1)}>
Clicked {count}
</button>
}
export default Component;
Для решения аналогичной задачи на Svelte вам потребуется переменная для хранения состояния. Далее в обработчике вы просто изменяете значение этой переменной. Итого 6 строк кода.
<script>
let count = 0;
</script>
<button on:click={()=>count+=1}>
Clicked {count}
</button>
Немного усложним пример. Допустим, нам нужно поле ввода, которое рядом выводит свое состояние
На React нам все так же потребуется переменная и функция для обновления состояния. Затем в поле ввода необходимо передать текущее значение и назначить обработчик на изменения. У меня в итоге получилось 11 строк кода.
import React from 'react';
const App = () => {
const [value, setValue] = React.useState('');
return (
<React.Fragment>
<input value={value} onChange={e => setValue(e.target.value)} />
{value}
</React.Fragment>
);
}
export default App;
Для решения этой задачи на Svelte вам потребуется переменная, которая хранит состояние, а затем просто сделать двустороннюю привязку в поле ввода. Итого 5 строк кода.
<script>
let value = '';
</script>
<input bind:value={value}/>
{value}
Если вам доводилось анимировать удаление элемента из DOM на React, то я вам сочувствую. На React потребуется либо враппер, который будет откладывать удаление элемента из DOM и производить анимацию, либо сам элемент остается в DOM, но анимация потребует управления свойством display или других манипуляций, чтобы элемент не занимал место.
Я пытался найти самую простую реализацию на React, в итоге получилось 35 строк кода. Если у вас есть решение проще, поделитесь в комментариях.
import React from "react";
import "./style.css";
const App = () => {
const [visible, setVisible] = React.useState(true);
return (
<React.Fragment>
<button onClick={() => setVisible(!visible)}>toggle</button>
<div className={visible ? "visible" : "invisible"}>Hello</div>
</React.Fragment>
);
};
export default App;
.visible {
animation: fadeIn 0.5s linear forwards;
}
.invisible {
animation: fadeOut 0.5s linear forwards;
}
@keyframes fadeOut {
0% {
opacity: 1;
}
100% {
opacity: 0;
display: none;
}
}
@keyframes fadeIn {
0% {
opacity: 0;
}
100% {
opacity: 1;
}
}
На Svelte аналогичный компонент требует всего 8 строк кода. В Svelte есть встроенный модуль для управления анимациями. Вы импортируете требуемый вид анимации, а затем говорите, как анимировать ваш компонент при добавлении и удалении.
<script>
import { fade } from 'svelte/transition';
let visible = true;
</script>
<button on:click={()=>visible=!visible}>toggle</button>
{#if visible}
<div transition:fade>Hello</div>
{/if}
Компилируемость позволяет Svelte предоставлять разработчику крутые абстракции. И если вы их не используете, они не попадут в итоговый бандл.
Например, в модуле transition есть крутой функционал crossfade [8], который позволяет анимировать компонент при переходе из одного DOM узла в другой. С помощью него можно сделать такой переход задач в ToDo листе.
Еще одним примером классных абстракций может служить директива use: [9]. Она позволяет назначить кастомный обработчик на DOM элемент. В примере ниже производится обработка событий нажатия и перемещения, а также тач события с использованием всего одной функции.
После знакомства со Svelte, мои друзья обычно говорят, что они не испытывали такого удовольствия от фронтенд разработки со времен jQuery.
Когда появился React, в сети было большое количество виджетов на jQuery. Найти нужный компонент на React было сложно. Затем начали появлятся врапперы для jQuery виджетов, которые умели синхронизировать React и jQuery. После этого уже начали появлятся компоненты, написанные на самом React.
Сейчас подобная ситуация с самим React. Есть куча готовых решений и библиотек, которые не позволяют пересесть на другой фреймворк без боли.
Что предлагает Svelte? После компиляции ваш код превращается в обычный JS, который не требует рантайма. Это дает возможность использовать Svelte компонент в других фреймворках. Вам всего лишь потребуется один универсальный враппер. Например, адаптер для React и Vue svelte-adapter [10]. Обернув компонент в адаптер, вы сможете использовать элемент, как обычный компонент.
import React from "react";
import SvelteSpinner from "svelte-spinner";
import toReact from "svelte-adapter/react";
const Spinner = toReact(SvelteSpinner, {}, "div");
const App = () => <Spinner size={50} />
Svelte поддерживает компиляцию в custom element, что еще больше расширяет границы применения компонентов. Посмотреть поддержку custom element различными фреймворками можно на custom-elements-everywhere [11].
На работе писать на Svelte я пока не могу, поскольку мы плотно сидим на экосистеме React, но у меня есть личные проекты.
Ранее я писал [12], как опубликовал свое приложение Metalz [13] в Google Play.
По моим ощущениям, Svelte позволяет писать более лаконичный и понятный код, при этом предоставляя широкий инструментарий для упрощения реализации.
Как у любого молодого фреймворка, у Svelte небольшая экосистема готовых решений и мало статей, где можно найти лучшие практики. Поэтому сразу брать Svelte для больших проектов я бы не рекомендовал, поскольку можно в итоге зайти в архитектурный тупик.
Попробуйте Svelte на небольших проектах, уверен, вам понравится.
Автор: Alexander Zinchenko
Источник [14]
Сайт-источник PVSM.RU: https://www.pvsm.ru
Путь до страницы источника: https://www.pvsm.ru/javascript/333648
Ссылки в тексте:
[1] Svelte: https://ru.svelte.dev
[2] Автор изображения Andrew Walpole: https://twitter.com/walpolea/status/1173975821540704256
[3] Google Trends: https://trends.google.ru/trends/explore?date=today%205-y&geo=RU&q=react,jquery,angular,vue
[4] Real World Application: https://github.com/gothinkster/realworld
[5] сравнении Real World Application: https://www.freecodecamp.org/news/a-realworld-comparison-of-front-end-frameworks-with-benchmarks-2019-update-4be0d3c78075/
[6] js-framework-benchmark: https://krausest.github.io/js-framework-benchmark/current.html
[7] реализацию бенчмарка DBMonster: https://github.com/mathieuancelin/js-repaint-perfs
[8] crossfade: https://svelte.dev/examples#animate
[9] use:: https://svelte.dev/examples#actions
[10] svelte-adapter: https://github.com/pngwn/svelte-adapter
[11] custom-elements-everywhere: https://custom-elements-everywhere.com/
[12] Ранее я писал: https://habr.com/ru/post/462003/
[13] Metalz: https://gitlab.com/az67128/svelte-metalz
[14] Источник: https://habr.com/ru/post/471702/?utm_source=habrahabr&utm_medium=rss&utm_campaign=471702
Нажмите здесь для печати.