Saltar al contenido principal

Nunjucks como motor de plantillas: lo bueno y lo mejorable

Nunjucks es el motor de plantillas que uso en todos mis proyectos con Eleventy. Lo elegí porque es potente, tiene una sintaxis clara y la herencia de layouts funciona exactamente como esperas. Después de varios años usándolo, tengo una opinión matizada: es muy bueno, pero no es perfecto.

Lo que me gusta #

Herencia de layouts #

La característica estrella. Defines un layout base y los demás lo extienden:

{# base.njk #}
<!DOCTYPE html>
<html>
  <head>...</head>
  <body>
    {{ content | safe }}
  </body>
</html>

{# post.njk — extiende base #}
---
layout: layouts/base.njk
---
<article class="post">
  <h1>{{ title }}</h1>
  {{ content | safe }}
</article>

Es limpio, predecible y fácil de seguir. Cada layout sabe qué hereda y qué añade.

Includes y partials #

Los parciales de Nunjucks son la forma más natural de componentizar HTML sin JavaScript:

{% include 'partials/cabecera.njk' %}
{% include 'partials/pie.njk' %}

No hay props, no hay estado, no hay ciclo de vida. Es solo insertar HTML. Para una web estática, es todo lo que necesitas.

Filtros #

Los filtros son funciones que transforman datos en la plantilla. Eleventy permite definirlos en la configuración y usarlos en Nunjucks:

<time>{{ date | readableDate }}</time>
<p>{{ content | intro(100) }}</p>

Son compositivos — puedes encadenarlos — y mantienen la lógica de presentación separada de los datos. Es el patrón correcto.

Loops y condicionales #

La sintaxis para iterar y condicionar es directa:

{%- for post in collections.bitacora %}
  {% if post.data.destacado %}
    {% include 'partials/postcard.njk' %}
  {% endif %}
{%- endfor %}

Sin sorpresas, sin edge cases raros. Hace lo que parece que hace.

Lo que me frustra #

Errores crípticos #

Cuando algo falla en una plantilla Nunjucks, los mensajes de error son a menudo inútiles. Un paréntesis mal cerrado o una variable inexistente te dan un error genérico que apunta a la línea equivocada. Depurar una plantilla compleja a veces se convierte en un proceso de eliminación: vas comentando bloques hasta que encuentras el que falla.

No hay tipado #

Nunjucks no sabe qué propiedades tiene un objeto hasta el runtime. Si escribes {{ post.tittle }} (con doble T), no hay error — simplemente no renderiza nada. Te das cuenta cuando ves un hueco vacío en la web. TypeScript arruinó mi tolerancia a los errores en tiempo de ejecución.

Sintaxis verbosa para lógica compleja #

Cuando la lógica se complica, Nunjucks se vuelve difícil de leer:

{%- set postsOrdenados = collections.bitacora | ordenarPorFecha | head(3) %}
{%- for post in postsOrdenados %}
  {%- if post.data.tags | filterTagList | length > 0 %}
    ...
  {%- endif %}
{%- endfor %}

No es terrible, pero cuando tienes tres niveles de anidación con filtros encadenados, echas de menos poder escribir lógica en un lenguaje de verdad.

Whitespace control #

Los {%- y -%} para controlar los espacios en blanco son necesarios pero molestos. Si no los usas, tu HTML generado tiene líneas vacías y sangrado irregular. Si los usas en todas partes, la plantilla se vuelve ruidosa.

Lo que he considerado #

Liquid: más limitado que Nunjucks, pero con mejor manejo de errores. Jekyll lo usa y la comunidad es enorme.

WebC: la propuesta nativa de Eleventy para componentes web. Interesante, pero todavía joven y con una curva de aprendizaje diferente.

JSX/TSX con 11ty: técnicamente posible, pero va contra la filosofía de mantener las plantillas simples y sin build step.

De momento me quedo con Nunjucks. Sus defectos son menores comparados con sus ventajas, y la familiaridad acumulada después de varios proyectos tiene un valor que no se puede subestimar. El mejor motor de plantillas es el que ya conoces, siempre que no te limite activamente.