Pull to refresh

Comments 185

Уже было подумал крутизна, но одна мысль мешает: какая его интеграция с поисковыми ботами? В смысле, на сколько хорошо они смогут парсить страницы?
Это странный вопрос. Робот получает уже готовый html.
Вроде как эти шаблонизаторы работают на клиенте.
Нет, в статье сказано, что шаблонизация происходит на стороне пользователя. Поэтому робот скорее всего не сможет нормально проиндесировать контент.
Даже в примере с меилбоксом шаблон сперва компилится в js, и потом подключается в html — не понятно, где тут шаблонизация на клиенте…
Компилируется в js, который потом уже лепит шаблон по правилам, видимо так
Yate компилируется на сервере, а на клиент отправляются уже скомпилированные шаблоны, которые накладываются на JSON и дают HTML на выходе.

Ничего не мешает использовать компилированные шаблоны на сервере и отправлять на клиент сразу готовый HTML.

Компиляции на клиенте пока не предусмотрено, но так как компилятор тоже написан на JavaScript, то вполне возможно, что он будет портирован на клиент.
UFO just landed and posted this here
Шаблоны накладываются на данные на клиенте, но необходима предкомпиляция шаблонов в JS, которая делается на сервере.
UFO just landed and posted this here
Скомпилировать шаблон — это разовая операция, которую надо выполнить при подготовке кода для продакшена. Это как обфускация js и препроцессинг CSS из LESS, Stylus.
UFO just landed and posted this here
UFO just landed and posted this here
Шаблоны можно скомпилировать один раз.
UFO just landed and posted this here
А в какой ситуации могут понадобится динамические шаблоны? По-моему сама идея шаблонов подразумевает, что есть какая-то неизменная часть и места, куда надо подставлять изменяющиеся данные. Или я не понял, что вы имеете ввиду.
UFO just landed and posted this here
Вы не улавливаете сути. Есть некоторый шаблон на Yate, он преобразуется в «шаблон» на javascripte (на сервере), именно этот «шаблон» заполняется полученными данными из JSON (на клиенте). И это происходит динамически на клиенте (заполнение). И уже в зависимости от полученных данных (JSON), у вас сформируется нужной кол-во строчек в списке писем, ну или что вам там нужно будет.
Судя по файрбагу сейчас как раз сделали все на клиенте. Приходит джейсон, на основе которого строится клиентская часть. Сейчас приходит анонимная функция, которая сформирована на сервере(там по факту под имя шаблона сформированный js для формирования dom), и уже она формирует гуй. т.е. передав один раз шаблоны при старте клиента, потом только передают опции в функцию с шаблоном для отрисовки dom с этими новыми данными. все кэшируется, все быстро в принципе работает.
UFO just landed and posted this here
Шаблон компилируется на сервере, формируя Javascript код функции, которая позже на клиенте будет получать данные из джейсона и формировать dom модель для отображения.
UFO just landed and posted this here
Возможно я путанно выражаюсь. На сервере пишется шаблон на каком нть мета языке, он компилируется создав джаваскрипт и отдается на клиент. на клиенте уже данная функция запускается. В нее скорее всего передается имя шаблона, который надо сформировать и пришедшие от сервера опции (скажем список писем в джейсоне) а функция эта по шаблону формирует и возвращает dom, которую просто надо подставить на место.
Шаблон пишется на Yate, Yate компилируется в JS на сервере (1 раз), готовый скомпилированный JS отдаётся клиенту вместе с JSON данными (каждый раз по запросу, точнее JS отдаётся при загрузке страницы, JSON при обновлении списков), которые и визуализируются в HTML. Все же просто.
Зачем обязательно на сервере-то? Можно деплоить продакшен после преобразований Ant/Capistrano/Phing.
У меня например нет и не предвидится желания запускать что-то вроде node на большинстве клиентских серверов. А вот на рабочей машинке все имеется.
А зачем индексировать закрытые разделы, такие как почта?
Вы действительно думаете что вам скажут правду? :) Для вашего же блага, очевидно :)
Можно использоывать один и тот же язык шаблонов на стороне клиента и сервера (например mustache). При первичной заргузке рендерим на сервере, а дальше, получая данные AJAX запросами, на клиенте.
Не все роботы работают с js. Создание html происходит на стороне клиента из полученого сначала js файла и запрашиваемых json данных, готового (полностью) html нету
Да кто же вам мешает отдавать готовый HTML?
Почту то индексировать не нужно… поэтому и выгодно перебросить шаблонизацию на клиент.

Да и вообще можно отдавать для поисковых ботов сгенерированные HTML, а обычным юзерам JSON… И этого вам тоже никто не запретит… С таким решением конечно же есть проблемы, URI например, но это возможно!
> Да и вообще можно отдавать для поисковых ботов сгенерированные HTML, а обычным юзерам JSON

Не уверен в SEO-экологичности такого клоакинга.
Да, с этим проблема! Так как если роутинг делать на клиенте в адресной строке браузера будет хреновая(не валидная для ботов) ссылка.
Для решения этой проблемы есть History API. Например так сделано на GitHub. Попробуйте походить по дереву каких-нибудь исходников. Подгрузка идет через ajax, но адрес меняется как обычно.
На хабре как раз была статья как это реализовано у них.
Значит нет никаких проблем… Можно равняться на GitHub!
Статья про шаблонизатор. Какую связь вы уловили с поисковыми роботами?
Вероятнее всего, romy4 хотел бы заюзать этот шаблонизатор на сайте, который индексируют поисковики.
В контексте почтового ящика связи действительно никакой.

Но в других случаях связь прямая — если все данные подгружаются динамически или вываливаются в виде JS-объекта, то могут быть проблемы
Теперь понял. Это общая проблема сайтов, которые устроены как JS приложение.
Остаются только meta описания.

Yate можно использовать на сервере, а не на клиенте.
Ну почему. Можно при запросе страницы заполнять темплейт первичными данными и отдавать клиенту готовый HTML. А потом уже подгружать, сортировать, воровать и убивать.
UFO just landed and posted this here
Думаю при разработке сервисов — индексация это последнее о чем вы будете думать.
Или ваша личная почта доступна поисковым роботам?
Я не думаю, что это чисто почтовый шаблонизатор, хотя бы исходя из:
Этот шаблонизатор уже успешно зарекомендовал себя на нескольких готовых, но ещё не представленных проектах Яндекса.

Поэтому интересна его интеграция в открытый проект.
Мне кажется вы возлагаете на шаблонизатор те функции, которые он исполнять не должен.
Я говорил не про конкретно почту, а про «услуги как сервис», где индексация поисковиками даже вредна.
Какие функции я на него возлагаю? Но я не говорил про сервис.
Индексация поисковиками.
Правильно, готовая страница, созданная шаблонизатором должна быть проиндексирована. Если шаблонизатор этого не делает, значит надо так и сказать. Зачем вы рассказываете про сервисы?
Мы с вами явно не подружимся :)

— если сервер отдает готовый html, поисковику все равно чем вы там страницу собираете
— если интерфейс собирается на клиенте, поисковику опять все равно, т.к. исполняется только простейший js, и ваша страница не индексируется.

Для решения этой задачи был придуман hash-bang, но задача шаблонизатора, шаблонизировать собственно, а не заниматься всем и вся.
UFO just landed and posted this here
Какие роботы вы хотите, чтобы сканировали вашу почту? Шаблонизатор клиентский с большой долей вероятности пригодится в web-приложениях, не требующих сканирования себя роботами.
Яндекс же в w3c! Какие проблемы, примут синтаксис шаблонизатора как новый язык разметки, и всего-то делов.

Хотя, конечно, хорошим окончанием рассказа про шаблонизатор стало бы («станет», т.к. рассказ был про «почту», про шаблонизатор обещают же рассказать) упоминание, что Яндекс научился индексировать страницы на этом шаблонизаторе, но как-то не верится…
Простите мой китайский, но на хуа думать о поисковиках, когда инструмент предполагается больше использовать в закрытом пространстве, где сначала идет аутентификация?
Не вижу никаких проблем, гугль и другие поисковики уже умеют индексировать ajax-сайты, причём делают это достаточно хитро: по имеющейся «ajax-ссылке» (что-то вроде mysite.ru/#!/link/89) они формируют нормальную ссылку без хэша, по которой сервер отдаёт готовый HTML-слепок ajax-страницы.
Я тоже не вижу, но а) покажите сводную табличку о том, что умеют парсить поисковики. Мне как-то на глаза не попадалась; и б) речь конкретно об этом шаблонизаторе
Вот вам как это делает гугль: developers.google.com/webmasters/ajax-crawling/docs/getting-started
при желании можете поискать как это делают другие поисковики (но лично мне кажется, что примерно так же).
Что касается шаблонизатора — не имеет никакого значения какой он, поскольку HTML берётся с сервера уже готовый, в обход клиентской инфраструктуры.
Просмотрел код — не понятно, как использовать шаблоны на клиенте, без пре-компиляции на сервере. Или это не предусмотрено?

Просто XSL компилится на клиенте…

Сорри, если туплю. Документацию надо, без нее сложно.
UFO just landed and posted this here
Работал, и работаю. И ищу замену. Мы компилим на клиенте, т.к. серверный компайл неимоверно грузен.
UFO just landed and posted this here
Действительно неправильно — используют XSL
Большинство шаблонизаторов медленнее XSLT, но это не мешает их использовать. Yate это интересная разработка, но он мало где пригодится, раз только используется на клиенте.
С чего вы взяли, что только на клиенте?
Шаблоны компилируются в обычный js — так что можно использовать хоть в node.js, хоть в чем еще.
Ну то что в node.js это можно использовать я не сомневался :) А где еще, в PHP/Perl/Python можно?
Ну ноде серверный js не заканчивается. Хотя, конечно, нода наиболее популярна.
Плюс v8 можно использовать и напрямую. Например, из перла/питона/…
Интересно было бы посмотреть серверные тесты такой шаблонизации, по сравнению с XSLT.
Очень рад, что вы начинаете подчищать атавизмы :).
UFO just landed and posted this here
Я слышал, что Яндекс ещё не перешёл на препроцессоры. Хотя может Яндекс.Почта уже перешла — там живенько всё.
Да, в Почте уже перешли на Stylus. Не целиком, конечно, — перевести код с таким наследием за один раз практически невозможно.

Сейчас больше половины старых блоков подключается импортами в css, но все новые блоки уже сразу пишутся на стайлусе, ну и как только какой-то блок надо подправить — он также переводится на стайлус. Плюс, новые темы для Почты также делаются, используя стайлус. Процесс идёт :)

Подробнее про переход на стайлус я когда-нибудь (как смогу найти на это время) напишу статью в наш блог по разработке интерфейсов.
Это было бы очень интересно, а то всё Сасс, да Лесс.
А почему кстати Stylus, а не сасс и лесс?
По этой теме много чего можно рассказать, но если кратко:

— Sass отличный, но он а) на руби, б) имеет местами излишне громоздкий синтаксис (для `.scss`), в) не поддерживает конкатенацию с parent reference (типа `&__element`).

— Less — очень-очень слабый, как-то спасает возможность внутри использовать js, но в целом он очень простой. Его сильная сторона — низкий порог входа, но когда нужно сделать что-то не банальное, его возможностей не хватает.

— Stylus — как и Less работает на js — у нас и так всё на нём, для нас это преимущество. Он очень гибкий и позволяет делать много сложных штук. Если сравнивать по функциональности с Sass, то он в чём-то и проиграет, но большинство минусов для нас не имеют значения. Зато у Стайлуса прозрачный синтаксис миксинов — не нужно учить новый синтаксис для префиксных свойств, просто подключаешь библиотеку с миксинами и всё будет работать.

А вообще, самый простой способ понять какой препроцессор использовать — взять какой-то свой проект и по очереди переписать весь CSS на разных препроцессорах — максимально используя их возможности. Сразу станет ясно что подходит, а что — нет :)
Спасибо за развернутый ответ!
Совет, конечно, прекрасный, но обычно малоосуществимый.
>> в) не поддерживает конкатенацию с parent reference (типа `&__element`)

Это типа такую &:element? Или как?
Именно `&__element`, т.е. когда не псевдокласс или псевдоэлемент присобачиваются к родительскому, а часть имени.

В Less и Stylus `&__element` внутри `.block` даст `.block__element`, а в Sass там появится пробел между ними — и править это разработчики не собираются.
И вот еще что, есть же libsass, так что обязательной привязки к руби нету.
С/С++ — тоже не JS. Кроме того, любые неофициальные порты будут отставать в версиях от оригинала. Какая версия Sass реализована сейчас в livsass? Я с ходу этой информации в репозитории не нашёл.
Там где C, до модуля ноды рукой подать, у sass вроде нет версий спецификации так что я затрудняюсь сказать, знаю лишь, что планируется замещение обычного sass на обертку поверх libsass. Но когда оно будет, никто не знает.
Ну, у оригинальной имплементации Sass есть ченджлог + в репозитории есть все версии как по тегам, так и соответствующих файликах типа VERSION. Хорошо бы и в сторонних реализациях как-то указывать, с какими версиями они совместимы.
XSL прекрасно отлаживается в студии. По нажатию F5 выбирается файл XML, после чего F10 и F11 позволяют дебажить в стандартном режиме, без и с заходом в функции (шаблоны).
А это закрытое решение или где-то в открытом доступе есть?
Я по работе в Professional сижу, так что не могу вам однозначно сказать насчет того есть ли такая возможность в Express версии. Если есть желание можете попробовать.
Люди без винды оказались не у дел.
в IntelliJ IDEA есть XSLT-debugger (правда я им сам ни разу не пользовался)
Вы же понимаете, что отладить код в одном единственном XSLT-процессоре — это как отладить верстку в одном единственном браузере?
Для веб-разработчиков, да, понимаю. Но мне к счастью не приходится заниматься интерфейсами, и использую только один процессор, поведение которого предсказуемо (msxsl).
Предложения по почте для доменов:

1. Упорядочить ящики по алфавиту. При добавлении адресов в рассылку убрать постраничное деление и добавить графу Ф.И.О., логины пользователей не всегда очевидны.

2. В списке почтовых ящиков ввести графу с датой последней активности (помогает вычислять неактивные ящики) и вообще сделать его более информативным. Например указать рассылки в которых ящик состоит.

3. Сделать оповещатель о новой почте для трея. «Швейцарский нож» Я.онлайн не предлагать.

4. Добавить возможность прикреплять к письму сразу несколько файлов.

5. Удалённый ящик не исчезает из списка рассылки, после чего почта сама себе начинает рассылать уведомления о недоставленом письме.
Было бы интересно узнать, сколько такая оптимизация экономит времени пользователям.
Например:
Количество открытий почты по браузерам, за день x Сэкономленное время на странице -> PROFIT!

PS: теперь понимаю, почему мне не нравилось пользоваться Я.Почтой в Chrome
Скорее — на сколько удалось понизить кол-во отказов до момента полной загрузки страницы.
Можно и так, но я ожидал в конце увидеть что-нибудь маркетинговое, вроде «Это ежедневно экономит ХХХ минут/часов пользователям Яндекс.Почты»
Вот честно, не представляю себе, чтобы таска на ускорение рендеринга страницы исходила из необходимости написать один пресс-релиз :)
А вот снижение отказор уже больше тянет на коммерческую задачу — больше юзеров загрузит страницу полностью — больше раз покажется баннер.
С одной стороны вы правы, должна быть коммерческая цель.
Но с другой стороны — важны довольные/счастливые пользователи, жизнь которых становится лучше (меньше времени тратится на рутинные задачи). А если это еще и соответствует коммерческим целям — просто замечательно!
Мне, как пользователю, важнее раньше увидеть заголовки писем. А дождался я полного рендера/загрузки — мне не важно.
UFO just landed and posted this here
НО у каждого клиента при этом экономится несколько милисекунд. Если говорить о скорости авторизации и выдачи юзеру списка писем, то у КОГО УГОДНО дела лучше, чем у Gmail :)

Я понял основную причину перехода на новую технологию как уход со старого стремного XSL на новый крутой Yate.
UFO just landed and posted this here
По предварительным подсчётам вчера мы сэкономили нашим пользователям больше месяца времени.
Пара вопросов:

— можно ли запускать на сервере? Если да — только node.js? Не планируется ли компилятор, например, в java, как у Google в Closure Templates?

— не планируется ли какая-либо автоматизация привязки DOM к JS при вставке шаблона?
Я такое видел в dojo, удобно. Что-то вроде такого: в шаблоне помечаем нужные для JS-логики ноды, а при вставке автомагически вызывается нужный JS, в который передаются эти ноды. Обычно ведь как — вставляем HTML, и потом ищем в том что вставилось все нужное запросами — это неудобно и есть дублирование кода, есть риск что шаблон поменяют, а селекторы забудут. Хочется чего-то декларативного.
Да, можно запускать на сервере, только nodejs, на языки, отличне от JavaScript транслировать компилятор не планируется.

Остальные вопросы скорее про используемый фреймворк, а не про шаблонизатор, не думаю, что шаблонизатору нужны все эти функции, так что нет, пока не планируется.
Вообще-то планы по компиляции шаблонов не только в js есть.
Сейчас почти весь генерируемый код описан в отдельном файле-шаблоне.
Пока что, к сожалению, не все вынесено туда, но в будущем будет все там.
Так что можно будет сделать компиляцию во что-то еще.
Не уверен насчет именно java, но там видно будет.
А Вы пробовали сравнить с Fest от мейл.ру? Я далеко не сторонник синтаксиса в духе XSLT, но в своём классе этот шаблонизатор действительно быстрый. У Вас в результатах бенчмарков цифры (сужу по Chrome) великоваты. На большинстве страниц адекватного размера быстрые шаблонизаторы вполне укладываются в 1мс на рендеринг из уже скомилированной функции, если она достаточно оптимальна.
У Fest же нет рантайма в браузере
Он точно также компилирует XSL-подобный синтаксис в JS-код. Передать этот код в браузер задача тривиальная.
Это не XSL-подобный синтаксис. Fest — обычный replacer, типа mustache или handlebars. Нам такие шаблонизаторы сразу не подошли.
А чем именно не подошли? Сложность в переписывании тонны кода старых шаблонов (хотя Вам всё равно, скорее всего, пришлось это сделать) или просто идеологическая не предрасположенность? В Вашем случае, с учётом количества пользователей ресурса, чтобы пренебрегать возможностью сделать раз в 5-10 быстрее нужны довольно веские причины.
Тем, что нет аналога xsl'ного apply-templates и предикатов в матчах шаблонов. Без этого наша тонна кода превратится в неподдерживаемую кашу.
Ну если только так, как решение чтобы не убиться о старый код. Если рендерить страницы из таких функций на сервере через node.js и функция рендеринга будет работать 6-16мс, то придётся запускать сильно больше инстансов ноды, т.к. процесс лочится на время выполнения блокирующего кода, коим является рендеринг. Это очень не экономно, т.к. многие другие шаблонизаторы гененрируют функции, которые выполняются менее 1мс.
… чтобы не убится об новый код. Простейшие реплейсеры как раз приведут к тому, что у нас будут не шаблоны, а каша.

И мы не рендерим страницы на сервере, а рендерим их на клиенте.
Получилось довольно узкое решение, а «каша» это понятие очень субъективное. Многим нравятся Haml/Jade подобные синтаксисы, комуто XSL-подобные. Мне, например, больше нравятся синтаксисы в духе EJS/Eco. Я только вчера публиковал статью о JS шаблонизаторе.
Тут не суть. В любом случае в конце концов получается функция конкатенации строки. У Вас она работает сильно дольше чем у других.
Конкатенация разная бывает.
У простых шаблонизаторов — это линейная склейка строк + if/for.
У xsl/yate это выбор, в зависимости от данных, что дальше склеивать.

Первый вариант работает мега-быстро, но при увеличении числа шаблонов, количества переопределений, появления common'а и вызова его из разных мест, код превращается в кашу.

Второй вариант работает медленнее, зато у него легкая поддержка и простота работы с большим числом шаблонов.
Код превращается в кашу не из за шаблонизатора, а из за того кто пишет шаблоны (естественно, если не использовать совсем простые шаблонизаторы). Наследование, инъекция и блоки, в большинстве случаев, задачу решают и поддерживаются уже несколькими различными шаблонизаторами. При этом функция остаётся «мега-быстрой». У меня всё же впечатление что тут играет роль именно дело привычки, т.к. Вам удобен подход именно с apply-templates.
Ок, я с вашим аргументами согласен, но все-таки попробую переубедить :)

Давайте разберем пример. Есть массив, каждый элемент надо отрисовать по-разному, в зависимости от типа.
<items>
  <item type="1"/>
  <item type="2"/>
  <item type="1"/>
  ...
</items>


в xsl мы пишем
<xsl:template match="items">
  <xsl:apply-templates/>
</xsl:tempate>

<xsl:template match="item">
  <!-- общий html -->
</xsl:tempate>

<xsl:template match="item[@type = 2]">
  <!-- переопределение -->
</xsl:tempate>


Т.о. добавление нового типа простое и понятное, тем более, что такой шаблон можно написать в любом месте (хоть сторонний код) и все будет работать.

Как это реализовать на вашем любимом шаблонизаторе?
Обычно создают карту обработчиков в зависимости от type и используют как декораторы.
т.е. все типы надо знать заранее?
Как правило + дефалты. Да и глупо сравнивать императивные и декларативные шаблонизаторы.
К примеру так:

<items>
  <% for item in @items : %>
    <% switch item.type : %>

      <% when 2 : %>
        <!-- переопределяем -->
      <% end %>

      <% else : %>
        <!-- общий html -->
       <% end %>

    <% end %>
  <% end %>
</items>


Или так:

<% renderItem = (item) -> %>
  <% switch item.type : %>

    <% when 2 : %>
      <!-- переопределяем -->
    <% end %>

    <% else : %>
      <!-- общий html -->
    <% end %>

  <% end %>
<% end %>

<items>
  <% for item in @items : %>
    <%- renderItem item %>
  <% end %>
</items>


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

<a href="{item/url}">
  <xsl:if test="item/current = 1">
    <xsl:attribute name="class">current</xsl:attribute>
   </xsl:if>
  <xsl:value-of select="item/name" />
</a>


вместо:
<a href="<%- item.url %>" <% if item.current%>class="current"<% end %>><%- item.name %></a>


А если ещё нужно добавлять другие классы при этом в зависимости от разных условий то код ещё больше разнесет.

В моём примере когото могут смутить разделители, но они по вкусу настраиваются. Например можно так:

<a href="{{-item.url}}" {{if item.current}}class="current"{{end}}>{{-item.name}}</a>

А если таких типов 10? Громандный switch?
А как их объявить в разных местах?
Если таких типов 10 и они все требуют своего html кода, то делается 10 шаблонов для каждого типа элемента. И выбирается нужный:

<items>
  <% for item in @items : %>
    <% partial 'items/item_' + item.type, item %>
  <% end %>
</items>
а как в вашем примере сделать дефолтный шаблон для 5-и типов из 10?

а если есть type и subtype?
match=«item[type = 1]»
match=«item[type = 2]»
match=«item[type = 2 and @subtype = 1]»
match=«item[type = 3 and @subtype = 4]»
Это синтетические примеры, опирающиеся на сильные стороны XSLT. Так что угодно можно подогнать. В каждом конкретном случае используется техника написания под особенности конкретного синтаксиса. У XSLT есть свои минусы и самый большой из них — производительность и избыточность синтаксиса. Чего только стоит disable-output-escaping=«yes» против «черточки» и «равно» у конкурентов.
К примеру в mako (который тоже не декларативный шаблонизатор, хоть и для Python) есть конструкция if,elif,else куда ваш пример великолепно ложится.
Кроме того никто не запрещает создавать шаблонные функции и красиво выносить обработку таких вещей туда. Мне кажется для JavaScript такое тоже можно вполне написать.
Кстати, ещё один камень в огород XSLT то, что на входе он ожидает XML данные, а в XML их ещё нужно собрать. В один прекрасный день, профилируя производительность скриптов мы обнаружили, что большая часть времени генерации страницы тратится на перевод массивов в XML. Обход нескольких уровней массивов в PHP и сбор XML — очень ресурсоёмкая операция. Оптимизировали как могли — ничего не помогало. Время конвертации массивов в XML доходило до 150мс. И это всё для того, чтобы шаблонизатору данные «понравились». Это же хардкор. Проблему решили через написание расширения для PHP на С++. Он с этим справляется гораздо быстрее, но осадок остался плохой. На новом проекте (со сравнимым объёмом данных и размером шаблонов) вся страница (вместе с бизнесс-логикой), генерируется в 2-3раза быстрее чем мы тратили время преобразования массивов в XML на PHP.
А проблема с классам решается отдельным шаблоном на класс, который можно переопределить и сделать apply-imports, а не if'ами
Приходится поддерживать проект с кучей XSLT-шаблонов. Замучились капитально. Потихоньку переписывается всё это на PHP-шаблоны и обретается счастье.
А мы вот, наоборот, радуемся. Все удобно и прозрачно. Видимо, надо просто уметь готовить.
Я поддержу BVadim, декларативные шаблонизаторы местами становятся крайне не удобными. Они гораздо хуже расширяются, не говоря о том, что работают медленно.
И надо понимать, что в императивных вполне возможно применять одно-проходные алгоритмы (нет необходимости специально формировать данные для шаблонизатора).

На счёт каши: она возможна НО при правильном проектировании её не будет. Не декларативный стиль даёт больше свободы и только вам решать, получится у вас каша или быстрая стройная система по генерации html/dom.

ЗЫ а вообще у меня много претензий к xslt, и было много споров с сотрудниками yandex ;) единственный козырь xslt был в том что можно было разделить роли в разработке — программист, верстальщик. Но при использовании JSON и шаблнизации на клиенте как то этот довод уже мне кажется себя изжил.
Декларативный шаблон сложнее сломать и сложнее криво написать — это особенно хорошо проявляется в проекте на 50 человек, где обрасть знания проекта у каждого разработчика сильно ограничена. Да и в последнее время все больше шаблонизации делается декларативно — те же DOM-Based шаблоны в Kockout.js и Angular.js.

У меня тоже когда-то было отвращение к декларативным шаблонам и XSLT — тут надо просто взглянуть с другой стороны на них, да и мозг на 45 градусов повернуть.

Абзац философии
В программировании как и в жизни важен баланс между полярными вещами для достижения прочности структуры. Сочетая декларативность и императивность мы получаем удобный и гибкий код. Если же мы делаем упор на что-либо одно, то как правило оргебаем, и получаем либо не удобно либо не гибко.

Вот пример не удачного подхода — «императивный конфиг» (это даже сложно представить в мире где все конфиги в ini, YAML, JSON и XML).
Декларативный шаблон сложнее сломать и сложнее криво написать — это особенно хорошо проявляется в проекте на 50 человек, где обрасть знания проекта у каждого разработчика сильно ограничена.

Не против, только может быть тут «плохому танцору»…
И опять же:
1. Если вам реально нужна производительность и вы ограничены в ресурсах то лучше императивный.
2. Если фич заложенных в декларативный шаблон не хватает то он превращается в куда более жуткую лапшу (шаблоны в django это показывают).

Абзац философии
Это всё же больше дело вкуса… кто то гоняет на мотоцикле, а кто то на машине. Везде есть свои плюсы и минусы, и тут скорее дело вкуса и навыков.
Я написал небольшой шаблон XSLT, который позволяет компилить шаблон с наличием синтаксического сахара в обычный шаблон XSLT, и ваш пример можно записать так:
<a href="{url}" x:if-attr="current" x:attr-class="current" x:val="name" xmlns:x="xslt-sugar"/>
Хотя даже приведенный вами XSLT код не так уж и страшен, а вот отсутствие аналога <xsl:template> и осей навигации, это уже гораздо хуже, о чем автор статьи и говорит. Правда я не знаю, есть ли в Yate что-то подобное осям навигации, или это надо как-то через свои функции делать.
Императивный, декларативный… Вся эта чехарда с apply-templates — тупо завуалированные виртуальные методы/single dispatch/pattern-matching/называйте-как-хотите. Причем предельно загадочно приделанные.

Добавьте в императивный шаблонизатор диспетчеризацию и pattern-matching — и будет вам в разы лучше чем с XSLT. Добавьте еще higher order functions к этому — и будет вообще жир.
Правильно, добавляем patter-matching — получаем декларативный язык.
Чтобы сделать декларативный язык, надо добавить pattern-matching как-нибудь загадочно, ну типа как в XSLT. Если сделать прямо и понятно — ничего декларативного не получится. Ocaml — декларативный язык?
В XSLT это ещё и синтаксически уродски сделано.
XSLT синтаксически уродлив весь целиком.
Прежде чем говорить глупости прочитали бы исходники fest.
Что-то я не нашел там предикатов и apply-templates, покажите пример.
Fest — императивный шалонизатор, с конечно более продвинутыми возможностями, чем в handlebars, но семантика одинаковая.
Синтаксис был непростым решением.

Но я пока не знаю другого способа гарантировать XML на выходе, кроме как обработкой через sax парсер.
Мне не совсем понятно, зачем вы выбрали xml-синтаксис, если оперируете внутри шаблонизатора с JSON-данными? То есть, есть конечно аргументы про поддержку в редакторах и экранирование всех данных по-умолчанию. Но получается такая гремучая смесь, что мне лично это даже сложно читать, не говоря уже про написание и поддержку.
Я же написал чтобы гарантировать XML на выходе.

Если использовать fest в штатном режиме то невозможно получить невалидный XML на выходе.

Это гарантирует валидность разбора шаблона sax парсером, если шаблон на этапе компиляции разобран sax парсером это значит что во всех возможных исходах скомпилированная js функция выдасть валиный xml.
а можно вот эти места по подробнее?

> реализации, как всегда, отличаются в IE и не в IE

разумеется все процессоры разные, но почему ие вдруг ставится особняком? xslt придуман не мелкософтом, но реализован ими раньше всех.

> игнорирование первого xsl:call-template

не наблюдаю такого

> и сложными предикатами

например, какими?

> а иногда — загрузка картинки до трансформации.

иногда? какой картинки? откуда?

> Хром требует отличного от других браузеров xsl:output.

какого?

больно уж они похожи на баги, с которыми было лень разбираться и свалили всё на «причуды браузера»

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

> Самым популярным способом диагностирования проблем является комментирование кусков шаблона.

это проблема также и любого препроцессора. будь то yate, bemhtml, stylus или любой другой. понять что происходит по нагенеренному коду может только тот, кто этот препроцессор написал (или хорошо его изучил). для остальных же, это чёрный ящик как и xslt.

> в браузере же приходится сильно исхитряться со стандартными средствами, чтобы как-то нестандартно обработать строки

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

> E4X на самом деле не очень удобный

да ладно? одно только «root..descendant» чего стоит. или отсутствие «null pointer exception». по скорости — да, не нативно. но вы же яваскрипт не из-за скорости выбрали.

далее, про тесты. я не нашёл в документации делает ли yate автоматическое экранирование данных (и если да, то решили ли вы проблему формирования json внутри html, где нужно двойное экранирование?). если нет экранирования, то тесты не корректны, синтаксис громоздкий, а XSS близко. от какого и до какого момента замерялась скорость (только трансформация или плюс парсинг данных, парсинг шаблона, формирование дома)? дело в том, что xslt позволяет сразу формировать поддерево целевого документа (а значит сериализация и как следствие экранирование не нужны вообще), а yate генерирует строку, которую потом ещё браузеру придётся парсить.

кроме того в xslt есть интересная особенность — многопроходная трансформация, которая сильно помогает в случае, когда данные могут приходить в разных форматах — первым проходом нормализуем данные, а вторым формируем целевой документ.

а в целом — не плохо, хоть один приличный json шаблонизатор. всё остальное либо императивное, либо как мусташ примитивное.
1) то, что XSL впервые реализован в IE не отменяет той проблемы, что реализация во всех остальных браузерах от него отличается

2) возможно починили в свежих версиях оперы, но проблема точно есть в Opera 9.64, например, приходилось всегда объявлять <xsl:template name="null"/>, иначе самый первый <xsl:call-template> мог не отработать

3) например <xsl:template match="some[foo = bar][0]">

4) если в шаблоне есть <img src="..." onload="..." />, то эта картинка загрузится при чтении шаблона, ещё и onload может вызваться, проблема в том, что картинка грузится, а переменные в src не интерполируются, в итоге 404

5) все браузеры просят <xsl:output method="html"/>, а в хроме такой output работает не всегда и для него приходится генерить отделные шаблоны с <xsl:output method="xml"/>

6) такое мнение может пропасть, если почитать скомпилированный yate-шаблон, там всё достаточно понятно и логично, понятные имена функций, комментарии, у нас проблем с этим не возникало

7) очень спорный момент — это передавать с сервера дату сразу в 20 локалях и в индивидуальном формате для каждой локали, лучше передать timestamp и из него сделать правильный вывод при отрисовке view

8) у E4X не самая богатая документация и синтаксис не самый очевидный, он то «около-xpath», то js + он depricated + он только в SpiderMonkey + да, он медленный

9) да, yate автоматически экранирует данные, про JSON не совсем понял вопрос, но вроде он тоже экранируется

10) время трансформации — это время за которое из JSON с помощью скомпилированного шаблона получается строка с HTML, которая затем достаточно быстро вставляется в DOM с помощью innerHTML, script evaluation time для скомпилированного шаблона не учитывается, так как выполняется только один раз при загрузке шаблона и, например, профайлер оперы говорит, что уходит на это 2-3мс

11) в yate скоро появится генерация JSON, это не совсем многопроходная трансформация, но тоже весьма удобно, аналог exsl:node-set
1) то, что XSL впервые реализован в IE не отменяет той проблемы, что реализация во всех остальных браузерах от него отличается

в чём? или имеется ввиду javascript api? ну так спрятать различия в обёртку — не великий подвиг.

2) возможно починили в свежих версиях оперы, но проблема точно есть в Opera 9.64, например, приходилось всегда объявлять, иначе самый первый мог не отработать

ну вот, а говорите не развивается) пилят потихоньку. не так активно как модный «html5» к сожалению.

3) например

и что сложного в этом ни на что не матчащемся шаблоне?) для справки:
а) индексация в xpath начинается с единицы, а не с нуля
б) у элемента xsl:attribute нет никакого аттрибута select. поправьте ваш «пример» github.com/pasaran/yate/blob/master/examples/mailbox/mailbox.xsl#L452

4) если в шаблоне есть, то эта картинка загрузится при чтении шаблона, ещё и onload может вызваться, проблема в том, что картинка грузится, а переменные в src не интерполируются, в итоге 404

интересный баг, но при чём тут xslt? nin-jin.github.com/etc/opera-img-bug/

5) все браузеры просят, а в хроме такой output работает не всегда и для него приходится генерить отделные шаблоны с

в каких это случаях метод html не работает? и что значит не работает?

6) такое мнение может пропасть, если почитать скомпилированный yate-шаблон, там всё достаточно понятно и логично, понятные имена функций, комментарии, у нас проблем с этим не возникало

а где его взять простому смертному? впрочем, я не поленился и заморочился со скачиванием исправлением багов в вашем компиляторе, чтобы он не падал под виндой, исправлением глупых багов в шаблонах. nin-jin.github.com/etc/yate-vs-xslt/template.js — вот это вы называете «понятно и логично»? это типичный нагенеренный трешак с именами функций вида t42 и переменными вида v13.

7) очень спорный момент — это передавать с сервера дату сразу в 20 локалях и в индивидуальном формате для каждой локали, лучше передать timestamp и из него сделать правильный вывод при отрисовке view

а зачем передавать сразу 20 локалей, когда нужна всего одна? и тогда уж не timestamp а в iso, который понятен человеку. но тут ещё ладно, дата — вещь атомарная — её куда угодно можно присунуть. а вот формирование урлов с помощью яваскрипта в шаблонизаторе — это ахтунг. github.com/pasaran/yate/blob/master/examples/mailbox/mailbox.yate#L425
эти урлы должны либо приходить с данными, либо для них должны быть отдельные шаблоны (с матчингом и плейсхолдерами, а не ифами и конкатенацией). в конце концов, на кой чёрт данные для экшенов фигачить в урл? они либо в теле сообщения должны быть, либо в uri ресурса (в данном случае сообщения), который и должен приходить с данными.

8) у E4X не самая богатая документация и синтаксис не самый очевидный, он то «около-xpath», то js + он depricated + он только в SpiderMonkey + да, он медленный

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

9) да, yate автоматически экранирует данные, про JSON не совсем понял вопрос, но вроде он тоже экранируется

про json вопрос был в том, чтобы можно было формировать ваш любимый onclick=«return {...}» без необходимости вручную экранировать каждое значение. аналогично с урлами и прочими языками в языке.

10) время трансформации — это время за которое из JSON с помощью скомпилированного шаблона получается строка с HTML, которая затем достаточно быстро вставляется в DOM с помощью innerHTML, script evaluation time для скомпилированного шаблона не учитывается, так как выполняется только один раз при загрузке шаблона и, например, профайлер оперы говорит, что уходит на это 2-3мс

а я вот тут потестил на вашем «примере» и у меня графики получились не такие классные. nin-jin.github.com/etc/yate-vs-xslt/ что я делаю не так?
по моим данным скорость примерно равна с перевесом в сторону xslt во всех браузерах, кроме хрома. yate разворачивает 24кб шаблон в 42кб и плюс требует 24кб рантайма. xslt шаблон занимает 25кб и парсится за те же единицы миллисекунд. при этом если сделать рефакторинг шаблонов и серверной выдачи (упростить структуру и избавиться от сложной логики) — можно ещё сильнее ускорить и ужать в размере. но это не так интересно как изобретать велосипед ;-) кстати, вопреки расхожему мнению, данные в json формате оказались больше по объёму, чем те же данные в xml.
Автоматический эскейпинг, конечно, есть. Без него можно разве что hello world писать.
Про формирование json — это в ближайших планах. Будет и преобразование json в json, и временные деревья, и многопроходность.
Прошу не бить, но у меня возникла ассоциация с XAML и QML. Возможно, из-за отдаленной схожести синтаксиса.
Название не очень удачное. Есть проект yate который занимается телефонией.
Я сильно недолюбливаю XML формат. Длинные конструкции, всегда много буков… Читается тяжело. Надо повторять имя тега при закрытии. При создании нового формата надо думать, что сделать текстовой нодой, а что атрибутами.

А JSON лаконичный, краткий. Разве что есть некоторые мудрости с экранировкой, но с этим наследием JavaScript я могу смириться.

Конечно понятно, что у XML длинная история, стандартизировано куча подмножеств, куча библиотек. Есть стандартные средства преобразований, валидации, обработки и т.п. А в JSON это пока все разрозненно и не общепринято.

Но если мне надо хранить или обмениваться структурами данных, я практически всегда предпочту JSON. В том числе и в передаче данных для шаблонизаторов. Я буду рад, если со временем JSON хорошо потеснит XML.
Очень хорошо, когда видно имя закрытого тега, а не обезличенные }}}} или )))). Я работал руками и с XML данными, и с JSON, так вот с JSON было больше проблем, и ошибки искать приходилось дольше. XML конечно тоже не подарок, и я был бы рад, если бы в будущем предложили что-то отличное и от XML, и от JSON, более человечное, к примеру как Markdown по сравнению с HTML.
Зачем Яндексу ещё один декларативный xslt-подобный шаблонизатор, когда уже есть BEMHTML?
Два вопроса:
— Насколько реально написать компилятор Yate -> PHP
— Почему было-бы не написать XSLT -> JavaScript компилятор, вместо создания нового языка шаблонов?
В этом случае не пришлось бы переписывать существующие XSLT шаблоны на Yate.
XSLT -> JavaScript компилятор
XSLT + xsl2yate -> Yate -> JavaScript
1. Написать компилятор в php (и другие языки) реально.
Собственно, изначально была такая цель. Но пока не до конца все готово для этого.
Кодогенерация описана в отдельном шаблоне (это для js).
Пока что там не все, но в будущем можно будет написать php.tmpl и генерить php (perl, python, ...).

2. xslt нас устраивает концептуально, но есть разные нюансы. Громоздкий xml-based синтаксис. Невозможность расширения и т.д.
Почему это невозможно расширять? В XML как раз заложена такая возможность, через xmlns, и последующие обработчики. Я вот сделал небольшой шаблон, упрощающий синтаксис XSLT, на самом же XSLT, годится для прекомпиляции шаблонов, как и в Yate.

На первый взгляд в Yate языковые конструкции сливаются с текстом, в этом отношении XSLT лучше, он выглядит как и получаемый с его помощью HTML/XML, хотя конечно нужно на практике смотреть, может я и не прав, и шаблоны Yate на самом деле удобнее, но! Применение Yate только на клиенте сильно уменьшает возможности использования этого шаблонизатора, большинство сайтов необходимо шаблонизировать на сервере, изучать сложный шаблонизатор только ради части своих проектов не хотелось бы.
Если на сервере есть node.js то скомпилированные в js шаблоны yate, можно применять к json данным на сервере и отдавать клиенту готовый html
Увидел в топике слово Yate и подумал, что Яндекс внедряет VoIP сервис, а оно вон как.
А если безотносительно синтаксиса — как показывает себя handlebars.js в плане производительности?
Наконец-то Yandex ушёл от XSLT к JSON etc.

Очевидность необходимости переходы была видна уже давно.

Поздравляю.
Мне кажется или Yate это некая концептуальная вариация JSONT? Понятно что и то и то делает JSON->template->HTML трансформацию. У вас правда некий нетривиальный входной язык наличествует.

Если задумываться про client side template compilation то интересует объем кода самого компилятора.
И кстати что есть откомпилированная template? В моем KiTE например откомполированная template это array со строковыми литералами и ссылками на функции — эдакий bytecode. А как у вас?

А IMAP вы лагать отучили? Я в своё время перенёс основной ящик на гмыл именно из-за невыносимых лагов IMAP.
Yet Another Template Engine? ;)

А как оно соотносится с XJST? github.com/veged/xjst
По задумке вроде очень похожи, а синтаксис с виду разный. Переписали, или у вас несколько конкурирующих xsl-подобных js-шаблонизаторов? =)
xjst — это в общем-то plain js.
так что ничего общего.
Как так «ничего общего»?
— задача (трансформация «JSON — разметка»)
— парадигма (декларативность)
— предпосылка (избавиться от громоздкого XSLT, сохранив его гибкость)
— результат (собранный JS-код)
— способ сборки (компилятор на JS)

Собственно, я уже слышал вот это «мы очень любим XSLT, но как же он задолбал!» — в каком-то тексте про xjst — потому и вспомнил :)

Ну это я так, спросонья лезу — доку почитаю, тема любопытная.
Яндекс достаточно большой, чтобы в нём могли существовать люди, не сумевшие договориться и было бы не честно отрицать наличие «не технологических» причин.

Вы правы, и XJST и YATE появились из общих базовых идей типа «как XSLT, только лучше», нужен JavaScript, декларативность и т.п… Но я могу обобщить технологические отличия.

XJST проектировался и создавался как часть некоторой системы, это ядерная библиотека с узкой специализацией — нахождение шаблонов по предикатам и их рекурсивное применение — и эта узкая специализация максимально проработана (см. подробнее доклад clubs.ya.ru/bem/replies.xml?item_no=899 ). В нём нет ничего про задачу создания HTML, синтаксический сахар, ескейпинг и всякое такое. Подразумевается, что XJST будет использоваться внутри других инструментов, которые будут уже отвечать за свою узкую специализацию, например, удобство генерации HTML (например, BEMHTML) или диспетчеризацию URL-ов.

YATE это инструмент полного стека для задачи написания шаблонов для генерации HTML. Т.е. в нём встроены и какие-то механизмы подбора шаблона (более простые, чем в XJST), и вещи типа автоескейпинга, синтаксического сахара (HTML-литералов), которых совсем нет в XJST.

XJST является по сути небольшим надмножеством JavaScript, т.е. практически всё пишется именно на JavaScript и только на нём, чтобы можно было использовать существующие знания синтаксиса, производительности и т.п… И если разработчику нужно добавить какую-то сложную функциональность он может написать её нативно, внутри XJST-шаблона.

YATE это отдельный язык, который подразумевается для компиляции не только в JavaScript, т.е. в нём, например, свои принципы использования переменных и т.п… Подразумевается, что язык этот достаточно простой, чтобы с одной стороны не создавать проблем для изучения, а с другой, потенциально компилироваться плюс-минус в любой язык типа C, Perl, Java и др… Так же, этот язык такой простой, что любые сложные вещи должны реализовываться не на нём, а отдельно в виде плагинов на том языке куда происходит компиляция (JavaScript, C, Perl и т.п.).

Уже этих отличий достаточно, чтобы могли существовать два проекта. Но в теории, в будущем, можно было бы компилировать YATE в XJST, чтобы использовать и сложный оптимизированный матчинг и синтаксис, если он многим понравится.
Наверное, еще не придумали одного единственного языка, который устраивал бы всех и во всем.
Во всем Яндексе — несколько тысяч человек. Команда одного сервиса — это единицы (редко — десятки) человек. Если одни делают проект на PHP, другие на Python, третьи на C++ — в этом ведь нет ничего странного.

Есть, например, куча стандартов валидации XML — это не всегда значит, что какой-то из них объективно лучше по всем параметрам.

У каждого инструмента есть не только достоинства, но и недостатки. Вопрос лишь в том, чтобы выбрать для конкретной задачи те инструменты, достоинства которых раскроются в решении этой задачи сильнее, чем недостатки. И для разных задач этот набор разный.
> их код превращался в «кашу», в которой всё сложнее было разбираться
можно подробнее пояснить про все шаблонизаторы, которые вы так резко отнесли к императивным и сразу забраковали? Все они сейчас куда популярнее и «поддерживаемие» чем ваше решение или ajaxslt.
Просто слегка кажется что вы поменяли xsl на такое же мыло только написанное на javascript с json и без ВМ.
Я же там ниже привел типичный пример с типами, сабтипами и переопределениями.
А популярность обусловлена популярностью имеративных языков программирования. Ну и в большинстве случаев их достаточно, а Почте — нет.

И вообще это все превращается в неуместный холивар императивное vs декларативное программирование.
И в правду быстрее стало. А еще у меня на IE исчезла перерисовка экрана, когда переходишь между письмами
Планируется ли расширить серверную часть на другие серверные языки? Ищу нечто похожее для .NET. Чтобы на сервере можно было компилировать шаблон в js и выполнять откомпилированные js функции на клиенте. А так же чтобы можно было тот же шаблон сразу на сервере откомпилировать в html.
А в каком виде в Яндекс почте используется SpiderMonkey? В виде сервера аналогичного nodejs, но вместо V8 там SpiderMonkey или в другом виде?
да, в виде движка для серверного js
Сейчас разрабатываем один продукт на нем (в виде эксперимента).
Пока ВСЕ устраивает, быстрый, удобный (уже привыкли), практичный.
Только наткнулся. А как быть, если сайт мультиязычный, и не все языковые конструкции можно (и нужно) пихать через JS переменные при вставке шаблона? Рендерить нужные наборы rumain_tpl.js, en_main_tpl...?
Есть функция i18n, написанная на js и экспортированная в yate, она подставляет локализационные строки и где нужно обрабатывает исключения. В дев окружении она всегда работает и грузится один и тот же файл для всех локалей, для продакшена она заменяется (с помощью js-парсера) сразу на нужную строку или на нужную функцию, обрабатывающую исключение с захардкоженным набором строк. Таким образом в продакшене всегда лежит набор файлов, где для каждой локали свой файл.
Интересно, а как у Yate c функцией аналогичной xsl:document(), т.е. как брать нужные json? Покапался в документации и не нашел ничего. На входе подается один единственный json и подгрузка данных не предполагается? Тогда это слабое место.
Sign up to leave a comment.