Breno G. de Oliveira

Xslate - Seu próximo sistema de templates
Publicado em 01/01/2010

Xslate - Seu próximo sistema de templates

Dizem que escrever um framework web ou um sistema de templates é uma espécie de ritual de passagem para muitos desenvolvedores. De fato, uma rápida olhada no CPAN nos dá diversas opções. Escondido no meio delas, com um nome estranho, direto da terra do sol nascente, está um um candidato de peso, e tema do artigo de hoje: o Text::Xslate, "Xslate" para os íntimos.

Já uso TT, obrigado. NEXT!

É inegável que, até o momento, Template reina absoluto entre os diferentes sistemas de template. É simples, robusto, estável, e muito bem documentado, mais recomendado que o novo Colgate Total 12. No mundo Perl, 9 entre cada 10 desenvolvedores tratam TT como a melhor, senão única, opção decente. Mas então, por que sequer considerar uma alternativa como o Xslate?

Continue lendo. Você não vai se arrepender ;-)

Altíssimo desempenho

O Xslate possui uma máquina virtual escrita em XS e fortemente otimizada para renderizar templates. Como resultado, benchmarkings apontam para renderizações muito mais eficientes que a concorrência. Não estamos falando de ser 2x, ou 5x mais rápido. O Xslate coloca velocidade na renderização em outra ordem de grandeza, com medições chegando a 158x(!!) mais rápido que o TT2.

O gargalo da maioria das aplicações está no acesso ao banco de dados, mas isso não quer dizer que outras áreas não possam ser otimizadas. Se sua aplicação possui templates complexos e você suspeita que a renderização possa estar impactando no desempenho, o Xslate pode ser a sua solução definitiva.

Compatibilidade com TT

Normalmente, esse tipo de velocidade vem com um impacto significativo na usabilidade do sistema de templates. Afinal, se fosse para escrever em Perl puro, não precisaríamos de um sistema de templates em primeiro lugar! Designers precisam de uma micro-linguagem simples que possam integrar em seu HTML sem muito esforço, e esse é um dos pontos mais fortes do TT.

Além disso, se você já trabalha muito bem obrigado com o TT, reescrever tudo na sintaxe do Xslate pode não ser uma opção. Nada tema! O Xslate já possui não uma, mas duas camadas diferentes de compatibilidade com o TT :)

   use Text::Xslate;

   my $template = Text::Xslate->new(
       syntax => "TTerse",
       module => [ 'Text::Xslate::Bridge::TT2Like' ],
   );

   my $tt_string = 'Bem-vindos ao [% evento %]!';

   print $template->render_string( $tt_string, { evento => 'Equinócio' } );

A camada de compatibilidade abrange ~90% de todo o TT, incluindo Virual Methods como var.length() e var.replace(), e diretivas como IF, WRAPPER, INCLUDE, FOREACH, WHILE, SET, etc. Alguns poucos elementos ainda estão de fora - como PROCESS e DEFAULT - mas na maioria dos casos podemos viver sem eles.

A variação do Text::Xslate::Bridge::TT2Like é o Text::Xslate::Bridge::TT2, e para utilizá-lo basta trocar a chamada no código acima. A diferença entre eles é que o TXB:TT2 importa os vmethods do Template-Toolkit, enquanto o TXB:TT2Like implementa tudo diretamente para você e não precisa do Template-Toolkit instalado.

Você precisará instalar a bridge desejada separadamente. Mas, assim como o Xslate, a instalação tanto do TXB:TT2Like quanto do TXB:TT2 é simples e indolor.

Com essas facilidades, você pode continuar escrevendo seus templates no formato do Template-Toolkit, e contar com uma renderização absurdamente rápida!

Escape automático de meta caracteres em HTML

Todas as expressões interpoladas pela engine do Xslate são escapadas em HTML automaticamente, a menos que você explicitamente diga o contrário. Isso significa que sua aplicação já vem protegida contra ataques XSS por padrão, sem que você precise fazer nada!

Templates extensíveis (com modificadores e roles, como Moose!)

Não, você não entendeu errado. Se você está acostumado com INCLUDE e WRAPPER do Template-Toolkit, tudo bem. Agora, se você escreve seus próprios templates e muitas vezes sentiu-se frustrado por não poder trabalhar com extensões mais flexíveis, experimente o Xslate. Veja a seção abaixo/Extendendo Templates abaixo para mais detalhes.

Instalação

O Xslate possui pouquíssimas dependências, mas seu código é em XS, então você vai precisar de um copilador C na máquina alvo. Instalar é moleza:

em sua shell do CPAN:

   cpan> install Text::Xslate

ou direto via cpanminus:

   $ curl -L http://cpanmin.us | perl - Text::Xslate

O formato padrão: Kolon

Se você está acostumado com formatos como Mason ou EPL (Mojolicious), vai se acostumar rapidamente com o Xslate. O formato é muito simples:

* tags inline

Para exibir o conteúdo de variáveis ou utilizar tags inline de um modo geral, basta utilizar colocar o conteúdo entre a abertuta <: e o fechamento :>.

   Olá <: $nome :>, tudo bem?

* linhas inteiras

Quando estivermos fazendo uma operação mais complexa, normalmente envolvendo blocos, pode valer a pena utilizar a linha toda. Para isso, basta começar a linha com ":".

   : if $idade > 18 {
       Bebida liberada!
   : }

Comentários

Como em Perl, comentários são o que vier depois de um #.

  : $var = "lalala" # isso é um comentário
  :# essa linha toda também é um comentário

A diferença é que também podemos usar comentários em tags inline:

  <: # $var : comentário!>

Você pode também terminar comentários com ponto e vírgula, assim como qualquer outra declaração:

  : # isso é um comentário; $var # o '$var' aí do meio é renderizado!

Variáveis

Além das variáveis passadas para o nosso template, podemos criar nossas próprias variáveis:

  : my $foo = 42;
  : my $bar = "baz";

Podemos também criar constantes:

  : constant FOO = 42;

Funções e Filtros

Você pode registrar funções através das opções function ou module do Text::Xslate->new(), e chamá-las usando o operador () ou o símbolo |.

  : f()        # sem argumentos
  : f(1, 2, 3) # com argumentos
  : 42 | f     # o mesmo que f(42)

Algumas funções úteis:

  : $var | raw  # interpola variável sem escapar o conteúdo
  : $var | dump # dump da variável com Data::Dumper

É possível ainda criar pequenas macros em seus templates:

  : macro alo -> $cidade {
      Alo, <: $cidade :> !
  : }

  Minha mensagem: <: : alo("são paulo")>

Métodos

Se $var é um objeto, você pode chamar os métodos usando um ponto:

  <: $var.método() :>

Condicionais

Blocos if-else e given-when funcionam sem a necessidade de parêntesis:

  : if $var == nil {
      lalala
  : }
  : else if $var != "foo" { # elsif também funciona
      lelele
  : }
  : else {
      lilili
  : }

Laços

Os laços for são iteradores simples:

  : # itera uma referência a ARRAY em $lista
  : for $lista -> $item {
      o item é <: $item :>
  : }

Podemos acessar a variável iteradora chamando $~NOME_DA_VAR:

  : for $lista -> $item {
      o item atual é  <: $item :>
      o índice dele é <: $~item.index :>
      index + 1 é     <: $~item.count :>

      : if $~item.is_first {
          primeirão!!!
      : }
  : }

Extendendo Templates

Templates podem ser incluídas normalmente:

  : include "foo.tx";
  : include "foo.tx" { var1 => "meep", var2 => 42 };

Mas o grande barato está mesmo na enorme flexibilidade que o Xslate proporciona. Podemos, por exemplo, definir uma série de blocos em um template base, e derivar nossos templates desses componentes.

Suponha o seguinte template myapp/base.tx:

  : block titulo -> {
      Equinócio!
  : }

  : block conteúdo -> { } # sem conteúdo padrão

Podemos testar a renderização de nossa base através do programa xslate, que vem junto com o módulo:

  $ xslate myapp/base.tx
     Equinócio!

Mas nosso objetivo é extender a base em outros templates, por exemplo, myapp/foo.tx:

  : cascade myapp::base
  : around conteúdo -> {
      meu conteúdo bonitão!
  : }

Vamos experimentar a renderização agora:

  $ xslate myapp/foo.tx
     Equinócio!
     meu conteúdo bonitão!

Podemos extender tantos templates quanto quisermos, exatamente como extenderíamos um método no Moose! Veja outro exemplo agora, myapp/bar.tx:

  : cascade myapp::foo

  : around titulo -> {
      ----------
      : super
      ----------
  : }

  : before conteúdo -> {
      Isso é renderizado ANTES do conteúdo!
  : }

  : after conteúdo -> {
      E isso vem DEPOIS!
  : }




É só executar e ver o resultado:

  $ xslate myapp/bar.tx
     ---------
     Equinócio!
     ---------
     Isso é renderizado ANTES do conteúdo!
     meu conteúdo bonitão!
     E isso vem DEPOIS!

Aliás, falando em Moose, templates podem ser tratados como classes, e extendidos tratando os blocos como roles:

  : cascade myapp::base with myapp::role1, myapp::role2

Com roles, podemos até mesmo omitir a base:

  : cascade with myapp::role1, myapp::role2

Legal, né?

Catalyst + Xslate

Agora que vimos todas as vantagens do Xslate, que tal experimentá-lo em seu framework Web favorito?

O primeiro passo é instalar a View apropriada:

  cpan> install Catalyst::View::Xslate

O segundo passo é... bom, não existe segundo passo ;)

A criação de uma View para nossa aplicação pode ser feita pela linha de comando:

  $ script/myapp_create.pl view HTML Xslate

ou, pra usar a camada de compatibilidade do Template-Toolkit:

  $ script/myapp_create.pl view HTML Xslate bridge=TT2

trocando TT2 por TT2Like conforme sua vontade (veja acima).

Se preferir "fazer na mão", a View é exatamente como qualquer outra:

  package MyApp::View::Xslate;
  use strict;
  use parent 'Catalyst::View::Xslate';

  1;

ou ainda:

  package MyApp::View::Xslate;
  use Moose;
  extends 'Catalyst::View::Xslate';

  has '+module' => (
      default => sub { [ 'Text::Xslate::Bridge::TT2Lite' ] }
  );

  1;




Mojolicious + Xslate

Se, por outro lado, você prefere o Mojolicious, instale o MojoX::Renderer::Xslate e adicione o seguinte código na sub startup de sua aplicação:

  use MojoX::Renderer::Xslate;
  my $xslate = MojoX::Renderer::Xslate->build(
      mojo => $self,
      template_options => {},
  );
  $self->renderer->add_handler( tx => $xslate );

ou simplesmente carregue o renderizador como um plugin do Mojolicious:

  $self->plugin('xslate_renderer');

No Mojolicious::Lite então, é mais fácil ainda! Basta adicionar no início de seu programa:

  plugin 'xslate_renderer';

Fácil, não é? Você pode também passar opções ao plugin normalmente:

  plugin 'xslate_renderer' => {
      template_options => { syntax => 'TTerse', ... }
  };




Concluindo

Text::Xslate é um poderoso e flexível sistema de templates, com altíssimo desempenho, e que veio para ficar.

Ainda que prefira a sintaxe tradicional do Template-Toolkit, bastam alguns pequenos ajustes em nossos templates tradicionais para contarmos com a incrível velocidade de sua engine. E, com a integração com os principais frameworks web do mundo Perl, você não tem motivos para não experimentar :)

AUTHOR

Breno G. de Oliveira <garu@cpan.org>

blog comments powered by Disqus