Вышел Svelte v2!

Тут всё, что вам нужно знать

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

Краткая инструкция по обновлению

Каждый пункт по списку ниже мы разберём подробнейшим образом. При возникновении проблем, пишите в наш чатик.

  • Установить Svelte v2 с помощью npm
  • Обновить шаблоны при помощи svelte-upgrade
  • Remove calls to component.observe, or add the observe method from svelte-extras
  • Убрать все вызовы component.observe, при необходимости их можно заменить на метод observe из библиотеки svelte-extras
  • Переделать все вызовы component.get('foo') к виду component.get().foo
  • Обновить все ваши пользовательские обработчики событий, чтобы они возвращали destroy вместо teardown
  • Убедится, что вы нигде не передаёте компонентам в свойствах числовые строки

Новый синтаксис шаблонов

Наиболее заметное изменение: мы внесли некоторые улучшения в синтаксис шаблона.

Часто, первой реакцией людей, когда они видели шаблоны предыдущей версии было что-то вроде 'фууу... усы'. Кое-кто из тех, кто в былые времена использовал системы шаблонов на основе строк их реально не любят. Поскольку Svelte в своё время взяла {{...}} из этих языков, эти люди решили, что мы каким-то образом перетащили и ограничения этих инструментов, вроде странных правил области видимости или невозможность использования произвольных JavaScript выражений.

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

<h1>Привет {name}!</h1>

Есть несколько других обновлений. Но вам не нужно делать их вручную — просто натравите утилитку svelte-upgrade на вашу папку с исходниками:

npx svelte-upgrade v2 src

Только убедитесь, что любой встретившийся в src файл .html является компонентом Svelte. Вы можете указать любой каталог, который вам нужно. Например, следует выполнить npx svelte-upgrade v2 router для обновления приложения Sapper.

Чтобы посмотреть полный список изменений, загляните в svelte-upgrade README.

Вычисляемые свойства

Ещё одна вещь, которая в Svelte часто вводила в заблуждение Svelte — это то, как работали вычисляемые свойства. Напомним, если у вас был компонент...

export default {
  computed: {
    d: (a, b, c) => a = b + c
  }
};

... тогда Svelte сначала смотрит на аргументы функции, чтобы увидеть, от каких значений зависит d, и затем он создаёт код, который обновляет d всякий раз, когда эти значения меняются, вводя их в функцию. Это круто, потому что это позволяет вам получать сложные значения из входных данных вашего компонента, не беспокоясь о том, когда их нужно пересчитать, но в то же время это... странно. JavaScript не работает таким образом!

В v2, мы используем деструктуризацию instead:

export default {
  computed: {
    d: ({ a, b, c }) => a = b + c
  }
};

Компилятор Svelte по-прежнему может видеть, от каких значений зависит d, но он больше не вытаскивает значения — он просто передаёт объект состояния компонента в каждое вычисляемое свойство.

Опять же, вам не нужно вносить это изменение вручную — просто запустите svelte-upgrade для ваших компонентов, как было показано выше.

Извини, IE11. Это не для тебя, это ... ну на самом деле, да. Для тебя

Svelte v1 был ограничен рамками ES5 при генерации кода, чтобы вам не пришлось использовать транспилеры для его использования. Но сейчас 2018 год, и почти все браузеры поддерживают современный JavaScript. Сняв ограничение ES5, мы можем создвать более простой код.

Если необходима поддержка IE11 и сотоварищей, теперь придётся использовать транспилеры типа Babel или Bublé.

Новые хуки жизненного цикла

В дополнение к oncreate и ondestroy, в Svelte v2 добавлены ещё два хука жизненного цикла для реагирования на изменения состояния:

export default {
  onstate({ changed, current, previous }) {
    // вызывается перед oncreate, всякий раз
    // при изменении состояния
  },

  onupdate({ changed, current, previous }) {
    // вызывается после oncreate, и всякий раз
    // когда DOM был обновлён вслед
    // за изменением состояния
  }
};

Вы также можете словить эти события у себя в коде:

component.on('state', ({ changed, current, previous }) => {
  // ...
});

component.observe

С новыми хуками жизненного цикла нам больше не нужен метод component.observe(...):

// было
export default {
  oncreate() {
    this.observe('foo', foo => {
      console.log(`foo = ${foo}`);
    });
  }
};

// стало
export default {
  onstate({ changed, current }) {
    if (changed.foo) {
      console.log(`foo = ${current.foo}`);
    }
  }
};

Это сокращает объём кода, который необходимо сгенерировать Svelte, и даёт вам больше гибкости. Например, теперь очень легко предпринимать действия, когда изменилось какое-либо из нескольких свойств, например перерисовывать canvas, без срабатывания сразу нескольких функций observe.

Однако, если вы предпочитаете использовать component.observe(...), вы можете установить его из библиотеки svelte-extras:

import { observe } from 'svelte-extras';

export default {
  methods: {
    observe
  }
};

component.get

Этот метод больше не принимает необязательный аргумент key — вместо этого он всегда возвращает весь объект состояния:

// было
const foo = this.get('foo');
const bar = this.get('bar');

// стало
const { foo, bar } = this.get();

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

event_handler.destroy

Если в вашем приложении есть пользовательские обработчики событий, они должны возвращать объект с помощью метода destroy, а не метода teardown (это сближает обработчики событий с API компонентов).

Больше нет приведения типов

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

<Counter start='1'/>

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

<Counter start={1}/>

Изменения в компиляторе

В большинстве случаев вам никогда не придётся иметь дело с компилятором напрямую, поэтому это не должно требовать каких-либо действий с вашей стороны. В любом случае, стоит отметить: API компилятора изменился. Вместо объекта с мешаниной свойств компилятор теперь возвращает js,css, ast и stats:

const { js, css, ast, stats } = svelte.compile(source, options);

js и css являются объектами { code, map }, где code является строкой, а map — карта исходников(sourcemap). ast является абстрактным синтаксическим деревом вашего компонента, а объект stats содержит метаданные о компоненте и информацию о компиляции.

Раньше существовал метод svelte.validate, который проверял, что ваш компонент действителен. Это было удалено — если вы хотите проверить компонент без фактической его компиляции, просто передайте опцию generate: false.

Моё приложение сломалось! Помогите!

Надеюсь, мы объяснили все, что можно и обновление для вас должно быть проще, чем для нас. Но если вы обнаружите ошибки или обнаружите вещи, которые здесь не упомянуты, пишите в чат Discord или на багтрекер.