NodeSmarty новый шаблонизатор для node.js (3.beta)

image Наверно каждый веб-разработчик слышал о шаблонизаторе Smarty (php). Но так как я частенько увлекаюсь JavaScript'ом, то решено было найти подобный шаблонизатор для этого языка, но серверного (node.js, ага). Первые ссылки в поисковике выдают такие шаблонизаторы, как: ECT, JUST, Mu. Все они, естественно, не подходили для меня, т.к. слишком далеко были от синтаксиса Smarty.

Чтож, раз хочется, а решений нет — то сделай. Выискивая время на работе и иногда получая по «шапке», родился проект NodeSmarty, который, в будущем, будет частично копировать синтаксис Smarty.



Итак, свои корни проект пустил примерно 4 месяца назад, в сентябре 2012 года и постепенно обретал рабочий вид. По началу весь алгоритм компиляции шаблонов брался из Smarty (файл Smarty_Compiler.class.php), некоторые функции не были перенесены. В процессе написания кода я делал всевозможные сокращения кода в плане простоты, так как это «мой стиль». Поэтому были заменены все огромные регулярные выражения (да и в них, кстати, всё равно было полно ненужного мусора), часть логики в функциях.

Так как проект необкатанный, то совершенно понятно, что в процессе будет найдено достаточное количество багов. Также уверен, что будут жалобы в сторону обработок ошибок в шаблонах (на данном этапе эта «функция» реализована плохо). Я буду только рад получать сообщения об улучшении кода, и по мере своих возможностей вносить как исправления, так и новые функции.

Примеры работы шаблонизатора:

compiler.js:
var NodeSmarty = require('./NodeSmarty/'); 

var Template = new NodeSmarty(); 

Template
   .setTemplateDir('./templates/')
   .setCompileDir('./compile/')
   .setCacheDir('./cache/');


var Array = ['val1', 'two'];

Template.assign({
   'Value':'first',
   'number':10,
   'array':Array 
});

var Final = Template.fetch('template.tpl', function(data) {
   console.log(data);
}); 


template.tpl:
{include file="header.tpl.html"}

{$Value}

{$number*10/20}

{if !$Value}
   //...
{elseif $number = $Value}
   //...
{else}
   //...
{/if}

{* comment *}

{literal}
for(var di=0; di < 10; di++) {
   console.log(di);
} 
{/literal}

{foreach from=$array item=Foo key=Key}
   Item: {$Foo} key: {$Key}
{/foreach}


Скорость выполнения кода выше, чем у EJS и JUST. Происходит это из-за того, что при повторном запросе файла, вызывается не шаблон, а уже скомпилированный код. Но есть и еще один плюс (хотя его и нет, но будет в будущем) — повышение скорости выполнения также зависит от файловой системы (дада, сначала нужно проверить, не изменились ли шаблоны, перекомпилировать их). Если же компилировать файлы при первом запросе, а при последующих просто выгружать из памяти, то скорость соответственно увеличится, и время выполнения кода станет еще меньше!

Сравнение скорости выполнения кода при 1000 итераций:

сравнение скорости

Немножко о принципе работы.

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

Первым делом парсится документ на наличие открывающего тега: { и закрывающего тега: } (хотя можно и изменить по желанию, см документацию).
Потом каждый тег парсится на главный параметр и атрибуты. Главный параметр также проходит обработку и разбивается на 2 типа: команда или переменная. Переменная отличается от команды впередистоящим знаком доллара ($). И переменная и команда проходят обработку для преобразования себя в рабочий JavaScript код. Скомпилированный код записывается в файл и происходит eval текста (хотя там не eval, а new Function()).

nodesmarty.com Ссылка на проект: NodeSmarty.com

github.com Ссылка на GitHub.com: github.com/lampaa/NodeSmarty

nodejs Ссылка на node.js: node.js
Ads
AdBlock has stolen the banner, but banners are not teeth — they will be back

More

Comments 33

    0
    Можете добавить графики сравнения производительности с dustjs и handlebars?
      0
      Скажу честно, графики я добавил лишь потому, что попросили. А так не вижу смысла сейчас сравнивать производительность. Но приму ваше сообщение на заметку. Просто еще в разных шаблонизаторах разные методы, по этому вывод переменной или обычных условий по скорости будут одинаковые, а вот, например, в одном шаблонизаторе вывод цикла через стандартные способы (forEach, for), а в других, как у меня, через специальный тег — тут уже неправильно сравнивать.
      0
      Что, серьезно? Мало шаблонизаторов для ноды?
        0
        Если не затруднит, покажите мне шаблонизатор, у которого синтаксис похож на синтаксис smarty? Я вот что-то не нашел. Спросите, почему именно синтаксис smarty? Отвечу: допустим, у меня много проектов с использованием smarty, и я хочу их портировать на node.js. Что лучше: использовать движок с другим синтаксисом и потом заморачиваться с шаблонами, или взять мой?
          +2
          В мире php многие переехали на Twig, есть две реализации на js:
          github.com/schmittjoh/twig.js
          github.com/justjohn/twig.js

          Случай портирования проектов php+smarty на node.js очень редки, и да, в этих ситуациях выгодно.
          В любом случае придется переписывать все фильтры, функции и блоки. У вас, кстати, есть такое API?
          А раз нужно переписывать все фильтры, почему не воспользоваться новыми шаблонизаторами?
            0
            Сейчас есть то, что есть. Фильтры и прочие вкусные штуки также будут. Этот шаблонизатор далеко не «Ну что, опять?». Он не похож на другие, и у него свои фичи.
              0
              А какие, если не секрет, в отличие от уже упомянутых dot, twig, handlebars, dustjs, jade и прочих? Ну, кроме синтаксиса «как в smarty», который отличается от twig, похоже, в основном наличием знака "$" перед переменными?
                0
                И, кстати, я правильно понимаю, что этот шаблонизатор нельзя использовать на клиенте?
                  0
                  Синтаксис, считаю, одно из самых главных различий между шаблонизаторами. Потом сам код довольно шустрый и не требует каких-либо компонентов. И да, шаблонизатор нельзя использовать на клиенте. Раз язык серверный, то и шаблонизатор серверный.
                    +1
                    Оооо, батенька, да вас понесло :]
                    И какой серверный язык, вы используете, если не секрет?
                      0
                      Вы о чем сейчас? Я о node.js
                        +1
                        NodeJS — это всего лишь серверная реализация JavaScript, основанная на V8.

                        P.S. Даже сейчас, вы транслируете код в очень примитивную функцию, которую можно использовать как сервере, так и на клиенте. Ну и заставить этот код работать на клиенте, тоже не трудно.
                          –2
                          Может это у вас мешают всё в лапшу, но у меня другой подход :) И я разграничиваю клиентский и серверный языки.
                            +1
                            Okay.gif
                        +1
                        Как я ошибался в своих суждениях :D
                          0

                          ¯\_(ツ)_/¯

            0
            Подскажите, а заработает ли он вместе с express.js и например nap (https://github.com/craigspaeth/nap)? К сожалению, сложно заставить express.js работать нормально НЕ с дефолтным jade и в тоже время, что бы он не кофликтовал с различным аддонами, которые встраиваются в jade
              0
              Был вопрос на github.com о примерах работы NodeSmarty и express.js в паре: github.com/lampaa/NodeSmarty/issues/2 Больше пока ничего не могу сказать.
              +2
              Вот уже не первая статья о создание шаблонизатора на NodeJS и все совершают одну и туже ошибку, никто не заботиться о разработчике, который этим будет пользоваться, где вывод ошибок compile & run-time (file, line) и юнит тесты?

              P.S. Но желаю удачи :]
                0
                О, это не ошибка, я прекрасно понимаю, как неудобно без средств отладки. Но сейчас нацелен на наращивание функционала, а уж потом на средства отладки. Конечно, хорошо бы и то и то делать, но но :) Не получается так. Спасибо!)
                  +2
                  Охо-хо, я даже не знаю как вам объяснить, что это тупик, но время рассудит.
                    0
                    Значит нужно будет пересмотреть своё решение :)
                +3
                Главный вопрос — зачем?
                Ведь от смарти нафталином несет за милю, есть гараздо более удобные и современные шаблонизаторы с поддержкой наследования и приятным глазу синтаксисом например мусташ или джейд.
                  0
                  Мне вот больше синтаксис smarty нравится. Приятный, легкий (как для разработчика, так и дизайнера).
                    +3
                    Вот про приятный, легкий для дизайнера можно подробнее? :)
                      0
                      Понятный синтаксис, море различных ситуаций, изъеденных вдоль и поперек. Под дизайнером имелось ввиду верстальщика, перепутал :)
                        0
                        Попробуйте дня три поверстать под Jade, передумаете.
                          +3
                          я ждал подобного комментария :)

                          Наткнулся на jade когда мне нужно было сверстать кучку статичных страниц (его было проще всего прикрутить к PhpStorm как «компилятор» для статики, да и плагин поддержки jade тоже вестма сносный имеется). в общем с тех пор не могу смотреть на верстку plain html без боли, jade удобен и отказаться от него мне будет сложно. Короче, я уже фанат jade с первой ложки, а ведь я его еще даже не распробовал толком, дай бог чтобы 10% возможностей освоил…

                          P.S.: naltatis.github.com/jade-syntax-docs/ первая доза бесплатно :D
                      +2
                      нафталином — так и пишите PHP :)
                        0
                        Для быстрого портирования проектов php на node.js.
                        0
                        Немного придирок

                        сейчас в мастере это: github.com/lampaa/NodeSmarty/blob/ba6fc41e61a9b1edd09b44df0e8ab1f9726ae811/index.js

                        строка 714 — нет var (возможен баг в разных объектах)
                        строка 729 — аналогично 714

                        В циклах вида for key in obj нет проверок obj.hasOwnProperty(key). Может привести к неожиданным багам

                        Ну и в конце концов — что за практика пошла писать все в одном файле? Попробуйте разделить логику (отдельно парсер, отдельно компилятор, отдельно рендерер и т.п.)
                          0
                          и console.log бы лучше убрать из модуля) используйте модуль аля debug
                          0
                          Из документации:

                          Все шаблоны при использовании проходят дополнительную обработку — компиляцию. Шаблон компилируется в чистый (native) JavaScript код, причем как компиляция, так и исполнение кода являются самыми быстрыми при сравнении с остальными шаблонизаторами!


                          JUST и EJS, а тем более Jade не являются самыми быстрыми шаблонизаторами. JUST это попытка сделать улучшенный EJS, однако она зашла в тупик из-за невозможности сделать доступ к переменный без which или префиксов типа this.varName. Для такого случая нужна прекомпилция всего кода. Поэтому родился ECT. Он наследуют синтаксис eco но намного быстрее и предлагает широкий функционал и язык изобретать/учить не надо т.к. используется CoffeeScript. Попробуйте протестировать скорость этим бенчмарком. Там учтен приближенный к среднему объем текста и тестируются отдельно варианты с эскейпингом и без.

                          Only users with full accounts can post comments. Log in, please.