Svelte — сравнительно новый UI фреймворк, разработанный Ричем Харрисом, который также является автором сборщика Rollup. Скорее всего Svelte покажется совершенно не похожим на то, с чем вы имели дело до этого, но, пожалуй, это даже хорошо. Две самые впечатляющие особенности этого фреймворка — скорость и простота. В этой статье мы сосредоточимся на второй.



Поскольку мой основной опыт разработки связан с Angular, вполне естественно, что я пытаюсь изучить Svelte, копируя уже привычные мне подходы. И именно об этом будет рассказано в этой статье: как в Svelte делать те же самые вещи, что и в Angular.


Примечание: Не смотря на то, что в ряде случаев я буду высказывать своё предпочтение, статья не является сравнением фреймворков. Это простое и быстрое введение в Svelte для людей, которые уже используют Angular в качестве своего основного фреймворка.


Внимание спойлер: Svelte — это весело.


Компоненты


В Svelte каждый компонент соотносится с файлом, где он написан. Например, компонент Button будет создан путем присвоения имени файлу Button.svelte. Конечно, мы обычно делаем то же самое в Angular, но у нас это просто соглашение. (В Svelte имя импортируемого компонента также может не совпадать с именем файла — примечание переводчика)


Компоненты Svelte однофайловые, и состоят из 3 разделов: script, style и шаблон, который не нужно оборачивать ни в какой специальный тег.


Давайте создадим очень простой компонент, который показывает "Hello World".


hello_world


Импортирование компонентов


В целом это похоже на импортирование JS-файла, но с парой оговорок:


  • необходимо явно указывать расширение файла компонента .svelte
  • компоненты импортируются внутри тега <script>

<script>
    import Todo from './Todo.svelte';
</script>

<Todo></Todo>

Из приведенных выше фрагментов очевидно, что количество строк для создания компонента в Svelte невероятно мало. Конечно, присутствуют некоторые неявности и ограничения, но при этом всё достаточно просто, чтобы быстро к этому привыкнуть.


Базовый синтаксис


Интерполяции


Интерполяции в Svelte больше схожи с таковыми в React, нежели в Vue или Angular:


<script>
  let someFunction = () => {...}
</script>

<span>{ 3 + 5 }</span>
<span>{ someFunction() }</span>
<span>{ someFunction() ? 0 : 1 }</span>

Я привык использовать двойные фигурные скобки, так что иногда опечатываюсь, но, возможно, такая проблема только у меня.


Атрибуты


Передать атрибуты в компоненты также довольно просто. Кавычки не обязательны и можно использовать любые Javascript-выражения:


//Svelte
<script>
  let isFormValid = true;
</script>

<button disabled={!isFormValid}>Отправить</button>

События


Синтаксис обработчиков событий выглядит так: on:событие={обработчик}.


<script>
  const onChange = (e) => console.log(e);
</script>

<input on:input={onChange} />

В отличие от Angular, нам не нужно использовать скобки после имени функции, чтобы вызывать её. Если нужно передать аргументы в обработчик, просто используем анонимную функцию:


<input on:input={(e) => onChange(e, ‘a’)} />

Мой взгляд на читабельность такого кода:


  • Печатать приходится меньше, поскольку нам не нужны кавычки и скобки — это в любом случае хорошо.
  • Читать сложнее. Мне всегда больше нравился подход Angular, а не React, поэтому для меня и Svelte здесь воспринимается тяжелее. Но это просто моя привычка и мое мнение несколько предвзято.

Структурные директивы


В отличие от структурных директив в Vue и Angular, Svelte предлагает специальный синтаксис для циклов и ветвлений внутри шаблонов:


{#if todos.length === 0}
  Список дел пуст
{:else}
  {#each todos as todo}
    <Todo {todo} /> 
  {/each}
{/if}

Мне очень нравится. Нет необходимости в дополнительных HTML элементах, и с точки зрения читаемости это выглядит потрясающе. К сожалению, символ # в британской раскладке клавиатуры моего Macbook находится в труднодоступном месте, и это негативно сказывается на моем опыте работы с этими структурами.


Входные свойства


Обозначить свойства, которые можно передать компоненту (аналог @Input в Angular) так же легко, как экспортировать переменную из JS модуля при помощи ключевого слова export. Пожалуй, поначалу это может сбивать с толку — но давайте напишем пример и посмотрим, насколько это действительно просто:


<script>
  export let todo = { name: '', done: false };
</script>

<p>
  { todo.name } { todo.done ? '?' : '?' }
</p>

  • Как вы могли заметить, мы инициализировали свойство todo вместе со значением: оно будет являться значением свойства по умолчанию, в случае если оно не будет передано из родительского компонента

Теперь создадим контейнер для этого компонента, который будет передавать ему данные:


<script>
 import Todo from './Todo.svelte'; 
 const todos = [{
  name: "Изучить Svelte",
  done: false
 },
 {
  name: "Изучить Vue",
  done: false
 }];
</script>

{#each todos as todo}
  <Todo todo={todo}></Todo>
{/each}

Аналогично полям в обычном JS-объекте, todo={todo} можно сократить и переписать код следующим образом:


<Todo {todo}></Todo>

Сначала мне казалось это странным, но теперь я думаю, что это гениально.


Выходные свойства


Для реализации поведения директивы @Output, например, получения родительским компонентом каких-либо уведомлений от дочернего, мы будем использовать функцию createEventDispatcher, которая имеется в Svelte.


  • Импортируем функцию createEventDispatcher и присваиваем её возвращаемое значение переменной dispatch
  • Функция dispatch имеет два параметра: имя события и данные(которые попадут в поле detail объекта события)
  • Помещаем dispatch внутри функции markDone, которая вызывается по событию клика (on:click)

<script>
 import { createEventDispatcher } from 'svelte'; 

 export let todo;

 const dispatch = createEventDispatcher();

 function markDone() {
  dispatch('done', todo.name); 
 }
</script>

<p>
 { todo.name } { todo.done ? '?' : '?' } 

 <button on:click={markDone}>Выполнено</button>
</p>

В родительском компоненте нужно создать обработчик для события done, чтобы можно было отметить нужные объекты в массиве todo.


  • Создаём функцию onDone
  • Присваиваем эту функцию обработчику события, которое вызывается в дочернем компоненте, таким образом: on:done={onDone}

<script>
 import Todo from './Todo.svelte';

 let todos = [{
  name: "Изучить Svelte",
  done: false
 },
 {
  name: "Изучить Vue",
  done: false
 }];

 function onDone(event) {
  const name = event.detail;
  todos = todos.map((todo) => {
   return todo.name === name ? {...todo, done: true} : todo;
  });
 }
</script>

{#each todos as todo}
  <Todo {todo} on:done={onDone}></Todo>
{/each}

Примечание: для запуска обнаружения изменения объекта, мы не мутируем сам объект. Вместо этого мы присваиваем переменной todos новый массив, где объект нужной задачи уже будет изменен на выполненный.


Поэтому Svelte и считается по-настоящему реактивным: при обычном присваивании значения переменной изменится и соответсвующая часть представления.


ngModel


В Svelte есть специальный синтаксис bind:<атрибут>={переменная} для привязки определенных переменных к атрибутам компонента и их синхронизации между собой.


Иначе говоря, он позволяет организовать двухстороннюю привязку данных:


<script>
  let name = "";
  let description = "";  
  function submit(e) {  // отправка данных формы }
</script>

<form on:submit={submit}>
  <div>
    <input placeholder="Название" bind:value={name} />
  </div> 
  <div> 
    <input placeholder="Описание" bind:value={description} />
  </div>  
  <button>Добавить задачу</button>
</form>

Реактивные выражения


Как мы уже видели ранее, Svelte реагирует на присваивание значений переменным и перерисовывает представление. Также можно использовать реактивные выражения, чтобы реагировать на изменение значения одной переменной и обновлять значение другой.


Например, давайте создадим переменную, которая должна показывать нам, что в массиве todos все задачи отмечены как выполненные:


let allDone = todos.every(({ done }) => done);

Однако, представление не будет перерисовываться при обновлении массива, потому что значение переменной allDone присваивается лишь единожды. Воспользуемся реактивным выражением, которое заодно напомнит нам о существовании "меток" в Javascript:


$: allDone = todos.every(({ done }) => done);

Выглядит весьма экзотично. Если вам покажется, что тут "слишком много магии", напомню, что метки — это валидный Javascript.


Небольшое демо, поясняющее вышесказанное:
demo


Внедрение содержимого


Для внедрения содержимого тоже применяются слоты, которые помещаются в нужное место внутри компонента.


Для простого отображения контента, который был передан внутри элемента компонента, используется специальный элемент slot:


// Button.svelte
<script>
    export let type;
</script>

<button class.type={type}>
 <slot></slot>
</button>

// App.svelte
<script>
  import Button from './Button.svelte';
</script>

<Button>
  Отправить
</Button>

В этом случае строка "Отправить" займет место элемента <slot></slot>.
Именованным слотам потребуется присвоить имена:


// Modal.svelte
<div class='modal'>
 <div class="modal-header">
  <slot name="header"></slot>
 </div>

 <div class="modal-body">
  <slot name="body"></slot>
 </div>
</div>

// App.svelte
<script>
  import Modal from './Modal.svelte';
</script>

<Modal>
 <div slot="header">
  Заголовок
 </div>

 <div slot="body">
  Сообщение
 </div>
</Modal>

Хуки жизненного цикла


Svelte предлагает 4 хука жизненного цикла, которые импортируются из пакета svelte.


  • onMount — вызывается при монтировании компонента в DOM
  • beforeUpdate — вызывается перед обновлением компонента
  • afterUpdate — вызывается после обновления компонента
  • onDestroy — вызывается при удалении компонента из DOM

Функция onMount принимает в качестве параметра callback-функцию, которая будет вызвана, когда компонент будет помещен в DOM. Проще говоря, она аналогична действию хука ngOnInit.


Если callback-функция возвращает другую функцию, то она будет вызвана при удалении компонента из DOM.


<script>
  import { 
    onMount, 
    beforeUpdate, 
    afterUpdate, 
    onDestroy 
  } from 'svelte';

  onMount(() => console.log('Смонтирован', todo));
  afterUpdate(() => console.log('Обновлён', todo));
  beforeUpdate(() => console.log('Сейчас будет обновлён', todo));
  onDestroy(() => console.log('Уничтожен', todo));

</script>

Важно помнить, что при вызове onMount все входящие в него свойства уже должны быть инициализированы. То есть в фрагменте выше todo уже должно существовать.


Управление состоянием


Управлять состоянием в Svelte невероятно просто, и, пожалуй, эта часть фреймворка мне симпатизирует больше остальных. Про многословность кода при использовании Redux можно забыть. Для примера, создадим хранилище в нашем приложении для хранения и управления задачами.


Записываемые хранилища


Сначала нужно импортировать объект хранилища writable из пакета svelte/store и сообщить ему начальное значение initialState


import { writable } from 'svelte/store';

const initialState = [{
  name: "Изучить Svelte",
  done: false
},
{
  name: "Изучить Vue",
  done: false
}];

const todos = writable(initialState);

Обычно, я помещаю подобный код в отдельный файл вроде todos.store.js и экспортирую из него переменную хранилища, чтобы компонент, куда я его импортирую мог работать с ним.


Очевидно, что теперь объект todos стал хранилищем и более не является массивом. Для получения значения хранилища воспользуемся небольшой магией в Svelte:


  • Добавлением символа $ к имени переменной хранилища мы получаем прямой доступ к его значению!

Таким образом, просто заменим в коде все упоминания переменной todos на $todos:


{#each $todos as todo}
  <Todo todo={todo} on:done={onDone}></Todo>
{/each}

Установка состояния


Новое значение записываемого хранилища может быть указано вызовом метода set, которое императивно изменяет состояние согласно переданному значению:


const todos = writable(initialState);

function removeAll() {
  todos.set([]);
}

Обновление состояния


Для обновления хранилища (в нашем случае todos), основываясь на его текущем состоянии, нужно вызвать метод update и передать ему callback-функцию, которая будет возвращать новое состояние для хранилища.


Перепишем функцию onDone, которую мы создали ранее:


function onDone(event) {
  const name = event.detail;  
  todos.update((state) => {
    return state.map((todo) => {
       return todo.name === name ? {...todo, done: true} : todo;
    });
  });
 }

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


// todos.store.js
export function markTodoAsDone(name) {
  const updateFn = (state) => {
    return state.map((todo) => {
       return todo.name === name ? {...todo, done: true} : todo;
    });
  });  

  todos.update(updateFn);
}

// App.svelte
import { markTodoAsDone } from './todos.store';

function onDone(event) {
  const name = event.detail;
  markTodoAsDone(name);
}

Подписка на изменение состояния


Для того, чтобы узнать, что значение в хранилище изменилось, можно использовать метод subscribe. Имейте ввиду, что хранилище не является объектом observable, но предоставляет схожий интерфейс.


const subscription = todos.subscribe(console.log);
subscription(); // так можно отменить подписку

Observables


Если эта часть вызывала у вас наибольшие волнения, то спешу обрадовать, что не так давно в Svelte была добавлена поддержка RxJS и пропозала Observable для ECMAScript.


Как разработчик на Angular, я уже привык работать с реактивным программированием, и отсутствие аналога async pipe было бы крайне неудобным. Но Svelte удивил меня и тут.


Посмотрим на пример совместной работы этих инструментов: отобразим список репозиториев на Github, найденных по ключевому слову "Svelte".


Вы можете скопировать код ниже и запустить его прямо в REPL:


<script>
 import rx from "https://unpkg.com/rxjs/bundles/rxjs.umd.min.js";
 const { pluck, startWith } = rx.operators;
 const ajax = rx.ajax.ajax;

 const URL = `https://api.github.com/search/repositories?q=Svelte`;

 const repos$ = ajax(URL).pipe(
    pluck("response"),
    pluck("items"),
    startWith([])
 );
</script>

{#each $repos$ as repo}
  <div>
    <a href="{repo.url}">{repo.name}</a>
  </div>
{/each}

<!-- 
  Имплементация в Angular:

  <div *ngFor="let repo of (repos$ | async)>
    <a [attr.href]="{{ repo.url }}">{{ repo.name }}</a>
  </div> 
-->

Просто добавляем символ $ к имени observable-переменной repos$ и Svelte автомагически отображает её содержимое.


Мой список пожеланий для Svelte


Поддержка Typescript


Как энтузиаст Typescript, я не могу не пожелать возможности использования типов в Svelte. Я так привык к этому, что порой увлекаюсь и расставляю типы в своём коде, которые потом приходится убирать. Я очень надеюсь, что в Svelte скоро добавят поддержку Typescript. Думаю этот пункт будет в списке пожеланий любого, кто соберётся использовать Svelte имея опыт работы с Angular.


Соглашения и гайдлайны


Отрисовка в представлении любой переменной из блока <script> — очень мощная возможность фреймворка, но на мой взгляд, может привести к замусориванию кода. Я надеюсь, что сообщество Svelte проработает ряд соглашений и гайдлайнов, чтобы помочь разработчикам писать чистый и понятный код компонентов.


Поддержка сообществом


Svelte — грандиозный проект, который, при увеличении усилий со стороны сообщества в написании сторонних пакетов, руководств, статей в блогах и прочим, может взлететь и стать признанным инструментом в удивительном мире Frontend-разработки, который мы имеем сегодня.


В заключение


Несмотря на то, что я не был поклонником предыдущей версии фреймворка, Svelte 3 произвёл на меня хорошее впечатление. Он простой, небольшой, но умеет очень многое. Он настолько отличается от всего вокруг, что напомнил мне тот восторг, который я испытал, когда перешёл с jQuery на Angular.


Вне зависимости от того, какой фреймворк вы используете сейчас, изучение Svelte, скорее всего, отнимет лишь пару часов. Как только вы узнаете основы и поймёте различия с тем, что вы уже привыкли писать, работать со Svelte станет очень легко.


В русскоязычном Telegram-канале @sveltejs вы обязательно найдёте разработчиков, имеющих опыт работы с различными фреймворками и готовых поделится своими историями, мыслями и советами касательно Svelte.

Комментарии (49)


  1. zoonman
    12.09.2019 05:53
    +1

    Я наверно один такой сумасшедший, но мне совсем непонятно, зачем делать все эти решетки, звездочки и прочий кошмар в коде.


    В чем проблема написать интерпретатор, способный нормально работать с такими шаблонами?


    <script>
      const todos = ['Код должен быть простым!']
      let newTodo = 'Новое значение'
      const add = () => {
        todo.push(newTodo)
      }
    </script>
    
    <div bind="todos" index="todoKey">
      Наш ключик {todoKey}. и здесь его значение {.}.
    </div>  
    
    <input type="text" value="{newTodo}">
    <button onClick="add()">Добавить<button>

    В данном случае транспайлер должен быть достаточно "умен", чтобы понять, что в bind передается итерируемое значение.
    Передачу параметров внутрь можно реализовать через механизм, подобный React props.
    Везде есть нормальный двухнаправленный биндинг для обычных компонентов ввода.


    Могу привести альтернативный пример подобного подхода


    <script>
    class Todos extends Component {
      // наш траспайлер поймет, что это свойство инициализируется через конструктор
      private items: string[];
      // как бы мы не использовали наш класс, мы всегда можем его отбразить в строку
      toString(): string {
        return <ul>
          <li bind="this.items">{.}</li>
        </ul>
      }
    }
    <script>
    <Todos items="['']" />

    А теперь просто покажу такую идею


    <ul>
          <li bind="['a', 'b', 'c']">{.}</li>
     </ul>

    Вместо bind можно использовать что-то другое, например делать так


    <script>
    const items = ['a', 'b', 'c']
    </script>
    <ul>
          <input {items} value={.} />
     </ul>

    С таким подходом можно писать простые приложения с точки зрения его интерпретации человеком. А машине все равно, что ей скормят, главное, чтобы она могла это быстро и без ошибок выполнить.


    1. PaulMaly
      12.09.2019 09:25

      Я наверно один такой сумасшедший, но мне совсем непонятно, зачем делать все эти решетки, звездочки и прочий кошмар в коде.

      Может быть потому что не всем нравятся управляющие конструкции в тегах? Этим страдают Vue и Angular и это является главным минусом их шаблонизаторов.


      1. AlexxNB Автор
        12.09.2019 10:04

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


        1. Carduelis
          12.09.2019 10:41

          А мне кажется — Svelte не взлетит именно из-за синтаксиса.


          1. PaulMaly
            12.09.2019 17:47

            Это все вкусовщина, но факт остается фактом — новый синтаксис Svelte 3 нравится значительно больше значительно большему кол-ву человек, иначе не было бы роста, который пришелся аккурат после выхода Svelte 3.


  1. mamont80
    12.09.2019 08:03

    Как раз нахожусь перед выбором шаблонизатора для небольшого проекта. Svelte интересная вещь для не очень навороченных интерфейсов, где Angular или React избыточны, но пока имеет 2 существенных для меня недостатка: он не typescript-френдли и сложность отладки из-за плохой поддержки со стороны IDE. И то и другое меня пугает, это шаг назад. Так что да, но наверное пока нет.


    1. PaulMaly
      12.09.2019 09:24

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


      1. lexey111
        12.09.2019 14:24

        Svelte намного мощнее React


        вот этот тезис можно развернуть?


        1. PaulMaly
          12.09.2019 17:49
          +1

          Кол-во встроенных возможностей в Svelte сопоставимо с Vue и даже больше (есть встроенные store/transitions/animations/etc). React же это не более чем шаблонизатор, фукнция от стейта. Да, блин, он банально даже не реактивный.))))


          1. lexey111
            12.09.2019 18:52

            Понятно, спасибо.


    1. vintage
      14.09.2019 09:22

      typescript-френдли

      Боюсь нормально интергрируется с TS лишь один шаблонизатор — JSX. И то с ограничениями. Всё остальное нормально с тайпскриптом не интегрируется, пока MS не добавит в него хотя бы поддержку трансформаций до тайпчекинга.


      1. JustDont
        14.09.2019 09:31

        Да вы что. Всё, что основано на tagged template literals — внезапно, тоже нормально интегрируется и не жужжит.


        1. vintage
          14.09.2019 09:44

          Что, и подсказки в именах компонент и их свойств в строковых литералах работают?


          1. JustDont
            14.09.2019 09:51
            -1

            А должны?
            Вы, фактически, тут просите TS поработать на разбор HTML. TS не умеет разбирать HTML.


            1. vintage
              14.09.2019 13:27
              +3

              TS умеет в плагины, только сейчас они отрабатывают после тайпчека. Если бы их можно было применять к AST до тайпчека, то можно было бы расширять тайпскрипт любым синтаксисом.


              1. JustDont
                15.09.2019 10:09
                -1

                Конечно умеет. Дело в том, что TS в общем виде и не должен разбираться с HTML — зачем это ему? Это ж не проект универсального парсера и лексера всего на свете. Артефакты другого языка уместнее разбирать соответствующим инструментом.


  1. JustDont
    12.09.2019 08:17

    Смотрел сам примерно 8 месяцев назад, выводы точно такие же: стильно, модно, молодёжно, но в продакшн — извините. Только когда (если) будет TS и вменяемая поддержка через IDE. Хотя за пределами этого проблем вроде б нет, и даже транспилируется оно всё до веб-компонентов — а это значит, что в целом будет уживаться с остальным миром, хотя вот в сабже всё такая же убогая закрытость css от внешнего доступа, как и в css modules и shadow dom (пока что, пока :part и :theme не взлетят), и это тоже в серьезном коде будет страшно мешать.


    1. PaulMaly
      12.09.2019 09:19

      Смотрел сам примерно 8 месяцев назад, выводы точно такие же: стильно, модно, молодёжно, но в продакшн — извините.

      NYT, GoDaddy, Яндекс.Деньги и Mail.Ru почему-то решили что норм. ;-) Но это ваше право конечно.


      1. JustDont
        12.09.2019 09:42

        NYT, GoDaddy, Яндекс.Деньги и Mail.Ru почему-то решили что норм. ;-)

        Argumentum ad verecundiam. Придумайте что-нибудь поинтереснее. Пока что вы слишком похожи на Wrike, которые со своим «нам не хочется признаваться, что dart был выбран по большей части от безысходности на тот момент, а поэтому будем топить за то, что это аж сам Хухл изобрел!».


        1. PaulMaly
          12.09.2019 17:45

          Знаете, мне то пишут что мол никто не использует из известных компаний, значит не готово для прода. А когда пишу кто в итоге использует, ретируются с ответов вроде вашего. Всем не угодишь.

          Вы, в целом тоже не блещите своей аргументацией ни в предыдущем комментарии, ни в других комментариях к другим статьям. Так что извините.


          1. JustDont
            12.09.2019 21:46

            Вы, в целом тоже не блещите своей аргументацией ни в предыдущем комментарии, ни в других комментариях к другим статьям.

            Я и не собирался блистать, всего лишь назвал критичные на мой взгляд недостатки. На что вы рассчитываете, когда на «нет TS и поддержки IDE» вы в ответ пишете «зато этим всякие условно-важные конторы пользуются»?
            От того, что сабж где-то среди всего Mail.Ru применили — появилась поддержка TS, или что?

            И эти люди будут мне за аргументацию чего-то объяснять, ага.


            1. PaulMaly
              13.09.2019 11:38

              Учитывая что вы даже не в курсе про сорс-мапы, кажется глубина вашего погружения была недостаточная, чтобы оценить какая поддержка TS или IDE имеется на данный момент. 8 месяцев назад это очень давно, тогда еще и Svelte 3 то не было.

              И опять же, причем тут TS если статья находится в хабе по JS и имеет тег JS. Можно с таким же успехом прийти и про CoffeScript затирать. Любите TS любите дальше, никто вас ни к чему не призывает, но не обязательно пытаться его присунуть везде где он не нужен.


              1. JustDont
                13.09.2019 14:59

                была недостаточная, чтобы оценить какая поддержка TS или IDE имеется на данный момент

                Так и какая?

                И опять же, причем тут TS

                При том, что лично я отношу отсутствие поддержки TS к существенным недостаткам. При чём тут хабы и теги?


                1. PaulMaly
                  13.09.2019 16:29

                  Так и какая?

                  Нормальная поддержка IDE. TS поддерживается в скриптах, в шаблонах нет, но можно и минимизировать выражения в шаблонах и не использовать автоматические биндинги.

                  При том, что лично я отношу отсутствие поддержки TS к существенным недостаткам. При чём тут хабы и теги?

                  Потому что это 2 разных языка. Это как сейчас набегут адепты Elm в статью по React и начнут ныть, что React не поддерживает Elm.


                  1. JustDont
                    13.09.2019 16:49

                    Нормальная поддержка IDE.

                    Я вижу WIP Language Server с открытыми issues в духе «TS не поддерживается» и «Language server молча падает». На моем языке это называется «поддержка IDE начинает появляться».

                    TS поддерживается в скриптах, в шаблонах нет, но можно и минимизировать выражения в шаблонах и не использовать автоматические биндинги.

                    Вот это говорит мне о том, что таки «TS не поддерживается». То, что можно проявить некоторую ловкость рук, и намазать TS отдельным слоем сборки над всей конструкцией — это нельзя назвать поддержкой.

                    Потому что это 2 разных языка.

                    И?
                    На всякий случай, если вы с первого раза не прочитали: «назвал критичные на мой взгляд недостатки». По каким причинам лично вы считаете это не важным или недостаточно важным — мне совершенно неинтересно.


                    1. PaulMaly
                      13.09.2019 20:14

                      Я вижу WIP Language Server с открытыми issues в духе «TS не поддерживается» и «Language server молча падает». На моем языке это называется «поддержка IDE начинает появляться».

                      А причем тут TS? Я про поддержку синтаксиса Svelte. На TS всем плевать.

                      Вот это говорит мне о том, что таки «TS не поддерживается». То, что можно проявить некоторую ловкость рук, и намазать TS отдельным слоем сборки над всей конструкцией — это нельзя назвать поддержкой.

                      Это ишак про поддержку из коробки, которая нафиг не нужна. Для таких вещей придуманы препроцессоры. Собственно TS это и есть препроцессинг для JS, поэтому не вижу тут ничего из разряда «ловкость рук». Точно также нужно поставить препроцессоры для PostCSS или SCSS если они необходимы. Так как 100% разработчиков Svelte не нужен TS, значит его не должно быть в Svelte по-умолчанию.

                      На всякий случай, если вы с первого раза не прочитали: «назвал критичные на мой взгляд недостатки». По каким причинам лично вы считаете это не важным или недостаточно важным — мне совершенно неинтересно.

                      Кроме фейспалма, у меня ничего для вас нет в этом вопросе.


                      1. JustDont
                        13.09.2019 20:22

                        Для таких вещей придуманы препроцессоры.

                        Конечно. Транспилятор TS таковым и является, вам не надо писать собственный.
                        Собственно TS это и есть препроцессинг для JS

                        Даже странно, что вы так быстро это для себя открыли.
                        поэтому не вижу тут ничего из разряда «ловкость рук»

                        «Ловкость рук» — это вот это вот:
                        TS поддерживается в скриптах, в шаблонах нет, но можно и минимизировать выражения в шаблонах и не использовать автоматические биндинги.

                        В переводе с русского на русский это и означает «да, вы можете пользоваться TS, но требуется проявить некоторую ловкость рук». Когда не будет никакого «но» — это и будет означать поддержку TS.


                        1. PaulMaly
                          13.09.2019 21:29

                          Конечно. Транспилятор TS таковым и является, вам не надо писать собственный.

                          А мне и не надо. Надо писать препроцессор для компонентов Svelte (точнее он уже написан), потому что они не просто JS, а SFC.

                          Даже странно, что вы так быстро это для себя открыли.

                          Если вы согласны с тем, что TS это препроцессинг, тогда в чем проблема его использоваться как препроцессор? Зачем его по-умолчанию включать туда, где он не нужен всем, а только вам например?

                          В переводе с русского на русский это и означает «да, вы можете пользоваться TS, но требуется проявить некоторую ловкость рук». Когда не будет никакого «но» — это и будет означать поддержку TS.

                          Это означает только то, что TS штука ограниченная в возможностях. Это TS не поддерживает использование кастомных шаблонизаторов. Как только TS начнет поддерживать HTMLx, никаких проблем с ним в шаблонах не будет.

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


                          1. JustDont
                            13.09.2019 21:50

                            Если вы согласны с тем, что TS это препроцессинг, тогда в чем проблема его использоваться как препроцессор?

                            Всё в том же:
                            TS поддерживается в скриптах, в шаблонах нет, но можно и минимизировать выражения в шаблонах и не использовать автоматические биндинги.


                            Зачем его по-умолчанию включать туда, где он не нужен всем, а только вам например?

                            А я вам где-то это предлагал? Или вы сами выдумали и сами же обиделись?

                            Это означает только то, что TS штука ограниченная в возможностях.

                            Это означает то, что ограниченная в возможностях штука по имени TS мне нужна для достижения других важных вещей (статической типизации), и серьезных конкурентов у неё нет. В то время как Svelte — это очень здоровская концепция, но ничего функционально уникального в ней нет: сочетание одного из нескольких десятков компонентных фреймворков с одним из дюжин инструментов для управления стейтом даст в итоге всё то же самое. Чуть менее изящно и с чуть большим количеством кода в рантайме, но нисколько не менее функционально (а то и более).
                            Поэтому в выборе «или-или» проиграет отнюдь не TS.

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

                            Для фанатов никогда нет преград. Это JS, где всегда можно примерно всё, хоть Ангуляр вместе с реактом и Vue на одной странице. Вопрос не в «можно-нельзя», а в «а так уж ли это надо?».


  1. zim32
    12.09.2019 10:12

    У Vue лучше, меньше скобочек, которых я терпеть не могу

    <input on:input={(e) => onChange(e, ‘a’)} /> — Svelte
    <input input=«onChange($event, 'a')»> — Vue


    1. AlexxNB Автор
      12.09.2019 10:46

      Возможно. Просто поясню, что в Svelte в атрибутах внутри {} всегда используется javascript выражение, по аналогии с правой частью стрелочной функции. Поэтому, и в шаблонах Svelte можно написать такую же короткую запись как и в Vue(даже еще короче):


      <input on:input={onChange(‘a’)} />

      Просто надо понимать, что обработчиком события станет не сама функция с переданным ей параметром, а то, что она вернёт.


      Поэтому, можно в компоненте объявить функцию для обработчика таким образом:


      const onChange = (param)=>(e)=>console.log(e,param);


  1. Kanut
    12.09.2019 11:15

    Интересно, но явных преимуществ лично я пока не вижу. Ну или если точнее, то что-то сделано лучше чем в Angular, что-то [как минимум пока] хуже. Аналогично с React/Vue.
    Но я не вижу ничего что было бы лучше чем во всех уже имеющихся альтернативах.


    И в такой ситуации лично я не буду выбирать для рабочих решений "молодой" и необкатанный фреймворк без большого коммьюнити и всех вытекающих из этого последствий.


    1. shurkandak
      12.09.2019 11:27

      Тоже хотел этот вопрос задать


    1. AlexxNB Автор
      12.09.2019 11:29

      Главная особенность, отличающая Svelte от мейнстрима — он компилируется, а не тащит рантайм с собой. В статье про это ни слова, по-скольку у нее цель помочь ангулярщикам "въехать" в Svelte. А особенности уже не раз обсуждались в других статьях, в том числе и на Хабре.


      1. Kanut
        12.09.2019 11:37

        Вот об этом тогда пожалуйста поподробнее. Что значит "компилируется" и в чём отличие от того же Angular, который вроде бы тоже компилирует Typescript в Javascript?
        И что имеется ввиду под "рантайм" и что конкретно Svelte меньше тащит по сравнению с Angular.


        П.С. Я взял Angular для примера потому что в статье скорее сравнивают с ним, но если не сложно то было бы интересно прочитать и какие в этом плане есть отличия/преимущества по сравнению с React/Vue.
        П.П.С. Если это слишком обширная тема для комментариев, то с удовольствием подожду отдельную статью или хотя бы ссылочку:)


        1. YNile
          12.09.2019 11:39

          Вот тут с избытком
          habr.com/ru/post/446026


        1. AlexxNB Автор
          12.09.2019 11:40

          Можно почитать вводную статью по Svelte3 — https://habr.com/ru/post/449450/
          Комментарии, как всегда, сильно интереснее самой статьи =)


          1. Kanut
            12.09.2019 11:48

            YNile и AlexxNB спасибо, а то просто по слову svelte "нахабрилось" очень много статей :) Пошёл читать :)


            П.С. И на работе конечно всё равно вряд ли буду использовать в ближайшие годы, но может хоть дома руки попробовать дойдут :)


            1. Kanut
              12.09.2019 14:34

              В общем почитал в обед поподробнее и наверное всё-таки останусь при своём мнении.


              Особых плюсов я пока не вижу. То есть в теории может быть, но конкретно в наших проектах пожалуй нет.
              А вот отсутствие typescript, относительно маленькое коммьюнити и слабая поддержка IDE это одгозначно большие минусы.


              Гляну на это дело ещё раз годика через два-три:)


      1. JustDont
        12.09.2019 11:58

        Главная особенность, отличающая Svelte от мейнстрима — он компилируется, а не тащит рантайм с собой.

        Это сложно записать в неоспоримое «лучше», ибо дебаг тут же машет ручкой из-за угла: если пишется одно, а выполняется уже другое, то для полноценного дебага нужен сопоставлятор выполняемого кода и исходников. А его нет.

        Это «интересно», но не обязательно «лучше».


        1. AlexxNB Автор
          12.09.2019 12:02

          Source maps же для этого и придуманы?


          1. JustDont
            12.09.2019 12:13

            Source maps откуда куда? ЧТО у вас будет исходником к написанному в ходе компиляции коду? Понятно, что замапить содержимое ваших <script> наверное можно (кстати, можно?), а как понять, откуда растут ноги у всего остального? У ошибок в svelte-коде, например? Как вы, например, будете выяснять, то ли баг порождается вашим кодом, то ли самим компилятором?


            1. AlexxNB Автор
              12.09.2019 12:38

              * В dev-режиме дебаг идет по исходным текстам, естественно:

              Скриншот
              image


      1. Yeah
        12.09.2019 16:00

        В большом проекте, а не ToDoMVC, процент рантайма в общем объеме кода будет снижаться, а вот "вес" экосистемы, комьюнити и банально количества разработчиков, доступных для найма тут выйдет на первый план


        1. PaulMaly
          12.09.2019 18:00

          Так и в 2013 году рассуждали люди когда принимали решение попробовать React или остаться на jquery. Многие и до сих пор на нем сидят, но вряд ли это остановит прогресс.


          1. xadd
            12.09.2019 19:17
            +1

            В 2013 помню что VDOM стал революцией, а facebook корпорацией добра. JavaScript быстрее, чем вы думаете, говорили они… В итоге народ до сих пор и возится с атомарными компонентами, с разными memo, PureComponent и shouldComponentUpdate в борьбе с реконсиляцией.


      1. vintage
        14.09.2019 09:31

        import {
            SvelteComponent,
            append,
            detach,
            element,
            init,
            insert,
            listen,
            noop,
            safe_not_equal
        } from "svelte/internal";
        import { createEventDispatcher } from "svelte";

        Вот это вот тоже "компилируется, а не тащит в рантайм", да?


        1. AlexxNB Автор
          14.09.2019 10:43
          +1

          Конечно же, не без хелперов — атомарные операции над DOM и прочее, например:


          // append
          export function append(target, node) {
              target.appendChild(node);
          }

          Вся эта история с "исчезновением", конечно же, рекламный трюк, всего там насобирается аж 1043 байта загзипованного кода для пустого приложения.


          Под отстутсвием рантайма можно понимать всю ту логику, которая происходит при вычислении изменений представления при изменении стейта. Это то всё как раз и происходит во время компиляции, а не во время выполнения.


  1. feligz
    12.09.2019 16:31
    +2

    Очень приятный фреймворк. Сделал 2 небольших проекта на нем, очень доволен. Реактивный, простой, понятный, мощный, легкий. Особых проблем не обнаружил, ни разу не ходил на стэк за подсказкой. Рич (создатель фреймворка) каждый день сидит в дискорде и отвечает на вопросы, да и коммьюнити уже довольно большое.