This is Sapper!

Este blog ha sido migrado desde Nikola a Sapper. En este artículo describiré las principales razones, resultados de pruebas de rendimiento y otras reflexiones sobre la utilización de Sapper y Svelte para generar sitios web estáticos.

He migrado el stack the tecnologías utilizado en mi blog de Nikola + reStructuredText a Sapper + Asciidoctor.

Por qué dejar Nikola?

Este blog ha sido generado por Nikola desde 2014, cuando el término JAMStack ni existía. Funcionó muy bien estos años y tiene todas las características que necesitaba por defecto:

  • Soporte multi-idioma.

  • reStructuredText, el cual prefiero sobre Markdown.

  • Está desarrollado en Python, uno de mis lenguajes de programación preferidos.

Pero tuve algunos problemillas que me molestaban desde el principio:

  • El fichero de configuración estaba un poco hinchado y era algo confuso.

  • No era fácil para mí crear, modificar on encontrar templates que me convenciesen.

  • El rendimiento del sitio era algo mediocre, el último informe que generé con Lighthouse audits era alrededor de 80, excepto por la sección SEO que era 96.

Por qué Sapper?

DX: Developer experience

Ya había utilizado Sapper para crear algunas pequeñas PWAs [1], aquí puedes encontrar 2 ejemplos que desarrollé con Svelte y Sapper:

Currency Exchage Loss Calculator

Una aplicación útil para viajeros que utilizan casas de cambio. Dependiendo en el cambio que ofrezcan en ese momento y la cantidad de dinero que quieras cambiar, te muestra la cantidad de dinero que estás perdiendo en esta transacción de cambio.

COVID-19 Stats

Muestra estadísticas actualizadas sobre el COVID-19 por país y por fecha.

Durante la creación de estas PWAs, la experiencia de desarrollo con Sapper&Svelte ha sido bastante impresionante.

UX: La experiencia de usuario con Sapper

Últimament me he encontrado con algunos blogs utilizando Sapper como el propio blog de Sapper, Coding with Jessie or swyx.io. La experiencia de usuario me ha parecido similar a Gatsby, quizá algo más ligeros y más originales.

Note
Sapper está inspirado en Next.js, aquí puedes encontrar una comparación con este conocido framework.

Asciidoctor

No tengo una preferencia clara sobre Asciidoctor o reStructuredText, estoy cómo con ambos, pero hay más soporte para Asciidoctor en otros lenguajes de programación como JavaScript. Así que, básicamente he cambiado a Asciidoctor prque no encontré una librería JavaScript que convirtiese correctamente reStructuredText a HTML.

El principal problema de no utilizar Markdown fue la falta de plugins de Rollup para convertir Asciidoctor a HTML, así que creé uno, rollup-plugin-asciidoc. La implementación fue muy sencilla, el plugin simplemente utiliza la librería Asciidoctor.js para convertir un texto de entrada en formato Asciidoctor a HTML.

rollup-plugin-asciidoc al rescate

Tip
Con rollup-plugin-asciidoc podemos importar Asciidoctor archivos de nuestro blog y Rollup los convertirá a HTML.

Ejemplo

a-blog-post.adoc
= Post title
:date: 2019-11-11

Such a post!
Con rollup-plugin-asciidoc podemos importar archivos Asciidoctor uno por uno.
import doc from './a-blog-post.adoc';

console.log(doc);
Salida
{
  meta: {
    title: "Post title",
    date: "2019-11-11"
  },
  html: "<p>Such a post!</p>"
}

Pero importar ficheros uno por uno no es útil para un blog donde tenemos muchos archivos, los cuales no queremos importart manualmente uno por uno.

rollup-plugin-glob al rescate

Con rollup-plugin-glob podemos importar todos los ficheros que estén en un directorio por extensión, esto significa que ya tenemos todos los posts de nuestro blog convertidos a HTML en un par de líneas de código.

import allAdoc from '../posts/**/*.adoc';

allAdoc.forEach(post => console.log(post));
Output: List of posts already converted to HTML
{ meta: { title: "Post title", date: "2019-11-11" },
  html: "<p>Post 1.</p>"
}
{ meta: { title: "Post title", date: "2020-02-22" },
  html: "<h2>Title post</h2><p>This is a sample post...</p>"
}
// ...

Resaltado de sintáxis para el código fuente

El tema principal de mi blog es la Ingeniería del Software, así que el resaltado de sintáxis es uno de los requisitos más importantes que un generador de sitios web estáticos debe cumplir.

Al principio utilicé la librería highlightjs desde un CDN, que consiste en importar un fichero javascript para analizar el código fuente y un fichero CSS para aplicar el resaltado.

Más tarde me dí cuenta, de que el trabajo de análisis del código fuente lo podemos hacer tiempo de compilación, cuando convertimos Asciidoctor a HTML en la implementación del rollup-plugin-asciidoc, de esta forma el usuario no tendrá que descargar el fichero JavaScript ni procesar el código fuente en su navegador.

Tip
Haciendo el resaltado de sintáxis mientra construimos el sitio web, mejoramos el rendimiento del blog y reducimos los datos que el usuario tiene que descargar.

La generación del resaltado de sintáxis en la construcción del sitio web tiene 2 grandes beneficios:

  • Reducir el tamaño del sitio web: no necesitamos descargar los 27KB del fichero highlightjs javascript library.

  • Mejora de rendimiento: el análisis del código fuente se hace solo una vez, mientras se construye el sitio web.

Resultado

Todavía hay algunos problemas o mejoras que hacer=_blank, pero hasta ahora tenemos un blog con las siguientes características:

  • Generación automática de Sitemap and Atom feeds.

  • Soporte multi-idioma (todavía faltan muchas traducciones).

  • Resaltado de código.

  • Puntuación de 100 en Lighthouse audits, aunque todavía hay algunas páginas con menos de 100.

lighthouse score

Pruebas

Soy un ferviente defensor de las pruebas automáticas, no me gusta escribirlas, pero creo que es la mejor forma de saber que todo funciona como se espera.

El template de Sapper trae preconfigurado un test de integración muy simple. Utiliza Cypress, un framework de pruebas E2E [2], más sencillo que Selenium, aunque creo que todavía no podemos hablar de the Selenium Killer.

Note
En muchos casos no puede reemplazar a Selenium: La principal razón es que Cypress por diseño no tiene algunas funcionalidades que podrías necesitar, depende del proyecto, como por ejemplo soporte para pruebas en casi cualquier navegador y plataforma, como el proporcionado por Selenium grid.

He añadido algunas pruebas para este blog (y añadiré más), como verificar que la información del header es correcta, que funcionan las redirecciones, que los principales flujos de navegación funcionan…​ Todo ello en un par de hoars, incluyendo correcciones de errores encontrados. Por esto me encanta escribir pruebas con Cypress, por su productividad.

Escribiendo una prueba

Funciona de forma similar a Selenium: . Abre una página. . Accede a un elemento utilizando HTML identifier (#element-id), XPath (/a[@title='link title']) or CSS selector (div > a.cssClass). . Interactuar con el elemento seleccionado. . Validar que todo se comporta de forma esperada.

Puedes encontrar ejemplos de pruebas en la carpeta cypress/integration.

Ejemplo simple
it('Header', () => {
  cy.visit('/posts/this-is-sapper/en') (1)
  cy.get('.subtitle .date').contains('28/08/2020') (2)
});
  1. Navega al path de un post.

  2. Comprueba que la fecha que aparece en el subtítulo es correcta.

Typescript

Finalmente el soporte de Svelte para Typescript está terminado y después de más trabajo del esperado, he migrado este blog utlizando Sapper con Javascript a Sapper con Typescript. Te animo a que utilices este proyecto como ejemplo o template para tu blog, si encuentras algún problema, el feedback es bienvenido. Hay todavía algunos problemas, como averiguar que si utilizar eslint o svelte-check o ambos.


1. Progressive Web Application
2. End to end