- PVSM.RU - https://www.pvsm.ru -
Статья будет полезна тем, кто так-же как и Мы решил попробовать Svelte [1] в живом проекте. В нашу небольшую компанию пришёл заказ на разработку веб-админки для сервиса с бекэндом на Mongodb Stitch. В последние пару лет frontend Мы пишем на React или Vue (в зависимости от размера проекта и нужен ли ReactNative), но наслышав о красотах Svelte мы решили попробовать его, чтобы понять для себя так ли он хорош. И может нам тоже стоит дальше использовать его вместо Vue или React?..

Если в двух словах — это новый js фреймворк (но он таким себя не считает), который убийца React и Vue, и бла, бла, бла… В своей статье я хочу рассмотреть Svelte не какой он классный «под капотом», а с точки зрения удобства его использования в реальном проекте.
Мы не делаем машины, мы на них ездим и у нас есть злые заказчики с еще не менее злыми сроками.
Первое с чего Вы начинаете знакомство с новым языком или фреймворков — это туториал на сайте. У Svelte это Svelte.dev/Tutorial [2].
К сожаление часть туториалов просто не работает на сайте в превью, при этом не совсем понятно работает ли оно в реальности или нет. Приходится тратить время и проверять самому вручную, так как не понятно устарел ли туториал или что-то пошло не так на сайте Svelte. И на это реально тратится очень много времени.

Поиски UI Kit для Svelte были отдельной болью для всех нас. Хотелось воскликнуть: «Хоть Material, Bootstrap… хоть что нибудь...».
Были найдены только sveltematerialui.com [3] и svelteui.js.org [4], которые в данный момент выглядели очень сыро.
При простом импорте <Button/> из него, при сборке вывалилась ошибка из самого пакета, решать ошибки ui kit времени не было.
Пробежав быстро по документации я решил от него отказаться в пользу «Ванилла» импорта из CDN.
В проекте хотелось использовать Material UI, так как возможно админка будет использоваться и с мобильного устройства, а Material очень хорошо для этого подходит (на мой взгляд он даже хуже смотрится на десктопе).
Использование JS без UI Kit вернуло меня мысленно на 10 лет назад ) Паровозы классов и добрая ностальгия ).
Из-за того, что Svelte работает с DOM «по другому» в MaterialUI начали вылазить всякие гадости, связанные с тем как отображаются UI компоненты которые добавляются через js в dom. Например простой спиннер отображается через раз:

После долгих поисков что же пошло не так, выяснилось что спиннер в Material UI, добавляется через JS после того, как документ готов (onLoad) но после этого события Svelte запускает своё добавление в DOM и JS скрипт Material просто его не видит так как событие было раньше.
Лечить это пришлось добавлением в родительский компонент Svelte:
afterUpdate(() => {
componentHandler.upgradeDom();
});
Со стилями все предельно ясно, мы запихиваем все стили в как в Vue. Вы пишите стиль и все в порядке, и потом пишите компонент UI (так как у Вас нет UIKit) который должен принимать параметры props, например width и height, и логично делаете это так:
<script>
export let width = '20px';
export let height = '20px';
</script>
<style>
.loader {
width: { width },
height: { height },
}
</style>
А… нет, в стиле у Вас не получится вставлять переменные. Из этой ситуации Вы можете выкрутится через «ReactWay» и делать динамические стили в как переменные или функции с возвратом стиля.
В итоге у нас опять каша, часть стиля в style часть в script. Чистый код получится только в том случае если у Вас нет параметров в стилях или у Вас только динамические параметры и они только в script.
Без нормального роутера Вы не сможете сделать даже one page app.
React, Vue при скалфолдинге 'Hello World' проекта уже идут с роутером в коробке (или можно его выбрать). Но как и всё в Svelte — это дается не просто.
Нужно выбрать роутер самому, да и еще между очень похожими решениями. По правде говоря пока есть всего два роутера github.com/EmilTholin/svelte-routing [5] и github.com/kazzkiq/svero [6]
Оба очень похожи но я выбрал первый, выбирал по количеству звезд (да я знаю, я ужасный человек ).
Итак начнем его встраивать в наш MDL.
Обернем всё в <Router url="{url}"> и Добавим <Link/> для ссылок из навигации.

Переходим в превью и смотрим, что получилось.
А получилось то, что детские болезни Svelte продолжаются и в <Link/> нельзя передавать классы. Возник резонный вопрос а как Вы его будете стилизировать?
Видимо это все еще в issues для роутера.
К счастью Мы можем привязать к роутеру наш обычный a href=‘’ указав use:link [7] за что отдельная благодарность.
В отличии от React который просто не даст Вам создать bundle и будет сильно «кричать» об ошибке, Svelte отлично соберёт всё с ошибкой. При этом если Вы забыли что-то npm install'нуть или export'ануть, все отлично соберется и просто покажет белый экран (Кстати говоря так было в первых версиях React).
В React и Vue, Мы привыкли видеть такие ошибки еще на этапе билда или линта.
В тоге Вам придется отлавливать ошибки в двух местах. Справедливости ради — это есть в React и Vue, но гораздо реже и такие явные ошибки ловятся еще на стадии линта.
C этой проблемой Вы будете сталкиваться довольно часто — с отсутствием конвенции по наименованию.
Например, вернемся к роутеру.
Есть вот такой импорт:
import { Router, link, Link ,Route } from "svelte-routing";
Что из этого Link и link? Даже в таком маленьком проекте как у меня, уже возникла путаница с отсутствием конвенций имен в проектах используемых в Svelte.
Конечно это должно было выглядеть в глазах ReactМэна вот так:
import { Router, useLink, LinkComponent ,RouteComponent } from "svelte-routing";
В Svelte есть подобие ref как в react’е, это ссылка на элемент dom или компонент.
Официальный туториал гласит нам сделать это так:
<script>
let dialog;
</script>
<dialog bind:this={dialog} class="mdl-dialog» />
А если у Вас будет 15 переменных в компоненте?
<script>
let loading;
let pins;
let dialog;
let stitch;
</script>
<dialog bind:this={dialog} class="mdl-dialog» />
Где и что из этого действительно переменные, а где ссылки на компоненты или элементы?
Я бы изменил туториал и сделал примеры более правильными с точки зрения новичков и их конвенции переменных (см Туториал React для хорошего примера). Если Вы даёте делать винегрет переменных, было бы неплохо чтобы linter или bundler ругался на такой винегрет, как например, это сделано у golang.
<script>
let dialogElement;
</script>
<dialog bind:this={dialogElement} class="mdl-dialog» />
Еще один пример «из жизни», когда Вы получаете какие-то данные в функции компонента и эти данные нужно отправить в Ваш View, где к части елемента UI у Вас прикручена какая-то переменная. И выглядит это у нас (вернее у нашего программиста) вот так:
async function ReloadPins() {
loading = true;
pins = await getAllPins();
status = 0;
}
Когда я открыл его код, мне сразу «стало понятно», что здесь переменная которая state и какая из них привязана к нашему UI.
Шучу, конечно же ничего не ясно. Причем даже не понятно меняется состояние или это просто вспомогательная переменная. В React это решается state, который хоть как-то вносит ясности.
Переменные внутри Svelte компонента — глобальные и меняются они везде (привет Angular).
Но есть и хорошая новость, они глобальны внутри одного компонента (пока Angular), поэтому это изменение всех и всеми не так уж и страшно внутри одного компонента.
При этом Вы экономите время на «красоте» кода и не размышляете, что Вам сделать state переменной, а что оставить внутри функции (привет React) — у Вас все и везде.

В итоге Вы быстро пишете компоненты но понять, что написал джуниор в этом «венегрете» через несколько дней когда он сам уже забыл (иногда даже как его зовут) бывает очень сложно. Из-за этого будет невозможно понять что внутри без четкой организации кода внутри проекта или команды.
Stitch — отличная штука и я обязательно расскажу о ней подробнее, и сравню с аналогами, померяем тесты в продакшене в своей следующей статье, а сейчас все таки больше про Svelte.
Чтобы использовать Stitch Вам прийдется пойти по «Ванильному» пути и вставить:
<script src="https://s3.amazonaws.com/stitch-sdks/js/bundles/4.4.0/stitch.js"></script>
Так как при использовании npm и нормального import пакета, начинается проблема с ошибкой buffer.
Не знаю связанно ли это со сборщиком Svelte или самим Stitch, или еще c чем-то, но времени ковырять у меня не было и пришлось просто добавить script с импортом, после чего всё успешно заработало.
Это основные проблемы с которыми мы столкнулись при работе со Svelte. И сказать честно — в общем нам не понравилось, причём никому…
Что в итоге:
Исходя из последнего я совсем не понимаю зачем мэйнтэйнеры Svelte собираются делать поддержку TypeScript? Мы же любим Svelte как раз за «стрельбу по ногам» и TypeScript на мой взгляд это как вседорожные гусеницы для спорткара Svelte. И знаете, поработав со Svelte, я понял на сколько сильно за последние годы изменился JS, и что он совсем уже не JS.
Svelte даёт возможность поработать в еще том, старом и ламповом JS, без PropTypes, Flow и TypeScript.
Автор: Maksym Geek
Источник [9]
Сайт-источник PVSM.RU: https://www.pvsm.ru
Путь до страницы источника: https://www.pvsm.ru/javascript/331536
Ссылки в тексте:
[1] Svelte: http://svelte.dev
[2] Svelte.dev/Tutorial: https://svelte.dev/tutorial
[3] sveltematerialui.com: https://sveltematerialui.com/
[4] svelteui.js.org: https://svelteui.js.org
[5] github.com/EmilTholin/svelte-routing: https://github.com/EmilTholin/svelte-routing
[6] github.com/kazzkiq/svero: https://github.com/kazzkiq/svero
[7] use:link: https://github.com/EmilTholin/svelte-routing#link-1
[8] event: https://svelte.dev/tutorial/component-events
[9] Источник: https://habr.com/ru/post/469361/?utm_source=habrahabr&utm_medium=rss&utm_campaign=469361
Нажмите здесь для печати.