RE: Боль и слёзы в Svelte 3

Вместо предисловия


Данный пост является ответом на вчерашнюю статью «Боль и слёзы в Svelte 3» и появился как следствие сильно «располневшего» комментария к оригинальной статье, который я решил оформить в виде поста. Ниже я буду использовать слово автор для отсылки к автору оригинальной статьи и позволю себе сделать некоторые уточнения по всем пунктам. Поехали!

9y3xe1y9bs0rri0w4zffgayclo8.jpeg

Кто такой Svelte?


Когда я увидел заголовок оригинальной статьи, сперва очень обрадовался. Вот сейчас, думаю, прочитаю какую-то глубокую и конструктивную критику. А главное интересные кейсы с подводными камнями не от «диванных экспертов», а от ребят «которые смогли». После прочтения, энтузиазма поубавилось, но все равно большое спасибо vds64_max за статью.

Несмотря на то, что не все получилось, мне кажется нужно больше статей описывающих реальные проблемы и их решения в Svelte. Хотя бы чтобы он не отставал от более именитых товарищей, таких как React или Vue. Ведь, в конечном итоге, у читателей может возникнуть ощущение, что Svelte слишком идеален, а это безусловно не так.

Tutorial


Так и не понял, что автор имел ввиду в этой части. Tutorial работал и работает прекрасно. Предполагаю, что автор лишь поверхностно ознакомился с ним из-за дедлайнов своего проекта и не смог понять принцип работы. Уже бывали случаи, когда люди не сразу улавливали смысл пошаговости туториала, когда чтобы пример заработал нужно сделать какое-то действие. Попробуйте сами!

UI Kit и Стили


zvrgvrczthzxzstlthyhvmkgp4o.gif

Поиски UI Kit для Svelte были отдельной болью для всех нас. Хотелось воскликнуть: «Хоть Material, Bootstrap… хоть что нибудь…».


Во-первых, далеко не во всех проектах в принципе применимы UI киты. Во-вторых, далеко не все UI киты для других фреймворков работают хорошо.

Основные проблемы начинаются, когда проект имеет сильно замороченный и кастомный дийзан, а киты обычно все же имеют лимитированные средства для кастомизации. Если же речь об админке, согласен, иметь UI кит это полезно, но далеко не всех пишут админки, да и профит от Svelte для backoffice будет не так заметен.

По ссылке можете ознакомиться и с другими UI китами для Svelte.

Из-за того, что Svelte работает с DOM «по другому» в MaterialUI начали вылазить всякие гадости, связанные с тем как отображаются UI компоненты которые добавляются через js в dom. Например простой спиннер отображается через раз:


Так и не понял, что означает начало предложения и как именно «по-другому» работает Svelte с DOM, но в целом весь тезис звучит, по крайней мере, не серьезно. Если вы попробуете интегрировать стороннюю либу работающую с DOM в любой из фреймворков (React/Vue/Angular/Ember), управляющих DOM, у вас будут всплывать точно те же вопросы. Сразу возникает ощущение, что автор никогда не делал этого.

Более того, в Svelte есть прекрасный механизм называемый actions, с помощью которого интеграция с любой сторонней DOM либой сводится к написанию небольшой функции. Похоже автор не дочитал доку до этого момента. Что ж, бывает.

Для примера, имплементация MDCSlider за 2 минуты: REPL
a26rwd5eubmus5xx3n8klawesis.gif
Скажите, пожалуйста, куда уж проще?

Стилизация


Со стилями все предельно ясно, мы запихиваем все стили в как в Vue. Вы пишите стиль и все в порядке, и потом пишите компонент UI (так как у Вас нет UIKit) который должен принимать параметры props, например width и height, и логично делаете это так:

А… нет, в стиле у Вас не получится вставлять переменные.


Насколько мне известно, во Vue стейт также не может использоваться внутри стилей компонента, а в React вообще нет работы со стилями из коробки.

Хотя, я могу понять желание использовать динамику в стилях, но есть ряд причин почему так делать не надо:

  • Как только кусок стейта компонента появляется в стилях эти стили надо дублировать для КАЖДОГО инстанса компонента. Сразу представляем список из 1000 айтемов со сложным дизайном. Оно нам надо?
  • Использование динамики в css вызывает много лишних перерисовок и крайне не производительно.


Альтернативные способы использовать динамические стили в Svelte:

  • Смена классов с помощью директивы class:
  • Использование инлайн стилей с помощью атрибута style
  • Использование css custom properties (variables)
  • Использование css-in-js решения, таких как Emotion (статья на эту тему)

И раз уж был упомянут Vue, давайте сравним использование динамических инлайн стилей:




Font size is: {{ fontSize }}




Font size is: {fontSize}


REPL

В целом, особых отличий я не вижу, но автор почему-то считает что в Vue все с этих хорошо, а в Svelte нет. Странно это.

Кстати, с помощью реактивных деклараций, можно довольно удобно собирать все динамические стили в одном месте:

....


Обычно этого хватает для 99% случаев, а остальное решается с помощью тем и/или css custom properties.

Routing и ротуеры


Вообще, Svelte — это UI фреймворк и он агностичен к роутеру. Более того, внешний апи Svelte позволяет легко интегрировать любой независимый роутера буквально за пару минут и строк кода. На примере page.js:

import page from 'page';

import App from './App.svelte';

const app = new App({ 
  target: document.body 
});

page('/posts', ctx => {
   // можно даже сразу с dynamic import & code-splitting
  app.$set({ ctx, page: import('./Posts.svelte') });
});

page('/', ctx => {
  app.$set({ ctx, page: import('./Home.svelte') });
});

page.start();

export default app;


{#await page}

Loading...

{:then comp} {/await}

Разве это сложно? Автор столкнулся лишь с проблемами конкретной реализации, конкретного роутера. Который, кроме того, мягко говоря не самый лучший из того что имеется для Svelte, так как копирует React Router со всеми его проблемами. Можете ознакомиться с множеством других роутеров по ссылке.

Ошибки


В отличии от React который просто не даст Вам создать bundle и будет сильно «кричать» об ошибке, Svelte отлично соберёт всё с ошибкой. При этом если Вы забыли что-то npm install’нуть или export’ануть, все отлично соберется и просто покажет белый экран (Кстати говоря так было в первых версиях React).


React вам ничего не собирает. Собирает сборщик. В этом случае, вангую, что автор работал Rollup и скорее всего делал это первый раз. Мне кажется имеет смысл либо изучать инструмент, который собираешься использовать, либо не использовать его. От себя добавлю, что того о чем пишет автор не наблюдается в Svelte. По крайней мере, какие-то проблемы возникают не чаще чем в других фреймворках. Скорее всего, для других фреймворков автор уже все настроил и отработал, а тут просто поленился это сделать.

Есть предположение, что автор имел ввиду также работу с пропсами, которая в Svelte ведется через export’ы из компонента, но даже тут всегда будет выведено предупреждение, если попытаться прокинуть пропс не определенный компонентом:
6lu0rbg1fklcuovqlsz2h_ngvbw.png

Svelte просто необходим naming convention


C этой проблемой Вы будете сталкиваться довольно часто — с отсутствием конвенции по наименованию.


Очень понравилась эта фраза, потому что по-сути ее можно использовать для любого проекта/библиотеки/языка программирования. Лукавство здесь заключается в том, что точно также вы будете сталкиваться с этим везде. Например, в том же React:

class MyComponent extends React.Component {
  constructor(props) {
    super(props);
    this.dialog = null;
    this.loading = false;
    this.pins = [];
    this.stitch = null;
  }
  render() {
    return  this.dialog = el} class="mdl-dialog» />;
  }
}


В общем и целом все тоже самое и нужно будет как-то «понимать» что есть рефка на элемент, а что есть объект для работы с бекендом или флажок загрузки. Казалось бы, если у вас команда, которая собралась не вчера, все эти вопросы давно должны быть решены.

В целом конечно, если у вас в проекте и команде нет naming convention тут вам Svelte ничем не поможет. Некоторые вещи которые использую в своих проектах:


 
  
  

Кроме того, обычно мои компоненты имеют «бюджет» в 200 строк кода вместе со стилями. Если чуть больше — не страшно. Если сильно больше, я создаю для компонента папку и начинаю выносить части в отдельный файлы с помощью svelte-preprocess, начиная со стилей. При этом сборщик настроен так, что импорты не меняются.

Что где изменилось и кто это сделал ?


l__yrdc8jsyuhyoym3bzsspsjk8.jpeg

В итоге Вы быстро пишете компоненты, но понять, что написал джуниор в этом «венегрете» через несколько дней когда он сам уже забыл (иногда даже как его зовут) бывает очень сложно. Из-за этого будет невозможно понять что внутри без четкой организации кода внутри проекта или команды.


Забавный тезис, а главное опять же применимый вообще к любому фреймворку и проекту. Более того, синтаксис хуков в современном React, так полюбившийся создателю Vue, что он даже решил срочно внедрить его во Vue 3, будет иметь все те же коллизии:

import React, { useState, useCallback } from 'react';

function MyComponent() {
  const [ loading, setLoading ] = useState(false);
  const [ status, setStatus ] = useState(0);
  const [ pins, setPins ] = useState([]);

  const ReloadPins = useCallback(async () => {
        setLoading(true);
        setPins(await getAllPins());
        setStatus(0);
  });

  return (
); }

vs

Как видите, все тоже самое, только писанины в 2 раза больше.

Шучу, конечно же ничего не ясно. Причем даже не понятно меняется состояние или это просто вспомогательная переменная. В React это решается state, который хоть как-то вносит ясности.


На самом деле, нет никакого смысл «понимать» какая переменная стейта компонента используется в шаблоне, а какая необходима только для работы скрипта. В Svelte вообще нет такого разделения, там переменные живут обычно JS жизнью — существуют в своем скоупе, некоторые имеют скоуп всего компонента, другие обитают в рамках одной функции или иного блока кода. Ничего нового или неожиданного. Важно понимать лишь одно — DOM пересчитывается исключительно тогда, когда изменяется связанная с них часть стейта.

Например, в том же React, если сделать:

this.setState({ foo: 1 })

и при этом foo НЕ используется в шаблоне, механизм VDOM никак не сможет понять этого и произведет rerender/reconcile. Вы знали об этом?

Поэтому, наверное, в React важно понимать, что используется в шаблонах, а что нет. В Svelte мы избавлены манипуляций.

В итоге, тут я могу лишь вторить автору — если у вашего проекта и команды нет четкой организации у вас будут проблемы с любым инструментом, на любом проекте. Собственно, пример проекта автора тому прямое доказательство.

Привязываем Stitch


Конечно же это связано со сборщиком. Автору не следует так легкомысленно относиться к новым инструментом. По-умолчанию, Svelte идет в поставке с Rollup, который «из коробки» поддерживает намного меньше фичей, чем Webpack, зато собирает более оптимизированные и более нативные бандлы. Любой дополнительный функционал можно донастроить с помощью плагинов. Если же не хочется париться, то можно взять официальный шаблон для Webpack, либо любой другой от сообщества, благо их прям много.

Для чего Вам пригодится Svelte?


В этом пункте, буду более краток — для любых новых проектов, для которых достаточно React или Vue. С Angular или Ember сравнивать не имеет смысла, потому что это фреймворка другого масштаба.

Исходя из последнего я совсем не понимаю зачем мэйнтэйнеры Svelte собираются делать поддержку TypeScript? Мы же любим Svelte как раз за «стрельбу по ногам» и TypeScript на мой взгляд это как вседорожные гусеницы для спорткара Svelte. И знаете, поработав со Svelte, я понял на сколько сильно за последние годы изменился JS, и что он совсем уже не JS.

Svelte даёт возможность поработать в еще том, старом и ламповом JS, без PropTypes, Flow и TypeScript.


Не могу не согласиться с этим утверждением. В действительности, TS не так уж и нужен в Svelte. Хотя частичная его поддержка есть с помощью препроцессоров (без тайпчека шаблонов), но в целом это скорее довесок, чем то, без чего нельзя написать хорошие компоненты.

Почему НЕ стоит использовать Svelte?


  1. Если ваш проект уже написан на другом фреймворке и работает сносно. Не нужно бежать и переписывать его.
  2. Даже в п.1 есть окно возможностей — можно переписать некоторые «тяжелые» компоненты на Svelte. Проект станет легче, а компоненты будут работать быстрее. При этом не придется переписывать все.
  3. Если вы пишете энтерпрайз, скорее всего лучше подойдет Angular или Ember. Svelte, ровно как и React и Vue, навряд ли хороший выбор.
  4. Если если вам нужна first-class поддержка Typescript.
  5. Если вы разрабатываете исключительно типовые решения и привыкли собирать проекты из готовых компонентов.
  6. До сих пор более слабый тулинг, чем у более матерых товарищей. Если это критично, тогда стоит подождать, либо присоединиться к нашему сообществу и развивать тулинг вместе.)))

***

В целом, к сожалению, большая часть выводов из оригинальной статьи основана на ложных предпосылках и вводит читателей в заблуждение. Учитывая, что я не видел автора в русскоязычном комьюнити Svelte в Телеграм (1К+ участников), делаю вывод, что автор и его команда приложили недостаточно усилий при освоения нового, неизведанного для себя инструмента. Думаю если бы ребята просто добавились в чатик, большей части проблем удалось бы избежать. В данный момент кажется ребята сделали довольно поспешные выводы, впрочем это их личное дело.

© Habrahabr.ru