Статьи

Закрытие на Гобелене 5.4

Мы приближаемся к бета-версии Tapestry 5.4. Последние пару недель я потратил на преобразование очень большого приложения существующего клиента (более 120 страниц, тонны компонентов, много JavaScript-кода на стороне клиента) из 5.3 в текущую альфа-версию 5.4, и это была большая работа … но также много наград.

До переключения приложение уже использовало  jQueryBootstrap и ограниченное количество  Backbone ; под Tapestry 5.3 это означает, что  Prototype  и  Scriptaculous  также были в соединении … и было довольно много конфликтов между Prototype и jQuery.

Дело не только в том, что Prototype и jQuery хотят использовать в  window.$ качестве точки входа; конфликты могут быть более глубокими и тонкими. Например, у меня было неприятное время с модальным диалоговым окном Boostrap, которое не отображалось корректно. После  долгих  отладок я обнаружил, что jQuery рассматривает метод элемента как обработчик события с соответствующим именем; Bootstrap вызывал  hide событие, а jQuery вызывал  hide() метод Element, добавленный Prototype. Такого рода вещи были моей жизнью под смешанным стеком.

Гобелен 5.4 справляется с этим лучше; а с новым  уровнем абстракции  можно полностью отключить Prototype и использовать только jQuery. Это устраняет эти конфликты … и также ускоряет процесс, но уменьшает количество кода JavaScript, загружаемого на клиент.

Переход с 5.3 на 5.4 стал возможностью пересмотреть и улучшить весь этот код. Вот несколько замечаний.

Приложение имеет несколько очень сложных клиентских форм; далеко за пределами возможностей Tapestry управлять с помощью компонентов FormInjector и FormFragment. Вместо этого мы используем Backbone — это своего рода гибридный режим, в котором модель или коллекция Backbone сохраняется в скрытом поле, так что собранные или отредактированные данные передаются на сервер как часть общей отправки формы.

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

В соответствии с 5.3, это требует изучений и часто взлом (или обезьяна латание) на сторону клиента код Гобелена, которые создают  FormEventManager и FieldEventManager объекты для каждой формы или элемента формы … и там было много повозки , запряженных волов к крану в цикл представления формы для выполнения валидация.

В 5.4 намного проще, когда при создании новых полей мы можем указать желаемые проверки с помощью атрибутов:

EditAddressView = BaseCountryRegionCityView.extend
 
      template: """
                <div>
                  <div class="control-group">
                    <label class="control-label">
                      <span data-insert="prefix"/>
                      <span data-insert="recipient-name"/>:
                    </label>
                    <div class="controls">
                      <input class="input-xlarge" data-bind="name"/>
                    </div>
                  </div>
 
                  <div class="control-group">
                    <label class="control-label">
                      <span data-insert="prefix"/>
                      Address
                      <span data-insert="suffix"/>:
                    </label>
                    <div class="controls">
                      <input class="input-xlarge" data-bind="street1" data-validation="true" data-optionality="required"
                        data-required-message="You must provide a street address."/>
                    </div>
                  </div>

data-validation Атрибут указывает , полевые участвует в проверке; у него будут события, инициированные на нем, когда отправляющая форма будет отправлена. t5/core/validation Модуль предоставляет код , который обрабатывает поля с  data-optionality="required" и гарантирует , что значение при условии, отображая  , data-required-message если поле остается пустым.

Это шаблон на протяжении 5.4; data- атрибуты используются, чтобы определить, где требуется специальное поведение, а хорошо документированная система событий используется для обработки поведения.

Очень мало со стороны сервера изменилось с обновлением до 5.4; но пересмотреть и переписать все это JavaScript было более чем достаточно работы!

Кроме того, появилась возможность конвертировать весь код в  CoffeeScript . CoffeeScript — мой предпочтительный способ написания кода на стороне клиента: он более лаконичен и удобен для чтения, чем JavaScript, но скомпилированный вывод все еще вполне читабелен. Он также имеет отличные функции, такие как блочные строки (из приведенного выше примера кода), что в значительной степени устраняет необходимость в отдельном шаблонизаторе.

Так много работы с CoffeeScript и Tapestry привело к некоторому быстрому развитию поддержки CoffeeScript, встроенной в Tapestry (в дополнительном модуле tapestry-wro4j). Первоначально любое изменение в любом файле CoffeeScript заставляло   перекомпилировать все файлы CoffeeScript; при использовании медленного движка Rhino JavaScript для запуска компилятора CoffeeScript мы могли видеть 10-20 секунд  на исходный файл !

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

Я также начал использовать  Less  вместо CSS. Меньше — это метаязык, который компилируется до CSS, очень похожий на отношения между CoffeeScript и JavaScript … но я думаю, что еще более резко. Компиляция довольно быстрая, основанная на   библиотеке Less4J .

Я обнаружил, что встроенная поддержка Less4J, поставляемая WRO4J, была недостаточной: с ней не получалось отлично работать  @import; изменение импортированного исходного файла не привело к перекомпиляции. Я обратился к этому с помощью специальной (для Tapestry) оболочки, которая правильно отслеживает зависимости.

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

Я думаю, что Tapestry стареет, если не грациозно, то, по крайней мере, комфортно, в растущем веке, когда насыщенные одностраничные приложения, созданные с использованием Backbone,  AngularJS или чего-то еще, являются нормой, а не исключением. Я первый, кто признает, что Tapestry был разработан для более простого времени, когда Ajax готовил приправу, а не мясо и картофель приложения. Там много багажа, особенно связанного с формами и элементами управления. И все же, несмотря на это, в Tapestry есть несколько удивительно полезных частей, которые одинаково хорошо подходят для современных приложений:


Актив Трубопровод

Конвейер ресурсов Tapestry выполняет большую часть работы, обычно связанной с этапом сборки из командной строки, но делает это во время выполнения, с преимуществом использования для разработки. Tapestry может не только компилировать файлы из одного типа в другой (например, CoffeeScript в JavaScript), но также может объединять множество небольших файлов в один объединенный файл и передавать его через минимизатор. Кроме того, Tapestry создает URL-адреса, содержащие контрольную сумму контента. Эта контрольная сумма означает, что мы можем заставить браузер агрессивно кэшировать файл (используя и электронные теги, и заголовок с истекшим сроком на будущее), так как любое изменение в файле также изменит контрольную сумму, в результате чего клиент будет выглядеть как полностью новый ресурс. Кроме того, Tapestry кэширует как обычный файл, так и сжатую GZip версию файла. Все это означает, что Гобелен обеспечивает не просто отличный 
пропускная способность за  счет быстрой обработки запросов, а также высокая 
производительность за  счет сокращения количества запросов от клиентов.

Поддержка определения асинхронного модуля (AMD)

Tapestry 5.4 представляет прямую поддержку AMD через 
RequireJS . Как минимум, это означает, что JavaScript может загружаться параллельно … но реальное преимущество заключается в том, что AMD побуждает вас организовывать код управляемым образом. Кроме того, Tapestry гарантирует, что ваши модули могут быть JavaScript или CoffeeScript, и предоставляет на сервере простой способ переопределения любых встроенных модулей, предоставляемых Tapestry, в случае необходимости. Еще лучше, у Tapestry есть серверный API для вызова клиентских функций, экспортируемых модулями AMD; это очень чистый и очень полезный способ связать логику на стороне сервера и на стороне клиента.

Превосходная обратная связь и отчеты об исключениях

При работе с другими стеками я больше всего скучаю по отчетам об исключениях из Tapestry.
Это полностью интегрировано в Tapestry, где сбой на стороне сервера приведет к подробному HTML-отчету о клиенте. Для запросов Ajax этот отчет представлен в плавающей форме 
<iframe>. Обилие информации, доступной со стороны сервера и передаваемой непосредственно клиенту, значительно упрощает разработку сложных приложений с вовлечением взаимодействия на стороне сервера.

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