company_banner

Хороший ли выбор Svelte для реализации виджета?

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


    CitymobilSvelte


    Исходные данные


    Задача: создать виджет для заказа такси через сайт.


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


    Что было важно в моем случае:


    1. Со стороны бизнеса:
      • Виджет должен быстро загружаться и запускаться. Как следствие, итоговый размер бандла должен быть как можно меньше.
    2. Со стороны разработки:
      • Компонентный подход. Это позволит легче вносить дальнейшие изменения.
      • Возможность не манипулировать DOM вручную. Это позволит быстрее писать код.
      • Хотелось, чтобы эту технологию развивали, у нее было сообщество и толковая документация.

    Самое главное в этом списке — размер бандла. У React, Vue и Angular с этим проблемы.


    React Vue Angular
    Размер в runtime (gzip + min) 39,5 Кб + 2,6 Кб 22.8 Кб 90, 1 Кб

    Я начал искать другие технологии, и вспомнил о Preact и Svelte.


    Тут обращал внимание на два пункта:


    1. Все тот же размер в runtime.
    2. Stateofjs — насколько интересна технология для разработчиков, и насколько они ей удовлетворены.

    Stateofjs


    Preact Svelte
    Размер в runtime (gzip + min) 3,8 Кб 1,4 Кб
    Удовлетворены 78% 88%
    Интересна 40% 67%

    Из дополнительных плюсов Preact: весь фронтенд в нашей компании сейчас пишется на React, и это дало бы взаимозаменяемость.


    Преимущества Svelte:


    1. Выигрышные показатели в таблице.
    2. Отличная возможность для эксперимента, так как проект маленький. Preact тут проигрывает, так как это React внутри, который у нас уже везде используется.
    3. Большая часть компонентов на главной странице Mail.ru написано на Svelte.

    Поговорил с коллегами, и мы сошлись в выборе Svelte.


    Пара слов о Svelte


    Svelte — это язык с принципиально новым подходом к созданию пользовательских интерфейсов. Тогда как традиционные фреймворки, такие как React и Vue, выполняют основную часть своей работы в браузере, Svelte переносит эту работу на этап компиляции, который происходит при сборке приложения.

    Советую прочитать эту статью, чтобы узнать больше о Svelte.


    Реализация


    Виджет представляет из себя модальное окно с несколькими экранами и формами внутри.


    Widget


    Тут нужно было понять, сможет ли Svelte реализовать ту функциональность, которая указана в ТЗ. Потратив день на изучение и проверку, я пришел к выводу, что сможет, и приступил к реализации.


    Виджет доступен — здесь. Сама реализация не заняла много времени — в Svelte есть огромное количество полезных инструментов (об этом далее).


    Из самых запомнившихся моментов: поднятие локального reverse proxy для общения с серверной частью в обход CORS. Изначально для сборки проекта был выбран rollup, но, как потом оказалось, нельзя сделать так, чтобы был активным и hot reload, и proxy, потому что каждый дает свой собственный сервер, а использовать можно только один. Пришлось менять уже подготовленный rollup на webpack.


    В остальном, все проблемы, с которыми я сталкивался, решались быстро.


    Итак, достоинства Svelte


    Опишу все достоинства, которые заметил в процессе выбора технологии и реализации проекта.


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


    Низкий порог входа


    Здесь простой JS/HTML/CSS в компонентах и дополнительные бонусы из больших фреймворков. Новички и разработчики с опытом в Vue/React/Angular, определенно, найдут в Svelte что-то знакомое.


    Скорость


    1. Размер в runtime (min+gzip) 1,4 Кб.
    2. Нет virtual DOM. Svelte на этапе сборки знает все состояния приложения, и как оно может между ними меняться.
    3. Минимум бойлерплейта.
    4. Технология удаления мертвого CSS. Если ваше приложение не использует какую-то часть CSS-кода, то подключенный linter подскажет. А если вдруг вы забудете этот код удалить, компилятор это сделает за вас.

    Много полезных инструментов для разработки


    1. Есть компонентный подход.
    2. Есть реактивность.
    3. Есть жизненные циклы компонента.
    4. Есть context и stores, позволяющие взаимодействовать между компонентами.
    5. Actions. Еще рекомендую статью AlexxNB, в которой он раскрыл больше примеров.
    6. Есть самая простая и функциональная анимация, какую я когда-либо видел. Несмотря на то, что анимации пишутся в виде JS-функций, они компилируются в нативные CSS-анимации и, соответственно, выполняются в отдельном от JS потоке.

    Сообщество и документация


    1. Есть подробная документация на сайте.
    2. Руководство, в котором, есть все, что нужно знать, чтобы начать писать на Svelte.
    3. Есть русскоязычное сообщество в Telegram, в котором более 1500 человек.
    4. Есть официальный Discord с чатами на разные тематики (sapper, svelte, jobs, typescript, etc).

    Минусы Svelte


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


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


    Подсветка синтаксиса в Gitlab


    Синтаксис Svelte в Gitlab изначально не подсвечивается. При командной разработке это большая проблема. PaulMaly подсказал, что можно воспользоваться gitattributes в качестве обходного решения.


    Нет подсветки синтаксиса


    Мониторинг ошибок


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


    Количество библиотек


    Готовых решений очень мало.


    Количество библиотек


    Выводы


    1. Тщательно проверяйте, соответствует ли выбранная вами технология заявленным требованиям.
    2. При реализации показалось, что лучше технологии для виджета и быть не может. Писать на Svelte было большим удовольствием. Надеюсь, появятся еще проекты, в которых можно будет его применить.
    3. Svelte — пример того, как не имея финансовой поддержки за плечами, можно сделать отличную технологию, у которой, определенно, есть ниша для применения. Рассчитываю, что с годами она будет только расти.

    Полезные ссылки и плагины на примере vscode



    Благодарности


    Хочу сказать отдельное спасибо Евгению Володину, Кристине Цараевой, Павлу Малышеву, Артему Пулявину, Владу Кабанцову, Павлу Луговкину за ревью этой статьи.

    Ситимобил
    Компания

    Комментарии 19

      +3
      Два раза перестраховались фразой о личном мнении. Неужели столько хейта в комментах на хабре. А статья хорошая, спасибо!
        +1
        Спасибо за статью и личный опыт. Уже около года слежу за ростом активности и популярности Svelte. Интересно ваше мнение — насколько он подходит для более крупных приложений, нежели обособленные виджеты? Будет ли выигрышно с точки зрения производительности, скорости разработки и удобства сопровождения заменить им один из фреймворков популярной тройки?
          0
          Спасибо за комментарий!
          Нужно всегда отталкиваться от требований. Мне кажется на все Ваши вопросы может ответить видео Ильи Климова. Он там подробно разбирает случаи, когда Svelte может подойти, а когда нет. Очень рекомендую. Оно немножко устарело в замечании с typescript, но большая часть там актуальна.
          +1
          Можно ли ознакомиться с исходниками виджета в учебных целях?
            0
            Размер в runtime (gzip + min) 39,5 Кб + 2,6 Кб 22.8 Кб 90, 1 Кб (bundlephobia)

            Каким образом размер npm пакета стал размером runtime? Весь npm пакет это не есть размер runtime отдельного приложения/виджета. Также стоит учитывать AOT/Ivy/tree-shaking.
              0
              Спасибо за комментарий!
              Имелось ввиду, сколько станет размер бандла если добавить только пакет(ы) React/Angular/Vue. Именно это показывает bundlephobia. У vue и angular действительно есть tree-shaking о чем у них тоже сказано. Но они все равно не сравнятся со svelte или preact.
              image
                –1
                Vue 3 is tree shaking-friendly. The core runtime has gone from ~20kb in size, gzipped, to ~10kb, gzipped.
                github.com/LayZeeDK/ngx-ivy-minimal-rendercomponent-app
                Но я не спорю с тем что именно для встраиваемых штуковин, как виджеты, svelte может быть рассмотрен как вариант.
              +2
              Слабовато для хабра… ну можно написать вижет на свелте и чт? А где тех. детали? Где сам код? Где пример тогоже функционала на др. более популярном фреймворке или вообще без него? Если писалось ради размера бандла, то может тогда вообще обычный аякс + пхп зарешает…
                0

                Поддержу. Модальное окно с 4 полями ввода, никаких сложных состояний и переходов нет, а точно ли был нужен фреймворк с декларативными шаблонами? Не проще ли было обойтись ванильным JS?

                  +1
                  Не проще. Если бы писалось на ванильном JS, то время тратилось на вещи, которые в фреймворках есть уже из коробки. Создавать с нуля их, зачем, если есть готовые решения? Например, обновлять DOM, если состояние компонента зависело от какой-то переменной, которая изменилась и не обновлять, если не изменилась.
                  Если говорить про Svelte, то он практически ничего не весит в runtime, потому что все свои работы делает на этапе компиляции и код в бандле получается, практически такой же, как если бы писался на ванильном js, да и пишется практически как ванильный.

                  К слову, вот пример с формой телефона, который я подсмотрел у AlexxNB, тут явно виден ванильный js.

                    function formatByPattern(node, pattern) {
                      const setCursor = () => {
                        const match = node.value.substr(2).match(/[\d]/gi);
                        const pos = match ? node.value.lastIndexOf(match.pop()) + 1 : 3;
                        node.setSelectionRange(pos, pos);
                      };
                  
                      const formatValue = e => {
                        let digits = node.value
                          .substr(3)
                          .replace(/[^\d]/g, '')
                          .split('');
                        node.value = pattern.replace(/[*]/g, m => digits.shift() || m);
                        setCursor();
                      };
                  
                      node.addEventListener('input', formatValue);
                  
                      return {
                        destroy: () => node.removeEventListener('input', formatValue)
                      };
                    }
                  
                  <input
                      use:formatByPattern={'+7 (***) ***-**-**'}
                      type="text"
                      bind:value={$phoneNumber}
                      placeholder="+7 (***) ***-**-**"
                    />
                  
                +1

                Дежурное напоминание о том, что если вы выбираете какую-то технологию по размеру бандла, нужно обязательно добавлять мониторинг на размер бандла в CI. В противном случае одно случайное добавление зависимости lodash или чего-то подобного похерит все ваши успехи.


                eilemust у вас есть что-то такое в процессе?

                  0
                  У меня в вебпак зашит webpack-bundle-analyzer + проверяю пакеты с помощью import-cost. Но тут, безусловно, на уровень CI внедрить, тоже не помешает. Спасибо за идею.
                  0

                  Отличная статья для старта мини-серии статей! Если будет возможность углубиться в технические тонкости и примеры (можно сделать их абстрактными, чтобы не конфликтовать с внутренними политиками организации) – огонь.

                    +1
                    Спасибо за статью. Заинтересовался, начал смотреть svelte и сразу же вопрос

                    Какой смысл сравнивать размеры фреймворков если svelte компилируемый и генерирует огромную кучу динамичекого кода при деплое? Все то, что вы сэкономили, не подключая, например, vue, — вернется вам в виде сгенеренного кода. Просто в vue этот код УЖЕ включен, а тут он генерится на лету.

                    Да, кода может будет поменьше (ведь подключаются только нужные части), но сравнение размеров все равно как-то теряет смысл, не? К тому же vue/react и прочие вы подключаете через CDN, и он наверняка у юзера уже закешен, а свое придется тянуть со своего сервера. Причем, каждый раз новое.

                    Вот смотрю: одна фраза «Hello World» генерирует 39 строк на js svelte.dev/tutorial/basics

                    Или я чего-то не понял? Я без всяких претензий, просто интересно.
                      +1
                      Все то, что вы сэкономили, не подключая, например, vue, — вернется вам в виде сгенеренного кода. Просто в vue этот код УЖЕ включен, а тут он генерится на лету

                      Не так. Тот код, который сгенерировал компилятор Svelte, во Vue постоянно считается в runtime. Svelte, заранее знает все состояния и не будет тратить каждый раз время на рассчитывание каких-либо изменений. (No virtual DOM)

                      Тот код который включен в Vue это вещи, без которых он не сможет работать в runtime, в Svelte размер этого кода 1.4кб.

                      Тот факт, что svelte компилируемый, кстати, дает ему возможность, не писать тонны кода как в React с useCallback, useMemo, useEffect, которые потом превращаются в сложные Proxy и также влияют на производительность. Да и в принципе относительно других фреймворков, будет значительно меньше кода, из-за этого. (Write less code)
                        +1

                        Давайте посмотрим на факты:


                        Размер вашего бандла – 79 Кб. Размер реакта – 42 Кб, на код приложения остается 37 Кб. В этот объем можно вполне уместить требуемую функциональность, если не увлекаться mobx и redux, как мне кажется.


                        Так что, получается, что в вашем примере Svelte вам особой компактности и не принес

                          +1
                          Бандл весит столько, из-за библиотек/изображений от которых я не смог отказаться. Например, sentry.

                          Использовал бы я реакт, было бы все то же самое, только еще:
                          1. 42 Кб сходу
                          2. Большое кол-во бойлерплейта в коде (+ меньше скорость разработки)

                          Без mobx/redux/effector также уменьшится скорость разработки.

                      +1
                      Неплохое начало! Мы используем Preact для виджета, размер не большой, работает шустро, развитая эккоситсема, вообщем пока ни разу не пожалели.
                      Если планируете продвигать виджет на другие сайты, встретите много разных проблем, одни из главных изоляция вашего кода от кода сайта, сбор ошибок и борьба с Same-origin-policy и прочими секьюрными вещами.
                        0
                        Такие утверждения подрывают доверие ко всей статье.
                        Preact тут проигрывает, так как это React внутри

                        Это с каких пор Preact это React внутри?

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

                        Самое читаемое