Пишем компонент с «материальными» кнопками для svelte

Быстрое введение в Svelte с точки зрения разработчика на Angular

Перевод


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

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

Observables

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

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

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

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

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

Люминесцентные лампы. Широкая область применения

Эти практичные и относительно недорогие газоразрядные осветительные приборы нашли применение в разных отраслях промышленности. Так, это популярный экономичный вариант для освещения образовательно-воспитательных, лечебных, спортивных учреждений, офисов, магазинов, спортивных центров и так далее. Особенно актуально их использование в помещениях, имеющих большую площадь, что значительно экономит электроэнергию. Люминесцентные лампы меньшей мощности активно применяют для освещения рабочих мест, то есть для так называемого точечного зонового освещения.

Если сравнить показатели световой отдачи, то модель с мощностью 20 ватт по своим характеристикам будет такой же, как и лампа накаливания, имеющая мощность 100 ватт, то есть показатели будут лучше в 5 раз. Производители гарантируют, что минимальный срок службы составляет 2000 часов, в некоторых моделях он доходит до 20000 часов, в то время как обычные лампы накаливания работают не более 1000 часов (однако помните, что многое зависит от соблюдения условий эксплуатации и регуляции числа включений).

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

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

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

Статья будет полезна тем, кто так-же как и Мы решил попробовать Svelte в живом проекте. В нашу небольшую компанию пришёл заказ на разработку веб-админки для сервиса с бекэндом на Mongodb Stitch. В последние пару лет frontend Мы пишем на React или Vue (в зависимости от размера проекта и нужен ли ReactNative), но наслышав о красотах Svelte мы решили попробовать его, чтобы понять для себя так ли он хорош. И может нам тоже стоит дальше использовать его вместо Vue или React?..

Если в двух словах — это новый js фреймворк (но он таким себя не считает), который убийца React и Vue, и бла, бла, бла… В своей статье я хочу рассмотреть Svelte не какой он классный «под капотом», а с точки зрения удобства его использования в реальном проекте. Мы не делаем машины, мы на них ездим и у нас есть злые заказчики с еще не менее злыми сроками.

Начнём с азов

Вы будете использовать командную строку, также известную как терминал. В Windows вы можете открыть терминал запустив приложение Командная строка из меню Пуск. В MacOS нажмите вместе на клавиатуре клавиши и для запуска Spotlight и введите в строку поиска . На большинстве Linux дистрибутивах достаточно нажать вместе для открытия терминала.

Командная строка позволяет взаимодействовать с вашим компьютером(или удалённым компьютером, но об этом в другой раз) с гораздо большими возможностями и контролем, чем предоставляет GUI(графический интерфейс пользователя), который ежедневно используют большинство людей.

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

чтобы войти в нее. Тут вы можете директорию для нового проекта командой :

Знакомство с обширным списком всех доступных команд в терминале выходит за рамки этого руководства, но запомните еще несколько полезных команд:

  • — перемещает в родителькую директорию
  • — в Mac/Linux ( на Windows), отображает содержимое файла
  • (или в Windows) — открывает текущую папку в Finder или Проводнике

Exporting

Many sites are effectively static, which is to say they don’t actually need an Express server backing them. Instead, they can be hosted and served as static files, which allows them to be deployed to more hosting environments (such as Netlify or GitHub Pages). Static sites are generally cheaper to operate and have better performance characteristics.

Sapper allows you to export a static site with a single zero-config command. In fact, you’re looking at an exported site right now!

Static doesn’t mean non-interactive — your Svelte components work exactly as they do normally, and you still get all the benefits of client-side routing and prefetching.

sapper export

Inside your Sapper project, try this:

This will create a folder with a production-ready build of your site. You can launch it like so:

Navigate to localhost:5000 (or whatever port picked), and verify that your site works as expected.

You can also add a script to your package.json…

…allowing you to your app.

How it works

When you run , Sapper first builds a production version of your app, as though you had run , and copies the contents of your folder to the destination. It then starts the server, and navigates to the root of your app. From there, it follows any elements it finds, and captures any data served by the app.

Because of this, any pages you want to be included in the exported site must either be reachable by elements or added to the option of the command.

The option expects a string of space-separated values. Examples:


Setting overwrites any defaults. If you wish to add export entrypoints in addition to then make sure to add as well or will not visit the index route.

When not to export

The basic rule is this: for an app to be exportable, any two users hitting the same page of your app must get the same content from the server. In other words, any app that involves user sessions or authentication is not a candidate for .

Note that you can still export apps with dynamic routes, like our example from earlier. will intercept requests made inside , so the data served from will also be captured.

Route conflicts

Because writes to the filesystem, it isn’t possible to have two server routes that would cause a directory and a file to have the same name. For example, and would try to create and , which is impossible.

The solution is to rename one of the routes to avoid conflict — for example, . (Note that you would also need to update any code that fetches data from to reference instead.)

Пришло ли время забыть о React и перейти на Svelte?

Перевод

Каждый год выходит исследование State of JavaScript, которое обобщает результаты опроса, изучающего текущее состояние экосистемы JavaScript. Это исследование затрагивает фронтенд-фреймворки, серверную и мобильную разработку, тестирование, популярные ресурсы для разработчиков и многое другое. В нём всё, конечно, крутится вокруг JavaScript

Поэтому если вы используете для веб-разработки JS — я очень рекомендую взглянуть на State of JavaScript в том случае, если вы ещё этого не сделали. Для меня одним из самых интересных результатов State of JavaScript стало неожиданное внимание тех, кто участвовал в опросе, к фронтенд-фреймворку Svelte. В общем рейтинге ведущих фронтенд-инструментов (основанном на показателях осведомлённости о фреймворке, интереса к нему и удовлетворённости им) Svelte появился на второй позиции. Он идёт там сразу после React, опережая такие хорошо известные инструменты, как Vue.js, Preact, Angular и Ember. Меня это слегка шокировало, так как Svelte — это сравнительно новый инструмент — как в плане возраста, так и в плане парадигмы разработки программного обеспечения.Рейтинг фронтенд-фреймворков по результатам исследования State of JavaScript

Building

Up until now we’ve been using to build our application and run a development server. But when it comes to production, we want to create a self-contained optimized build.

sapper build

This command packages up your application into the directory. (You can change this to a custom directory, as well as controlling various other options — do for more information.)

The output is a Node app that you can run from the project root:

Browser support

Your site is built only for the latest versions of modern evergreen browsers by default. If you are using Rollup, you can use the 1 flag to build a second bundle that can be used to support legacy browsers like Internet Explorer. Sapper will then serve up the correct bundle at runtime2.

When using , Sapper will pass an environment variable to your Rollup config. Sapper will then build your client-side bundle twice: once with set to and once with it set to . sapper-template-rollup provides an example of utilizing this configuration.3

You may wish to add this flag to a script in your :

Layouts

So far, we’ve treated pages as entirely standalone components — upon navigation, the existing component will be destroyed, and a new one will take its place.

But in many apps, there are elements that should be visible on every page, such as top-level navigation or a footer. Instead of repeating them in every page, we can use layout components.

To create a layout component that applies to every page, make a file called . The default layout component (the one that Sapper uses if you don’t bring your own) looks like this…

…but we can add whatever markup, styles and behaviour we want. For example, let’s add a nav bar:

If we create pages for , and …

…the nav will always be visible, and clicking between the three pages will only result in the being replaced.

Nested routes

Suppose we don’t just have a single page, but instead have nested pages like and with a shared submenu (for a real-life example, see github.com/settings).

We can create a layout that only applies to pages below (while inheriting the root layout with the top-level nav):

Layout components receive a property which is useful for things like styling:

Still to come

As grueling as this release has been, we’re nowhere near finished. We have a ton of ideas for generating smarter, more compact code, and a long feature wish-list. Sapper, our Next.js-style app framework, is still in the middle of being updated to use Svelte 3. The Svelte Native community project, which allows you to write Android and iOS apps in Svelte, is making solid progress but deserves more complete support from core. We don’t yet have the bounty of editor extensions, syntax highlighters, component kits, devtools and so on that other frameworks have, and we should fix that. We really want to add first-class TypeScript support.

But in the meantime we think Svelte 3 is the best way to build web apps yet. Take an hour to go through the tutorial and we hope to convince you of the same. Either way, we’d love to see you in our Discord chatroom and on GitHub — everyone is welcome, especially you.

Игровой цикл

У нас есть базовый каркас игры. Следующий шаг — создать игровой цикл, который будет обрабатывать нашу логику. Создадим хранилища, где будут содержаться переменные для нашей логики. Нам понадобится компонент writable из модуля svelte/store. . Создание простого хранилища выглядит так:

Создадим папку src/stores/, здесь будут храниться все изменяемые значения нашей игры. Создадим файл src/stores/game.js, в котором будут храниться переменные, отвечающие за общее состояние игры.

Создадим файл src/stores/cannon.js, в котором будут храниться переменные, отвечающие за состояние пушки

Svelte позволяет создавать пользовательские хранилища, включающие логику работы. Подробнее об этом можно почитать в учебнике. У меня не получилось красиво вписать это в концепцию игрового цикла, поэтому в хранилище мы только объявляем переменные. Все манипуляции с ними мы будем производить в разделе src/gameLoop.

Игровой цикл будет планироваться с помощью функции requestAnimationFrame. На вход будет подаваться массив из функций, описывающий логику игры. По завершении игрового цикла, если игра еще не закончена, планируется следующая итерация. В игровом цикле мы будет обращаться к значению переменной isPlaying, чтобы проверить, не закончилась ли игра.

Используя хранилище можно создавать подписку на значение. Этот функционал мы будем использовать в компонентах. Пока для чтения значения переменной будем использовать функцию get. Для установки значения будем использовать метод .set() переменной. Обновить значение можно вызвав метод .update(), который на вход принимает функцию, в первый аргумент которого передается текущее значение. . Все остальное — чистый JS.

Теперь опишем логику поведения нашей пушки.

Теперь добавим наш обработчик поворота пушки в игровой цикл.

Текущий код игрового цикла:


У нас есть логика, которая умеет поворачивать пушку. Но мы еще не связали ее с нажатием кнопок. Самое время сделать это. Обработчики событий нажатий будем добавлять в src/components/Controls.svelte.

Добавим наши обработчики и текущее состояние нажатия в элементы IconButton. Для этого просто передадим значения в ранее созданные атрибуты start, release и active, как описано в .

Мы использовали выражение $ для переменной $direction. Этот синтаксис делает значение реактивным, автоматически создавая подписку на изменения. .

На данный момент при нажатии у нашей кнопки происходит выделение, но пушка еще не поворачивается. Нам необходимо импортировать значение angle в компонент Cannon.svelte и обновить правила трансформации transform

Осталось запустить наш игровой цикл в компоненте App.svelte.

Ура! Наша пушка начала двигаться.

Но сначала, React

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

Хм, а почему он тогда называется React?

Ещё одна оговорка: эта статья никоим образом не предназначена для критики React. Я решил использовать его в качестве примера, потому что большинство людей, которые читают эту статью, имели дело с React в тот или иной момент своей жизни. Просто сейчас это лучший пример для противопоставления Svelte.

Что же имел в виду Dan, и как это повлияло на то, как мы сейчас пишем код? Чтобы ответить на эти вопросы, позвольте мне упрощённо рассказать о том, как React работает под капотом.

Когда происходит отрисовка React-приложения, копия DOM помещается в структуру, называемую Virtual DOM. Этот виртуальный DOM выступает посредником между вашим React-кодом и тем, что браузер отображает в DOM.

Затем, при изменении данных (например, после вызова или ), React проделывает небольшую работу, чтобы определить, какие части приложения нужно перерисовать.

Он сравнивает виртуальный DOM с реальным, чтобы определить, что изменилось после обновления данных. Затем перерисовывает только те части DOM, которые имеют отличия в виртуальном DOM, устраняя необходимость каждый раз при любом изменении, перерисовывать весь DOM целиком.

Всё происходит очень быстро, потому что обновлять виртуальной DOM намного дешевле, чем реальный, и React обновляет только необходимые кусочки реального DOM. Эта статья намного лучше объясняет этот процесс.

Вероятно, вы заметили одну особенность. Если вы не сообщите React, что данные изменились (вызвав или эквивалентный хук), виртуальный DOM не изменится, и от React не последует никакой реакции (та-дам! ).

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

Элементы управления

Компонент Controls.svelte будет состоять из трех кнопок: движение влево, движение вправо, огонь. Иконки кнопок будут отображаться svg элементом. Создадим папку src/asssets, в которую добавим наши svg иконки.

Добавим компонент кнопки src/components/IconButton.svelte. Мы будем принимать обработчики событий из родительского компонента. Для того, чтобы можно было зажать кнопку, нам понадобятся два обработчика: начало нажатия и конец нажатия. Объявим переменные start и release, куда будем принимать обработчики событий начала и окончания нажатия. Еще нам понадобится переменная active, которая будет отображать, нажата кнопка или нет.

Стилизуем наш компонент

Кнопка представляет собой button элемент, внутри которого отображается контент, переданный из родительского компонента. Место, где будут монтироваться переданный контент обозначается тегом <slot/>. .

Обработчики событий обозначаются через директиву on:, например, on:click. Мы будем обрабатывать события мыши и тач нажатия. . К базовому классу компонента будет добавляться класс active, если кнопка нажата. Назначить класс можно свойством class.

В итоге наш компонент будет выглядеть следующим образом:

Теперь импортируем наши иконки и элемент кнопки в src/components/Controls.svelte и сверстаем расположение.

Наше приложение должно выглядеть так:

Что такое Svelte?

Svelte — это компонентный фреймворк, похожий на React или Vue, но с важным отличием. Традиционные фреймворки позволяют вам писать декларативный state-driven код, но не без наказаний: браузер должен выполнить дополнительную работу для преобразования этих декларативных структур в манипуляции с DOM, используя техники, такие как virtual DOM diffing, которые проедают имеющийся бюджет кадров отрисовки и добавляют обязанностей сборщику мусора.

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

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

Svelte 3 — это уже существенный пересмотр

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

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

Чтобы эта возможность стала реальностью, нам сначала нужно было переосмыслить концепцию, лежащую в основе современных UI фреймворков: реактивность.

‘Переосмысление реактивности’ на You Gotta Love Frontend Code Camp

Svelte, исчезающий фреймворк, что всё никак не исчезал


Из песочницы

Когда я вижу очередную статью о Svelte:

RE: Боль и слёзы в Svelte 3Svelte 3: Переосмысление реактивностиПочему SvelteJS возможно лучший фреймворк для новых веб-разработчиковЛегенда о Фреймворке ВсевластияRe: «Сравнение JS-фреймворков: React, Vue и Hyperapp»Исчезающие фреймворки

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

Паранойя, скажете вы и будете правы. Но мой психотерапевт занят поддержкой пострадавших от коронавируса. Им нужнее. Поэтому выговариваться мне придётся вам. А выговориться я бы хотел на тему того, что Svelte — натужно пиаримый кем-то мертворождённый фреймворк. Который в 2020 году является пустой тратой времени и не имеет никаких реальных конкурентных преимуществ по сравнению с другими фронтенд-фреймворками.

Выстрелы

Теперь научим нашу пушку стрелять. Нам нужно хранить значения:

  • Стреляет ли сейчас пушка (зажата кнопка огонь);
  • Временную метку последнего выстрела, нужно для расчета скорострельности;
  • Массив снарядов.

Добавим эти переменные в наше хранилище src/stores/cannon.js.

Обновим импорты и игровую логику в src/gameLoop/cannon.js.

Теперь импортируем наши обработчики в gameLoop.js и добавим их в игровой цикл.

Теперь нам осталось создать обработку нажатия кнопки огонь и добавить отображение снарядов на игровом поле. Отредактируем src/components/Controls.svelte.

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

Осталось отобразить снаряды на игровом поле. Сначала создадим компонент снаряда

Поскольку снаряды у нас хранятся в массиве, нам понадобится итератор для их отображения. В svelte для таких случаев есть директива Each. .

Теперь наша пушка умеет стрелять.

Link options

rel=prefetch

Sapper uses code splitting to break your app into small chunks (one per route), ensuring fast startup times.

For dynamic routes, such as our example, that’s not enough. In order to render the blog post, we need to fetch the data for it, and we can’t do that until we know what is. In the worst case, that could cause lag as the browser waits for the data to come back from the server.

We can mitigate that by prefetching the data. Adding a attribute to a link…

…will cause Sapper to run the page’s function as soon as the user hovers over the link (on a desktop) or touches it (on mobile), rather than waiting for the event to trigger navigation. Typically, this buys us an extra couple of hundred milliseconds, which is the difference between a user interface that feels laggy, and one that feels snappy.

rel=external

By default, the Sapper runtime intercepts clicks on elements and bypasses the normal browser navigation for relative (same-origin) URLs that match one of your page routes. We sometimes need to tell Sapper that certain links need to be be handled by normal browser navigation.

Adding a attribute to a link…

…will trigger a browser navigation when the link is clicked.

sapper:noscroll

When navigating to internal links, Sapper will change the scroll position to 0,0 so that the user is at the very top left of the page. When a hash is defined, it will scroll to the element with a matching ID.

In certain cases, you may wish to disable this behaviour. Adding a attribute to a link…

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

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

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

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

  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. — насколько интересна технология для разработчиков, и насколько они ей удовлетворены.
Preact Svelte
Размер в runtime (gzip + min) 3,8 Кб 1,4 Кб
Удовлетворены
Интересна

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

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

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

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


С этим читают