asmoth.me
Как я писал свой Svelte
2020-03-14
Как я писал свой Svelte

Как я писал свой Svelte

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

Предыстория

В 2016 году я работал в компании разрабатывающей социальную сеть. Веб приложение у нас работало на AngularJS (не путать с Angular). Наступил этап когда уже нужно было разрабатывать мобильное приложение. Мы тогда все дружно сели и начали придумывать что можно сделать.

Было 2 варианта пути:
  1. Нанять Android и iOS разработчиков и сделать нативые приложения;
  2. Сэкономить и сделать на первое время прототипы гибридных приложений на Phonegap или Ionic.

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

Небольшая история почему у нас использовался AngularJS. Изначально я нанимался в эту компанию как верстальщик, хотя на тот момент опыта у меня было больше. Коллектив у нас был небольшой и неопытный. Начав верстать первые шаблоны в 2013ом году, я сразу подумал что дальше так не может продолжаться, мы не можем писать серьезный проект на jQuery (да, мне предложили начать писать на нем 🤦‍♂️). Слишком много кода нужно повторять, а это ведь не есть хороший подход. Здесь вспоминаются слова моего учителя математики, что мы (математики) должны быть ленивыми. И началось изучение что же можно использовать.

Мы решили протестировать несколько фреймворков своими силами и понять какой же будет лучше: AngularJS, Ember, Backbone, Knockout. Был еще CanJS, но он отпугнул меньшим комьюнити. Мы руководствовались следующими оценками: порог вхождения и скорость написания аналогичных фич. После исследований наш выбор и пал на AngularJS. Дальше мы ниразу не пожалели о выборе, кроме дня когда нужно было сделать гибридное мобильное приложение.

Версия #1

Вернемся снова к 2016ому, когда была написана часть интерфейсов мобильной версии на AngularJS, мы поняли что он очень медленно работает (медленно рендерит, много тяжелого кода выполняет), даже использование Angular Mobile не помогло особо. Волевым решением было принято написать свой мини-фреймворк для мобильных устройств с быстрым рендерингом.

Очень кстати вспомнилось видео которое я смотрел на днях.

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

Нехватало контроллеров, сервисов, двойного биндинга для инпутов, шины событий. Написали с ребятами пару плагинов для Webpack, первый плагин - рендеринг шаблонов а-ля JSX, но попроще, второй плагин - css-модули.

Что мы получили в итоге:
  • шаблонизатор с if, for, include на основе temple;
  • обработка кликов;
  • двойной биндинг для инпутов;
  • роутер изначально на основе page.js, а в дальнейшем самописный с History API;
  • эвент шина;
  • и конечно же компоненты, с html шаблонами, postcss sass стилями и контроллерами.

Завернули code splitting чанки с минимизациями и обфускациями и тут мы зажили. Все работало очень и очень быстро. Кода не так много и слабые мобильные устройства уже намного лучше справлялись с нашими требованиями.

Версия #2

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

Предстояло постепенно переписать несколько сервисов, сняв с бэкенда ответственность за “представление” информации. Не долго думая я выбрал этот движок, что в будущем сказалось в каких-то моментах положительно, а в каких-то отрицательно на будущей разработке.

Версия 1 была безымянная, а вот чуть позже вторую версия про себя я решил назвать Furnace, “кузница” страничек, хотя один из вариантов был SmeltJS, почти что Svelte.
Плюсы:
  • низкий порог вхождения за счет небольшого функционала;
  • те ребята что обучились на этом движке, в будущем стали добавлять в него нужный функциона, на этом движке обучилось как минимум 9 человек;
  • скорость разработки выросла.
Минусы:
  • обычный минус всех самописных движков, если автора движка нет на проекте, то проекту будет плохо;
  • обучаться этому движку не у кого;

Это не плюсы/минусы движка, а последствия выбора его как средства разработки.

По мере развития движка и его использования за первые два месяца мы переписали фронт одного из сервисов. Еще через месяц вышла первая версия приложения Edumark. Дальше больше, мы успели наклепать 3 внутренних сервиса, 6 пользовательских сервисов и 3 мобильных приложения (одно из них с аудиторией 100-200к пользователей).

Эпилог

В начале 2018го года мы решили перейти на Vue с Bootstrap в новых проектах для еще более быстрой разработки. Основательно подготовились, написали свой UI кит, прописали что и как должно использоваться и приступили к новым сервисам. Furnace же остался на старых проектах, там и так все работало стабильно. И до сих пор он живет, но уже не мейнтейнится. У него нет развития.

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

Напоследок пример кода

login.tpl

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
<div>
    <form novalidate>
        <div class="form-line">
            <div class="ui-label stick">
                <span>Name/Email</span>
            </div>
            <div class="ui-input stick">
                <input type="text" name="name">
            </div>
        </div>
        <div class="form-line">
            <div class="ui-label stick">
                <span>Password</span>
            </div>
            <div class="ui-input stick">
                <input type="password" name="password">
            </div>
            <span class="ui-error-label">
                {{errors}}
            </span>
        </div>
        <div class="form-line buttons">
            <button type="button" class="stick" f-click="$go('/')"><span>Back</span></button>
            <button type="submit" class="blue stick" f-click="login()"><span>Submit</span></button>
        </div>
    </form>
</div>

login.js

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
import './login.scss';
import template from './login.tpl';

import {viewer, err} from 'core';

export default scope => {
    scope.login = () => { // вызов при клике по кнопке войти
        viewer.login(scope.user).then(() => {
            scope.$go('/user'); // переход на другую страницу
        }, response => {
            scope.errors = err(response.error); // обработка и вывод ошибок
            scope.$update(); // обновление страницы
        });
    };
    scope.user = {
        name: '',
        password: ''
    };
    scope.$on('$rendered', () => { // хук при первом рендере страницы биндим поля
        scope.$binding('user.name', 'input[name="name"]');
        scope.$binding('user.password', 'input[name="password"]');
    });
};

export {template};