Middleman: Generador de sitios web estáticos
Publicado el Miércoles, 6 de agosto de 2014Vengo usando mi sitio personal como "tarjeta de presentación" desde hace un buen tiempo, para dirigir potenciales relaciones laborales a ese sitio. Hace mucho que venía con ganas de actualizarlo así que volví a arrancar de cero (por tercera o cuarta vez).
El contenido es bastante simple, debía ser un sitio que mostrara parte de mi trabajo y experiencia de manera sencilla y directa. No inclui mi CV. Tengo perfiles en LinkedIn y StackOverflow Careers, por lo que mostrar un CV online implica repetir información que ya está en otros lugares. Con cada cambio debería mantener la información actualizada en varios sitios. Así que agregué los links.
También agregué el link a GitHub, donde se puede ver gran parte del trabajo Open Source que he hecho, y otros perfiles online como Lanyrd o Speakerdeck. Las empresas se están acostumbrando a que pueden encontrar mucha información de un programador online sin tener que pedir específicamente un archivo PDF con la especificación técnica de la persona.
Sería interesante interactuar con la API de LinkedIn o StackOverflow Careers (si la tiene), para tener un CV actualizado "dinámicamente". Es algo a pensar, junto a la cantidad indeterminada de veces que pienso en borrar mi perfil de LinkedIn en el día. No me aporta mucho más que Spam de gente que no conozco y con la que nunca tuve relación laboral agregándome con el mensaje por defecto de "Me gustaría agregarte a mi red profesional" o algo así. En un momento pensé empezar a responder a cada una de las "invitaciones" con un simple: "¿Por qué?", pero seguro encuentro cosas mejores que hacer con mi tiempo.
Desde la parte técnica, aprovecho cada reboot de mi sitio personal para usar al menos una tecnología que no conociera de antes. Mi caso de uso era bastante sencillo:
- HAML para el HTML (por preferencia personal nomás)
- Markdown para el contenido (ídem anterior)
- Contenido internacionalizado para Inglés y Español
- No voy a actualizar el sitio tan seguido ni tengo tanta información, un CMS o similar es demasiado
- Tiene que ser rápido - El CSS y (en caso de usarlo) JavaScript debe ser lo mínimo necesario.
Tecnología
Vamos a las decisiones tecnológicas que tomé y el por qué. Para empezar, decidí que iba a usar Cuba y me iba a armar un "mini-cms" como para mantener el sitio actualizado cuando quiera agregar alguna cosa nueva. El sitio era una aplicación Sinatra alojada en Heroku. No usaba base de datos, al ser poco el contenido se encontraba en archivos de texto (yml). Así que empezar de cero con Cuba no iba a cambiar mucho el tema de hosting, podía usar Postgres o alguna otra cosa en Heroku.
A mitad de camino volví a pensar en generadores de sitios estáticos. Ya había hecho algunas pruebas antes con Jekyll, y empecé a leer sobre Middleman. Navegando un poco por la documentación, me decidí a usarlo. Al producir páginas estáticas, podía alojar el sitio en GitHub Pages en vez de Heroku. De esta forma, dependo de un repo menos.
Templates
Middleman soporta templates Slim, ERB, HAML y más. También trae soporte para Markdown con distintos motores, así que resolvía dos de las cosas que quería en el sitio. Trae también soporte para partials y Template Helpers que nos facilitan algunas tareas y definir helpers propios es bastante sencillo. En mi caso usé los helpers propios para incluir algunos fragmentos de código Ruby que tenía por ahí para recuperar información de distintos sitios: RubyGems, GitHub y WordPress.
Esto genera una lista "dinámica" obteniendo información de cosas que he publicado (gemas, plugins, repos) y lo muestra en el sitio.
Contenido
Haml es malo para escribir contenido, y prefiero usar Markdown siempre que puedo. La idea era combinar estas dos cosas con la internacionalización. Así que el contenido se encuentra en archivos yml correspondientes a los locales 'es' y 'en' para español e inglés respectivamente. Al usar i18n, llamamos a los textos con el método t(:clave_del_texto). El siguiente paso era parsear el texto como markdown, por lo que hice un helper parecido llamado text, con el cual renderizo como Markdown lo que me devuelve el método t:
def text(string) markdown = Redcarpet::Markdown.new( Redcarpet::Render::HTML, autolink: true, no_intra_emphasis: true, lax_spacing: true) markdown.render(t(string)) end |
CSS y JavaScript
El CSS es muy sencillo, menos de 200 líneas aunque inclui el framework SimpleGrid para las grillas y diseño responsivo. Otras veces había usado PureCSS, pero decidí usar algo distinto esta vez. También agregué los íconos de Octicons y Genericons para darle algo más de vida al sitio.
Middleman incluye Sprockets, un sistema de empaquetamiento de recursos (CSS, JavaScript, CoffeeScript). Permite incluir otros archivos en uno, empaquetándolos y minificándolos (opcionalmente) a un solo archivo. De esta forma, puedo incluir simplegrid.css, octicons.css y genericons.css en mi archivo css principal con las siguientes sentencias:
/*
*= require _simplegrid
*= require _octicons.css
*= require _genericons.css
*/ |
Al agregar el guión bajo antes del nombre de cada archivo, estoy pidiendo que los contenidos de ese css sean concatenados al contenido de mi css para tener todo en un mismo archivo.
Lo mismo se puede hacer con JavaScript. Lo bueno de esto es que a pesar de tener muy poco código, puedo organizarlo en archivos distintos. Y nada de esto afecta al rendimiento final del sitio ya que todo el contenido se va a servir como recursos estáticos generados previamente.
Publicación en GitHub Pages
Una parte que le falta al código es la generación automática de los archivos estáticos de manera periódica. Por ahora estoy usando la gema middleman-gh-pages desarrollada por algunos ex Neo y otros desarrolladores de la comunidad. La funcionalidad básica que provee la gema, es una tarea Rake para poder publicar a la branch gh-pages en GitHub con un único comando:
$ rake publish |
Conclusión
Llegué a un proceso de actualización bastante dinámico y el resultado con un sitio estático alojado en GitHub Pages es suficientemente bueno. Cumple su cometido de ser un centro de enlaces a distintos recursos que permitirían a potenciales colegas o contratadores conocer un poco sobre mi perfil laboral.
El resultado final está en fernandobriano.com y el código fuente en GitHub. Cosas para mejorar siempre hay, ya habrá tiempo para eso 🙂
abr4xas 10 agosto. 2014 - 22:57
Esta es una excelente alternativa, y no probaste pelican y alojarlo en github?
Fernando 13 agosto. 2014 - 11:50
Hola, no conocía Pelican hasta que lo mencionaste en este comentario. De hecho hay mucho que no conozco del mundo Python todavía. Pero no descarto probarlo para algun futuro proyecto 🙂
Marco de la Concha 12 agosto. 2014 - 10:30
Fernando.
Has trabajado con algun desarrollo de geolocalizacion de sucursales mas cercanas a la IP donde acceso al sitio?
Tenemos un cliente con 189 sucursales en todo el territorio mexicano y quisieramos utilizar google maps API.
Tenemos otro con 7 sucursales.
Nuestro sitio es http://www.funnel.mx
Saludos cordiales,
Marco de la concha.
marco@funnel.mx
Fernando 13 agosto. 2014 - 11:53
Hola Marco,
Una vez usé geolocalización, pero fue hace un buen tiempo. La tecnología ha cambiado bastante desde entonces así que ya hay mejores alternativas. Si fuera a hacer algo estos días, arrancaría por la documentación de la API web Geolocation.
¡Saludos!
raviolicode 16 agosto. 2014 - 03:26
Hola! Muy buen artículo 🙂
Un tip, para deployar es mejor usar: https://github.com/karlfreeman/middleman-deploy
Creo que middleman-gh-pages no está siendo actualizado, y además no te permite deployar a a github-pages para algo que no sea tu sitio personal (por ejemplo, un sitio de proyecto).
Saludos!
Fernando 20 agosto. 2014 - 22:00
Gracias Lu,
Voy a empezar a usar middleman-deploy entonces, por lo que veo está super al día así que es una mejor opción 🙂
¡Saludos!