Vaadin Flow — диковинный олень

    Всякая перемена, даже перемена к лучшему,
    всегда сопряжена с неудобствами

    Ричард Хукер

    Как вы возможно знаете, Vaadin — один из самых популярных web-фреймворков на Java:


    Совсем недавно вышел новый релиз этого фреймворка для разработки web UI — Vaadin 10. Про Vaadin 10 и Vaadin Flow пока довольно мало публикаций на русском, и этот пост призван восполнить этот пробел.


    Создатели позиционируют Vaadin Flow как новый Java web-фреймворк для разработки современных web-приложений и web-сайтов (вот тут я им не совсем верю). Это часть Vaadin Platform, которая приходит на замену другому продукту — Vaadin Framework, она позволяет разрабатывать web-приложения (а если быть точным, то web UI) с применением стандарта Web Components на Java.

    Тут у читателя в голове скорее всего всё уже смешалось, все эти Vaadin Bla Bla, фреймворк, платформа и прочее. Что происходит?

    Мы используем Vaadin в составе своей платформы CUBA для UI back-office систем на протяжении 7 лет и за это время накопили большой опыт работы с ним, поэтому нас не может не волновать его судьба. Под катом вы найдёте мои спекуляции на тему Vaadin 10.

    Vaadin Framework


    Vaadin — это финская компания, которая разрабатывает инструменты и библиотеки для разработки UI. Они же делают одноимённый фреймворк для web-разработки на Java.

    Vaadin Framework — это UI фреймворк с server-side моделью программирования, в которой вся логика UI и его состояние расположены на сервере, а в браузере исполняется только код UI компонентов. По сути, это технология тонкого клиента, где браузер всего лишь отображает то, что скажет сервер, а все события отправляются на сервер.

    Server-side подход позволяет забыть про то, что разработка ведется под web, и разрабатывать UI как настольное Java-приложение с непосредственным доступом к данным и сервисам на сервере. При этом Vaadin позаботится и о отображении UI в браузере, и об AJAX-взаимодействии между браузером и сервером. Движок Vaadin осуществляет рендеринг пользовательского интерфейса приложения серверной стороны в браузере и реализует все детали обмена клиента и сервера.



    У этого подхода есть много плюсов:

    • Java код проще писать и отлаживать
    • Можно использовать существующие Java библиотеки и инструменты (IDE, компиляторы, тестирование)
    • Не требуется разрабатывать веб-сервисы
    • Лучше обстоят дела с безопасностью

    И минусов:

    • Нужно много памяти на сервере для UI представления
    • Сложнее масштабировать решение
    • При разработке виджетов требуется разрабатывать Java API

    Исходя из этих минусов и плюсов Vaadin FW плотно поселился именно в enterprise разработке, где нагрузки предсказуемы, а скорость и простота разработки гораздо важнее стоимости железа и памяти.

    Что случилось с Google Web Toolkit


    Всё то время, что Vaadin знаком широкой публике, клиентская часть Vaadin FW была неразрывно связана с другим известным продуктом — Google Web Toolkit (GWT). Этот тандем позволял писать сами UI компоненты и серверный API для них на одном языке — Java, что было довольно удобно.

    Последние годы Google Web Toolkit не развивался, и мы с 2015 года всё ждём появления GWT 3.0 / J2CL, анонсированного на GWT.Create 2015:


    В этот застойный период (2015-2017) случилось важное событие: появилась спецификация Web Components и другой фреймворк от Google — Polymer. Видимо, это и послужило началом конца GWT.

    Стоит отметить, что GWT 3 разрабатывается как внутренний фреймворк Google и его разработка ведется внутри компании. А значит, коммьюнити никак не может влиять на процесс или хотя бы видеть, что процесс идёт.

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

    Web Components


    Web Components — это набор стандартов. Его предложили и активно продвигают ребята из Google, но инициативу уже поддержали в Mozilla. По сути, это технологии для создания UI компонентов для web, так, чтобы в них поддерживалась инкапсуляция поведения и представления. А главный плюс — возможность повторного использования.

    Основные концепции:

    • Custom Elements — API для создания своих HTML элементов
    • Shadow DOM — инструмент инкапсуляции HTML компонентов и изоляция их визуального представления от глобальных правил CSS. Если коротко, то вы можете сделать компонент, например, форму заказа, и не бояться, что её стили сломаются на какой-то из страниц сайта из-за CSS правил этой страницы.
    • HTML Templates — возможность размещения в HTML документе пассивных блоков, содержащих DOM элементы-заготовки. Такие блоки парсятся браузером, но не отрисовываются и не исполняют свой код. Их предлагается использовать в качестве шаблонов для рендеринга данных.
    • HTML Imports — возможность импортировать HTML документ как модуль со всей его версткой, стилями и JS

    Например, если сейчас заглянуть в DOM дерево YouTube, то вы обнаружите использование Custom Elements и Shadow DOM:



    Все эти штуки и позволяют писать новые модные UI компоненты для web.

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

    Polymer


    Polymer — это небольшая библиотека поверх стандартов Web Components, призванная упростить их использование. Пример:

    // Импортируем существующие компоненты
    import '@polymer/paper-checkbox/paper-checkbox.js';
    import {PolymerElement, html} from '@polymer/polymer';
    
    // Определяем новый класс
    class LikeableElement extends PolymerElement {
    
      // Здесь будут публичные свойства компонента
      static get properties() { return { liked: Boolean }}
    
      // Так будет выглядеть DOM дерево внутри, CSS влияет только на сам компонент
      static get template() {
        return html`
          <style>
            .response { margin-top: 10px; } 
          </style>
          <paper-checkbox checked="{{liked}}">I like web components.</paper-checkbox>
    
          <div hidden$="[[!liked]]" class="response">Web components like you, too.</div>
        `;
      }
    }
    // Регистрируем элемент в браузере
    customElements.define('likeable-element', LikeableElement);
    

    По сути, Polymer делает всё то, что раньше делал GWT, но при этом он совместим с любыми JS компонентами и другими фреймворками, например, React и Angular.

    Vaadin Components


    Вернёмся к Vaadin. Довольно давно компания Vaadin делает продукт под названием Vaadin Components — UI компоненты для фронтенд разработчиков, которые могут встраиваться в любые JS приложения.



    Эти компоненты базируются на Web Components и Polymer!

    Как мы теперь видим, это был запасной аэродром для Vaadin Framework, позволивший уйти от Google Web Toolkit и разработать новый фреймворк, для которого еще не существовало компонентов. Проблема курицы и яйца решена и Vaadin Components стали фронтендом грядущего Vaadin 10.

    Vaadin Flow


    Vaadin 8 включал в себя механизм синхронизации состояния UI и поддержку двустороннего RPC протокола (удаленного вызова процедур). Это было возможно благодаря GWT, поскольку общие интерфейсы и классы сервера и клиента писались на Java.

    Вместе с отказом от GWT потребовалось реализовать новый механизм, который бы позволил прозрачно интегрироваться с JS фронтендом и Java бэкендом. Этим механизмом стал Vaadin Flow (а ещё это имя долгое время использовали для обозначения всего Vaadin 10).

    В документации по Flow есть такая схема:



    Основной её смысл в следующем:

    • поддерживается синхронизация состояния UI с сервера на клиент
    • серверная часть может подписываться на события UI компонентов, при этом будет выполнен AJAX запрос
    • бизнес-логика выполняется на сервере, в веб-браузер загружаются только данные, отображающиеся в UI
    • серверная часть использует Java
    • клиентская часть может использовать HTML, CSS, JS и шаблоны Polymer

    Для меня это означает, что в Vaadin станет больше фронтенд технологий, а теперь одной Java явно недостаточно (для Vaadin 8 вам хватило бы Java и не требовались HTML/CSS). С другой стороны, теперь возможна легкая интеграция JS кода.

    Vaadin Platform


    Каждый компонент Vaadin 10 разрабатывается отдельно и в лучших традициях JS мира — крошечные модули, максимально независимые друг от друга. При этом клиентская часть компонентов упакована в JAR в формате WebJARs: www.webjars.org

    Это немного пугает, особенно если заглянуть в зависимости минимального проекта:



    Чтобы хоть как-то управлять этим хаосом появился проект BOM (Bill of Materials) под названием Vaadin Platform.

    Это не какой то самостоятельный продукт, а всего лишь список совместимых версий компонентов и инструментов оформленный в формате Maven BOM.

    Подключается в Maven он следующим образом:

    <dependencyManagement>
        <dependencies>
            <dependency>
                <groupId>com.vaadin</groupId>
                <artifactId>vaadin-bom</artifactId>
                <version>${vaadin.platform.version}</version>
                <type>pom</type>
                <scope>import</scope>
            </dependency>
        </dependencies>
    </dependencyManagement>
    

    Возможности Vaadin 10


    Итого, весь фреймворк состоит из 3х составляющих:

    1. Vaadin Components — фронтенд
    2. Vaadin Flow — транспорт
    3. Server Components API — Java API для UI компонентов

    Начинать его освоение стоит с официального туториала.

    Также, рекомендую свежий вебинар.

    Starters


    Более плотно познакомиться с фреймворком можно со страницы. Там вы найдёте примеры проектов, в том числе full-stack на базе Spring Boot.

    Ярые поклонники Spring Boot могут проследовать прямо в start.spring.io и выбрать там Vaadin среди web-фреймворков.

    Минимальный проект можно начать с одного Java класса, например:

    // определяем URL для страницы
    @Route("")
    public class MainView extends VerticalLayout {
    
        public MainView() {
            // конструируем UI из компонентов
            Button button = new Button("Click me");
            // подписываемся на события
            button.addClickListener(event -> {
                new Notification("Hello!").open();
            });
    
            add(button);
        }
    }
    

    В общем и целом, можно писать на Vaadin 10, как на Vaadin 8, НО! Нужно обязательно заглянуть на страницу соответствия компонентов.

    Element API


    Киллер фича Vaadin 10 — управление элементами DOM прямо из серверного Java кода.

    Element nameField = ElementFactory.createInput();
    nameField.setAttribute("id", "nameField");
    nameField.setAttribute("placeholder", "John Doe");
    nameField.setAttribute("autofocus", "");
    

    Также можно управлять атрибутами, которые уже проставлены:

    // "John Doe"
    String placeholder = nameField.getAttribute("placeholder");
    // true
    nameField.hasAttribute("autofocus");
    nameField.removeAttribute("autofocus");
    // ["id", "placeholder"]
    nameField.getAttributeNames().toArray();
    

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

    Data binding


    Для работы с компонентами, реализующими интерфейс HasValue (get/set value и ValueChangeListener) есть удобный класс Binder:

    Binder<Person> binder = new Binder<>();
    TextField titleField = new TextField();
    
    binder.forField(titleField)
      .bind(
        Person::getTitle,
        Person::setTitle);
    

    Как можно видеть из примера, поддерживается статически типизированный биндинг на базе лямбда-выражений.

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

    binder.forField(yearOfBirthField)
      // Validator will be run with the String value of the field
      .withValidator(text -> text.length() == 4,
        "Doesn't look like a year")
      // Converter will only be run for strings with 4 characters
      .withConverter(
        new StringToIntegerConverter("Must enter a number"))
      // Validator will be run with the converted value
      .withValidator(year -> year >= 1900 && year < 2000,
        "Person must be born in the 20th century")
      .bind(Person::getYearOfBirth, Person::setYearOfBirth);
    

    Templates


    HTML шаблоны представляют собой вёрстку вида:

    <link rel="import" href="../bower_components/polymer/polymer-element.html">
    <link rel="import" href="../bower_components/paper-input/paper-input.html">
    
    <dom-module id="hello-world">
        <template>
            <div>
                <paper-input id="inputId" value="{{userInput}}"></paper-input>
            <button id="helloButton" on-click="sayHello">Say hello</button>
            <div id="greeting">[[greeting]]</div>
        </div>
        </template>
        <script>
            class HelloWorld extends Polymer.Element {
                    static get is() {
                        return 'hello-world'
                    }
            }
            customElements.define(HelloWorld.is, HelloWorld);
        </script>
    </dom-module>
    

    В шаблонах поддерживается декларативный биндинг данных и можно писать нативный JavaScript, который будет исполняться в браузере as-is. Это позволяет реализовывать часть простейшей UI логики без отправки запросов на сервер.

    Events


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

    TextField textField = new TextField();
    textField.addChangeListener(e -> System.out.println("Event fired"));
    

    Здесь вы не заметите разницы с Vaadin 8.

    Routing


    Навигация и роутинг в приложении стали такими какими должны быть:

    @Route("some/path")
    public class SomePathComponent extends Div {
      public SomePathComponent() {
        setText("Hello @Route!");
      }
    }
    

    Представления могут определять какой URL они обрабатывают, какие параметры им требуются из адреса и многое другое.

    Разработка компонентов


    Для Vaadin 10 можно разрабатывать компоненты следующими способами:


    Такой прямолинейный подход в разработке custom-компонентов, пожалуй, самый большой шаг вперёд. Больше не требуется писать обёртки для JS на GWT, чтобы затем писать серверную часть на Vaadin.

    Lumo Theme


    Вместо SASS для визуальных тем теперь используются CSS Variables, т.е. больше не требуется компилировать CSS при сборке проекта:

    <custom-style>
        <style>
            html {
              --lumo-font-family: "Open Sans", sans-serif;
            }
        </style>
    </custom-style>
    

    А на смену теме Valo приходит новая настраиваемая тема Lumo.



    Миграция с Vaadin FW 8


    Опции миграции с Vaadin 8 описаны в документе: vaadin.com/docs/v10/flow/migration/1-migrating-v8-v10.html

    Тут у меня для вас плохая новость: если вы написали огромный проект на Vaadin 8, то вам потребуется его полностью переписать при переходе на Vaadin 10. Пути миграции нет, от слова совсем!

    Vaadin 10 и Vaadin 8 похожи в нескольких аспектах:

    • Server-side подход
    • Java для разработки логики UI
    • Одинаковый подход к биндингу данных

    В сухом остатке: Vaadin 10 это новый фреймворк написанный с нуля.

    Как обещают разработчики, Vaadin 8 будет поддерживаться до 2022 года, возможно появятся подходы к миграции.

    Заключение


    Считаю важным тот факт, что новый веб-сайт компании Vaadin написан на Vaadin Flow, что становится де-факто стандартом для фронтенд технологий, как в своё время зрелость языка программирования определялась тем, написан ли его компилятор на этом же языке.

    Надеюсь, что теперь и вы сможете составить свое мнение о Vaadin 10. В целом, это неплохой фреймворк и огромный задел на будущее. Для меня же — это отличный экспериментальный полигон для новых идей и подходов к построению UI.
    • +19
    • 4,5k
    • 8

    Haulmont

    236,00

    Разработка корпоративного ПО

    Поделиться публикацией

    Похожие публикации

    Комментарии 8
      +1
      Как-то писал пару страниц на этом фреймворке. Идея хорошая. Правда без конструктора форм довольно трудно ориентироваться в коде.
        0
        Конструктор у них есть, правда платный. В своих демо-проектах я сейчас использую Vaadin Kotlin DSL www.vaadinonkotlin.eu
        @AutoView
        class CreateArticleView: VerticalLayout(), View {
            private val binder = beanValidationBinder<Article>()
            init {
                label("New Article") {
                    styleName = ValoTheme.LABEL_H1
                }
                textField("Title") {
                    bind(binder).bind(Article::title)
                }
                textArea("Text") {
                    bind(binder).bind(Article::text)
                }
                button("Save Article") {
                    onLeftClick {
                        val article = Article()
                        if (binder.writeBeanIfValid(article)) {
                            article.save()
                        }
                    }
                }
            }
        }
        
        0

        Проблема в том, что не успев как следует выпустить Vaadin 8 они уже выпускают Vaadin 10. Большинство аддонов не успело мигрировать даже под Vaadin 8, и вероятно, никогда уже не мигрирует под Vaadin 10. Для десятки там фактически пустой репозиторий. А количество компонентов в самом Vaadin более чем ограничено. Даже простого confirmation dialog нет.
        И такое впечатление, что возможностей от версии к версии становится меньше. Например, в восьмерке в Grid-е исчез метод editRow(), который нужен был, чтобы добавить пустую запись и редактировать ее inline. Теперь нужно дополнительно открывать форму.

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

          А в Vaadin 8 в Grid теперь это делается так:
          grid.getEditor().editRow(2);
          
            0

            А, прикрутили-таки, вижу: https://github.com/vaadin/framework/issues/8477
            Еще одна неприятная вещь у восьмерки — stateless tabs. Когда переключаешься между табами, state текущей вкладки заново запрашивается с сервера. Когда у тебя в каждом табе редактор текста на сотню килобайт, переключаться становится накладно.

              0
              Да, есть такое. Мы поэтому себе разработали свой компонент, который контент табы прячет через CSS, а от Vaadin использует только сами корешки вкладок.
            0

            Поддерживаю. Есть ряд важных проблем в 8-ой версии, которые не решены и не понятно уже будет ли решение. Например, важнейший компонент Grid нельзя прокрутить до нужной строки, если данные подгружаются "лениво". После редактирования записи пользователь не видит, какая строка только что им редактировалась.
            https://github.com/vaadin/framework/issues/9266
            Разработчик Vaadin пометил этот запрос как "Расширение"(!) и прогресса не видно.
            Думаю проблема в том, что основные контрибьюторы проекта штатные сотрудники Vaadin Inc., которые очень лихо бегут вперед и программисты из сообщества не успевают разобраться и починить то, что хотят.

            0
            Фреймворк неплохой. Года полтора назад как раз выбирал фреймворки. Начал писать тестик на 8ой версии.Потом наткнулся на то что таблицы в попап-окнах иногда кривовато выводились и забросил.
            >у меня для вас плохая новость
            Как вижу, правильно сделал. А то тут еще и такие серьезные изменения.

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

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