Транспайлер из Vue в Svelte
Запустить веб-морду:
yarn install
yarn workspace repl-vue serve
В репозитории три воркспейса:
- ./vue2svelte - сам транспайлер
- ./repl-vue - веб-морда на Vue
- ./repl-svelte - настроенный вебпак для Svelte
Чтобы, насколько это возможно, автоматизировать переезд на исчезающий фреймоврк Svelte кодовой базы, написанной на Vue.
Результат преобразования требует ручного допила (см. ниже "что не умеет"), но все равно ощутимо экономит время.
v-for
=>{#each}
v-if
=>{#if}
(else-if
/else
тоже умеет )<template>
обрабатывается<component is...>
=><svelte:component this>
:prop="..."
/v-bind:prop="..."
=>prop={...}
v-bind="props"
=>{...props}
@event
/v-on:event
=>on:event
- модификаторы событий:
click.stop
=>click|stopPropagation
etc. - если событие ловится на компоненте, используется хелпер
unwrapEvent
, достающий payload из.detail
- правильно понимает разные способы задания хендлера: выражение, ссылка на функцию, стрелочная функция
ref="someEl"
=>bind:this={refs$.someEl}
- корневому элементу добавляются
{$$restProps.style}
и{$$restProps.class}
- и
bind:this={el$}
если в исходнике vue было обращение кthis.$el
- все выражения в шаблоне прогоняются через маппинг имен переменных, для преобразований типа
$style
=>style$
(потому что переменные, начинающиеся с доллара, в Svelte обозначают чтение из store) - при этом умеет понимать локальный скоуп цикла
v-model
для<input type=radio|checkbox|text>
,<textarea>
и<select>
v-html
=>{@html ...}
- для не-статических классов используется хелпер
makeClass
(схлопывает массивы/объекты), кроме случая, когда класс состоит из единственного обращение к$style.someClass
- для не-статических стилей исплоьзуется хелпер
makeStyle
- для компонентов с
<template functional>
обрабатываются$$options
иprops
- data - ключи превращаются в
let key = val
, при необходимости оборачивается в IIFE - props =>
export let prop = defValue;
- vue-types: умеет доставать значение по умолчанию из
prop: Types.def(val)
- methods =>
const myMethod = () => {...}
- computed преобразуются в
$: name = expression
либо в$: name = (() => { doSmth })()
если тело функции состоит из нескольких стейтментов - watch - использует хелпер
makeWatcher
, если заданimmediate=true
либо если исплоьзуется второй аргументoldValue
, иначе просто создается ф-цияwatcherProp
+ ее реактивный вызов$: watcherProp(prop);
- lifecycle - вроде весь, но
beforeMount
/mounted
схлопнуты вonMount
, аналогично с дестроем - во всех функциях обращения к
this.smth
заменяются на простоsmth
- также умеет понимать
const { smth } = this
(можно и с алиасами) - компьютеды/методы сортируются так, чтобы переменная объявлялась до обращения к ней. Правда выяснилось, что svelte сам их сортирует, а с недавних пор и плагин для IDEA перестал ругаться.
- импорты
smth.vue
переименовываются вsmth.svelte
- импорт
vue-types
изничтожается - если где-то используется
$emit
, подключаетсяcreateEventDispatcher
и создаетсяdispatch
, на который замеяются все$emit
- алиасы типа
$emit -> dispatch
,$style -> style$
и т. д. можно настраивать - везде по возможности сохраняются док-блоки
Стили выносятся в отдельный файл componentName.pcss
и импортируются в компонент.
- игнорирует JSX / render-функцию (сделаю, чтобы она копировалась, но собирать полноценный шаблон нужно будет руками)
- ничего не знает про Vue.extend / миксины
- v-model на компонентах
- обработка дефолтов на пропсах из vue-types
- всякие динамически задаваемые опции типа
props: { ...otherCom.props }
- сложный доступ вида
this[computedPropName]
v-on={...$listenrs}
provide
/inject
Можно скопировать содержимое папки sourceDir
в targetDir
, применяя преобразование к файлам .vue
и копируя все остальное как есть.
cd ./vue2svelte
yarn transpile --config=path/to.config.js
Пример конфига - в файле v2s.config.js
- транспилирует веб-морду на Vue в работоспособное приложение на Svelte, записывая файлы в ./repl-svelte
Проверить, что получилось:
yarn workspace repl-svelte serve
Изготовлено в благословенных стенах Ozon Tech - кстати, мы нанимаем! =)