+(505) 5727-9567
contacto@felixicaza.com

Astro: Un Generador de Sitios Estáticos para la Web Moderna

07 Septiembre, 2022 - 11 minutos de lectura

Actualmente los desarrolladores web contamos con una gran cantidad de herramientas, librerías, frameworks, utilidades, etc, etc… Que nos permiten crear sitios web. A veces nos puede resultar complicado entre tantas opciones, elegir una herramienta que se adapte completamente a nuestras necesidades para iniciar un proyecto, pero, Astro es una opción muy interesante a la que podrías darle un vistazo.

Astro: Un Nuevo Generador de Sitios Estáticos para la Web Moderna

En esta publicación conocerás a fondo sobre Astro, aprenderás como puedes empezar a utilizarlo, sus principales conceptos y una comparación con otras alternativas ya existentes.

¿Qué es Astro?

Astro es un framework para construir sitios estáticos, es decir, páginas web que se renderizan a HTML, CSS y JavaScript puro y que no necesitan código de servidor para funcionar. Pero Astro no está limitado a esto, sino que, también podemos hacer uso de cualquier librería JavaScript para construir un sitio web ya sea React, Vue, Preact, Svelte y algunos otros, siendo útil para el desarrollo Micro Frontend. Además podemos implementar Server Side Rendering (SSR), esto con el fin de optimizar el rendimiento y hacer que los sitios web sean amigables para el SEO.

Cuándo crees tu primer proyecto con Astro, notarás que es extremadamente rápido, y esto es gracias a que por debajo utiliza Vite.js como builder, lo que permite tener Hot Module Replacement (HMR) activado por defecto y todas las demás ventajas con las que cuenta Vite.

Principales conceptos en Astro

Astro como lenguaje de plantillas

Astro por sí mismo es un lenguaje de plantillas tal y cómo puede ser otros sistemas de plantillas antiguos como Pug, Handlebars, EJS, etc, lo que te permite poder separar interfaces o cualquier lógica en componentes y reutilizarlos a lo largo de tu proyecto.

Pero la sintaxis de Astro está fuertemente inspirada en JSX, por lo que si tienes experiencia en React se te hará muy cómodo utilizarlo, pero si no, también es muy similar a utilizar HTML puro, solamente debes aprender algunos otros conceptos sencillos que podrás ir notando en esta publicación.

Los archivos de Astro deben tener la extensión .astro y en el siguiente ejemplo puedes ver cómo es su sintaxis:

---
const mainTitle = 'Este es un sito web hecho con astro.'
---

<html>
  <head>
    <meta charset='UTF-8' />
    <meta name='viewport' content='width=device-width, initial-scale=1' />
    <title>Ejemplo de la sintaxis de Astro</title>
  </head>
  <body>
    <h1>{mainTitle}</h1>
  </body>
</html>

El ejemplo anterior es muy fácil de entender, además puedes omitir el uso de la declaración DOCTYPE, ya que Astro lo agrega automáticamente, pero repasemos que significa la sección entre los tres guiones --- de la parte superior.

Esta idea fue inspirada de un concepto llamado Frontmatter que es una sección comúnmente utilizada para añadir metadatos usando la sintaxis del lenguaje YAML, se volvió muy popular en otros generadores de sitios estáticos como Jekyll para facilitar la creación de blogs utilizando Markdown.

Pero en Astro esta sección está destinada a escribir código JavaScript que será renderizado por el Runtime. Todo el código escrito en esta sección nunca se compilará para el Frontend, por lo que se puede definir esta sección en un término más sencillo como la “parte Backend” de Astro. Es útil para:

  • Importar otros componentes de Astro.
  • Importar librerías como React y componentes de estas librerías.
  • Crear variables que se pueden referenciar en el código (Como en el ejemplo anterior).
  • Hacer llamadas a una API.

Astro Islands

Este es un concepto mayormente útil cuándo utilizamos librerías JavaScript como React, Vue, Svelte, etc. Con la filosofía principal de Astro de construir sitios web con el mínimo de JavaScript necesario, los Astro Islands se basan en un patrón llamado Hidratación Parcial que consiste en la optimización de componentes interactivos para que estos solamente sean cargados cuándo el usuario realmente los necesite.

Por ejemplo, pensemos en un carousel o en un menú lateral (sidebar) ambos solicitan datos de una API externa y son componentes interactivos creados con React. Normalmente si tenemos algún tipo de error en cualquiera de ambos componentes, nuestra aplicación web de React fallará, pero en Astro utilizando los Astro Islands ambos componentes son totalmente independientes uno del otro, por lo que si tenemos un error en algún componente sólamente se verá afectado el componente en cuestión. Además, otra ventaja, es que si algún componente se encuentra fuera del área visible del usuario (viewport) este no será cargado, ahorrando así una ejecución innecesaria de JavaScript.

Si quieres conocer más a fondo sobre los Astro Islands puedes leer su documentación: https://docs.astro.build/es/concepts/islands/

Astro vs Otras Alternativas

Al ser un generador de sitios estáticos, es muy fácil comparar Astro con otras herramientas con el mismo propósito como Gatsby, Hugo y Jekyll (por mencionar algunos). Pero también es válido comparar Astro con frameworks que soportan Server Side Rendering como Next.js, Nuxt.js y SvelteKit, ya que Astro también soporta este patrón.

Haciendo una comparación general de Astro versus las demás alternativas mencionadas, es que con Astro así como tenemos la opción de no usar ninguna librería también tenemos una mayor libertad de elegir cuál podemos utilizar en nuestro proyecto, pero además, podemos combinarlas, usar React para algún componente o Vue para otro, sin preocuparte por el performance de tu aplicación web, esto con la optimización que por defecto ofrece Astro.

Mientras que herramientas como Gatsby, Next.js o Nuxt.js, solamente podemos usar React o Vue respectivamente. Pero, otros como Hugo o Jekyll, tiene una curva más alta de aprendizaje, ya que estamos obligados a conocer incluso otro lenguaje de programación para poder utilizarlo a nuestro gusto, porque Hugo está creado usando Go y por último, mencionar que Jekyll está creado usando Ruby.

En este aspecto, Astro resultará mucho más fácil de utilizar, tanto si solo conoces HTML, prefieres usar React o simplemente te resulta mejor opción usar Vue. Todo te será muy familiar, porque no tendrás que aprender ninguna sintaxis nueva.

Puedes conocer otras comparaciones en la documentación de Astro: https://docs.astro.build/es/comparing-astro-vs-other-tools/.

¿Cómo empezar a usar Astro?

Ahora sí podrás conocer cómo crear un proyecto con Astro o migrar uno ya existente.

Usando create-astro

La manera más fácil de usar Astro es crear un proyecto usando su herramienta CLI, solamente debes ejecutar el siguiente comando en la terminal:

npm create astro@latest

Luego deberás indicar el nombre de la carpeta que contendrá tu proyecto, después deberás elegir si deseas usar una plantilla, las opciones que ofrece Astro son: Un proyecto básico, Blog, Portafolio, Sitio de documentación o Proyecto vacío, luego deberás indicar si deseas instalar las dependencias (obviamente debes aceptar) y opcionalmente te pedirá si deseas inicializar un repositorio con Git.

Después de haber creado tu proyecto con create-astro deberás entrar a la carpeta de tu nuevo proyecto y podrás inicializar el servidor de desarrollo ejecutando el comando:

npm run dev

Y para construir tu proyecto listo para producción deberás ejecutar el comando:

npm run build

Instalando Astro de forma manual

Si ya tienes una carpeta dónde te gustaría incluir Astro, lo primero que debes hacer es instalarlo ejecutando el siguiente comando en la terminal:

npm install astro@latest

Luego deberás añadir los siguientes comandos en el archivo package.json:

{
  "scripts": {
    "dev": "astro dev",
    "build": "astro build",
    "preview": "astro preview"
  }
}

Ahora solamente deberás crear el archivo de configuración de Astro, el cual deberá tener el nombre astro.config.mjs, y dentro deberás escribir el siguiente código:

import { defineConfig } from 'astro/config'

// https://astro.build/config
export default defineConfig({})

Sea el método que hayas utilizado, lo siguiente que sigue es comprender cómo es la estructura de carpetas de un proyecto de Astro. Si elegiste la instalación manual deberás crearla siguiendo la manera tal cual como verás en la siguiente sección.

Estructura de un proyecto con Astro

En Astro proponen una estructura de carpetas recomendadas:

  • astro-project
    • src
      • components
        • Header.astro
        • Button.jsx
      • layouts
        • PostLayout.astro
      • pages
        • posts
          • post1.md
          • post2.md
          • post3.md
        • index.astro
      • styles
        • global.css
    • public
      • robots.txt
      • favicon.svg
      • social-image.png
    • astro.config.mjs
    • package.json

src/

Esta carpeta es dónde se encontrará todo el código fuente de tu proyecto de Astro.

src/components

En esta carpeta se encontrarán piezas de código reutilizables (componentes). Podemos incluir componentes de Astro, pero también cualquier otro componente de framework como React o Vue.

src/layouts

Los layouts son un tipo especial de componente, ya que son más globales porque podemos separar una estructura (layout) en común para el contenido. Por ejemplo, en un layout principal podemos colocar un navbar o footer, ya que queremos que aparezcan en todas las páginas.

src/pages

La carpeta pages es muy importante en Astro, ya que cualquier archivo o carpeta que creemos dentro será una ruta de nuestro proyecto. En cuanto al nombre de las demás carpetas, el nombre pages es el único que es obligatorio.

src/styles

Esta es una carpeta opcional dónde podemos almacenar archivos CSS.

public/

Cualquier archivo que sea colocado dentro de la carpeta public no será procesado por Astro, es decir, no será incluido dentro del proceso de optimización del código para producción. Por lo que en esta carpeta será dónde podemos colocar imágenes y código de terceros que no tendremos que modificar.

astro.config.mjs

Este es el archivo de configuración principal de Astro, dónde podrás configurar cualquier opción que necesites para la compilación final, incluir integraciones, etc.

Si deseas conocer más sobre la configuración de Astro, puedes leer la guía de referencia de la configuración.

Componentes de Astro

Anteriormente ya conocimos un poco sobre la sintaxis de Astro, pero ahora vamos a profundizar en otros conceptos.

Principales similitudes con JSX

Debido a que Astro está inspirado en la sintaxis de JSX, es por esta razón que vamos a encontrar muchas similitudes que podemos utilizar al momento de crear nuestros componentes o layouts con Astro.

Variables

Al igual que en JSX, podemos obtener el valor de una variable usando la sintaxis de las llaves {}.

---
const nombre = 'Astro'
---

<h1>¡Este es un componente de {nombre}!</h1>

HTML dinámico

En muchas ocasiones tendremos que generar HTML dinámicamente y en Astro podemos hacerlo de la siguiente manera:

---
const items = ['Item 1', 'Item 2', 'Item 3']
---

<ul>
  {items.map(item => <li>{item}</li>)}
</ul>

Renderizado condicional

Renderizar condicionalmente un componente es un caso muy común. Por ejemplo:

---
const visible = true
---

{visible && <p>¡Muéstrame!</p>}

{visible ? <p>¡Muéstrame!</p> : <p>¡O muéstrame a mi!</p>}

Fragmentos

En los componentes JSX, siempre debe existir un elemento principal, es por eso que en muchas ocasiones es obligatorio utilizar los fragmentos (<> </> o <Fragment> </Fragment>), pero en Astro esto no es necesario, excepto en un caso muy puntual.

Para crear más de un elemento dinámicamente en Astro, es dónde es necesario utilizar la sintaxis de los fragmentos.

---
const items = ['Uno', 'Dos', 'Tres']
---

<ul>
  {
    items.map(item => (
      <>
        <li>{item} Rojo</li>
        <li>{item} Azul</li>
        <li>{item} Verde</li>
      </>
    ))
  }
</ul>

Propiedades de componentes

En Astro podemos definir propiedades personalizadas para nuestros componentes.

Creamos nuestro componente llamado Saludar:

---
const { saludo, nombre } = Astro.props
---

<h2>{saludo}, {nombre}!</h2>

Utilizamos nuestro componente:

---
import Saludar from './Saludar.astro'
const name = 'Astro'
---

<h1>Componente de saludo</h1>
<Saludar saludo='Hola' nombre={name} />

Entendamos el ejemplo anterior, para utilizar nuestro componente en otro, primero debemos importarlo, luego vamos a instanciarlo (<Saludar /> en este caso) y por último definimos sus propiedades saludo y nombre, como podrás notar también podemos pasar valores dinámicos a las propiedades. Y para obtener esas propiedades en la creación de nuestro componente, debemos hacer uso de la propiedad Astro.props dónde haciendo uso de la sintaxis de desestructuración obtenemos el nombre de las propiedades (saludo y nombre).

En caso de que no hayamos proveído ninguna propiedad, también es posible establecer valores por defecto.

---
const { saludo = 'Qué tal', nombre = 'Ejemplo' } = Astro.props
---

<h2>{saludo}, {nombre}!</h2>

Slots

Cuándo creamos un componente que no recibirá elementos dentro, debemos cerrarlo en sí mismo, pero cuándo tenemos que pasar elementos dentro del componente, en Astro hay que hacer uso del elemento especial <slot />. A diferencia de las propiedades que podemos obtenerlas a través de Astro.props, cada elemento que definamos dentro, se renderizará automáticamente.

Definimos un componente contenedor o layout:

---
import Header from './Header.astro'
import Logo from './Logo.astro'
import Footer from './Footer.astro'

const { titulo } = Astro.props
---

<div id='content-wrapper'>
  <Header />
  <Logo />
  <h1>{titulo}</h1>
  <slot />
  <!-- aquí van los elementos hijos -->
  <Footer />
</div>

Luego lo utilizamos de la siguiente manera:

---
import Contenedor from '../layouts/Contenedor.astro'
---

<Contenedor titulo='Página de Ejemplo'>
  <h2>Todo sobre Ejemplo</h2>
  <p>Aquí veremos cosas sobre Ejemplo.</p>
</Contenedor>

Estilos CSS

Para aplicar estilos a un componente también podemos definir una etiqueta <style> dentro.

---
const { saludo, nombre } = Astro.props
---

<h2>{saludo}, {nombre}!</h2>

<style>
  h2 {
    font-size: 25px;
    font-weight: bold;
    color: #333;
  }
</style>

Script del lado del cliente

Cómo ya has visto, podemos definir scripts dentro de la directiva de los guiones ---, pero estos nunca serán utilizados por el Frontend de nuestro proyecto. Es por esta razón que en Astro para aplicar scripts que sean necesarios para el lado del cliente podemos usar la etiqueta <script>.

Por defecto, el código que hayamos definido dentro será procesado por Astro. Además, si nuestro componente es utilizado varias veces a lo largo de nuestro proyecto esa lógica con JavaScript solamente será utilizada una vez, evitando así código duplicado.

---
const { saludo, nombre } = Astro.props
---

<h2>{saludo}, {nombre}!</h2>

<button id='main-button'>Haz clic</button>

<script>
  const btn = document.getElementById('main-button')

  btn.addEventListener('click', () => {
    console.log('Haz hecho clic')
  })
</script>

Pero si queremos omitir la optimización del código dentro de la etiqueta, podemos hacer uso de la directiva de Astro is:inline.

---
const { saludo, nombre } = Astro.props
---

<h2>{saludo}, {nombre}!</h2>

<button id='main-button'>Haz clic</button>

<script is:inline>
  const btn = document.getElementById('main-button')

  btn.addEventListener('click', () => {
    console.log('Haz hecho clic')
  })
</script>

Para conocer sobre las directivas de Astro puedes leer su documentación: https://docs.astro.build/es/reference/directives-reference/.

Si quieres conocer más sobre los componentes de Astro, haz clic en el siguiente enlace: https://docs.astro.build/es/core-concepts/astro-components/.

¿Cómo crear rutas en Astro?

Para crear una ruta en Astro, simplemente debemos crear un archivo dentro del directorio src/pages con el nombre de la ruta que vamos a referenciar y este estará disponible automáticamente para ser accedida a través de un enlace. En Astro podemos crear rutas estáticas y dinámicas.

Rutas estáticas

Cada componente de página que crees dentro de la ruta src/pages será una ruta estática para tu proyecto. Supongamos que tenemos la siguiente estructura:

  • astro-project
    • src
      • pages
        • posts
          • post1.md
          • post2.md
          • post3.md
          • index.astro
        • about
          • index.astro
          • me.astro
        • about.astro
        • index.astro

Lo que se renderizará de la siguiente manera:

src/pages/index.astro -> /
src/pages/about.astro -> /about
src/pages/about/index.astro -> /about
src/pages/about/me.astro -> /about/me
src/pages/posts/index.astro -> /posts
src/pages/posts/post1.md -> /posts/post1
src/pages/posts/post2.md -> /posts/post2
src/pages/posts/post3.md -> /posts/post3

Como habrás notado con las rutas src/pages/about.astro y src/pages/about/index.astro puedes usar solamente el nombre del archivo o en su lugar usar una carpeta para referenciar dicha ruta. Si te preguntas qué opción es mejor, en realidad depende de ti, pero nunca debes usar ambos como en este ejemplo, ya que en la compilación final entrarán en conflicto entre sí.

Rutas dinámicas

Las rutas dinámicas son útiles cuándo obtenemos información desde una API y queremos generar dichas rutas a partir de esta. En Astro, para la generación dinámica debemos crear un archivo o una carpeta con la siguiente nomenclatura en su nombre: [rutas].astro o src/pages/[usuarios]/perfil.astro y haremos uso de un método que nos provee Astro, llamado getStaticPaths().

Supongamos que tenemos la siguiente ruta en nuestro proyecto, src/pages/posts/[post].astro y dentro del archivo este contenido:

---
export function getStaticPaths() {
  return [
    // Genera: /posts/post1
    { params: { post: 'post1' } },
    // Genera: /posts/post2
    { params: { post: 'post2' } },
    // Genera: /posts/post3
    { params: { post: 'post3' } }
  ]
}

const { post } = Astro.params
---

<h1>Este es el {post}</h1>

El método getStaticPaths() siempre debe devolver un array de objetos que serán las rutas que van a ser pre renderizadas por Astro, ya que las rutas dinámicas se crearán en tiempo de compilación.

Si deseas conocer cómo funciona a fondo la función getStaticPaths() puedes darle un vistazo a su documentación: https://docs.astro.build/es/reference/api-reference#getstaticpaths.

Además para comprender un poco más sobre las rutas en Astro, haz clic en el siguiente enlace: https://docs.astro.build/es/core-concepts/routing/.

¿Cómo desplegar un proyecto de Astro?

Después de haber finalizado de trabajar en tu nuevo proyecto con Astro, ahora querrás saber cómo desplegarlo. Cómo ya sabes en Astro podemos desplegar un sitio web estático o uno implementando Server Side Rendering.

En la documentación de Astro ofrecen varias guías para desplegar tu proyecto con varios proveedores muy populares, entre los cuales están:

Puedes revisar las guías de otros proveedores que ofrecen en la documentación de Astro, haciendo clic en este enlace: https://docs.astro.build/es/guides/deploy/.

Otros Recursos

Integraciones

Si quieres extender la funcionalidad de Astro puedes usar las integraciones, que no son más que plugins. En Astro ofrecen algunas integraciones oficiales, como:

Puedes revisar todas las integraciones oficiales en este enlace: https://astro.build/integrations/official/. Además existe una gran colección de integraciones creadas por la comunidad: https://astro.build/integrations/.

Instalando una integración

Para añadir una integración en tu proyecto debes instalarla, por ejemplo si quieres instalar react, debes ejecutar el siguiente comando:

astro add react

Esto instalará el paquete @astro/react y añadirá la configuración automáticamente en el archivo de configuración de Astro:

import { defineConfig } from 'astro/config'
import react from '@astrojs/react'

// https://astro.build/config
export default defineConfig({
  integrations: [react()]
})

Cuándo instalas una integración no oficial debes instalarla manualmente usando npm install someintegation en lugar de usar astro add y además debes añadir la opción experimental en el archivo de configuración:

import { defineConfig } from 'astro/config'
import someintegration from 'someintegration'

// https://astro.build/config
export default defineConfig({
  experimental: { integrations: true },
  integrations: [someintegration()]
})

Temas

Si quieres empezar tu proyecto con un tema puedes revisar el directorio de temas de Astro, dónde encontrarás temas oficiales como de terceros, si bien a la fecha de publicación de este post no hay muchos temas, debido a que Astro aún es una herramienta muy nueva, no está de más mencionar que incluso podemos crear nuestros propios temas que nos permitirá ahorrar mucho tiempo al momento de crear un nuevo proyecto usando esta herramienta.

Instalando un tema de Astro

En este ejemplo haré mención del tema oficial de Astro llamado Blog, podemos instalarlo usando este comando:

npm init astro -- --template blog

Luego de eso ya podrás utilizar el tema en tu nuevo proyecto, aunque deberás comprender cuál es la estructura del proyecto.

Ya hemos repasado un poco de todo lo que ofrece Astro, en mi opinión es una herramienta con un gran futuro. Debido a su facilidad de uso, ya que cualquier desarrollador con conocimientos avanzados o alguien quién apenas esté empezando en el desarrollo web, no tendrá que aprender sintaxis nueva o compleja, simplemente teniendo el conocimiento base en HTML puedes empezar a usar Astro.

Referencia:


Si te ha gustado este artículo, podrías invitarme a un café, te lo agradecería muchísimo.

Invítame a un café

¡Comparte este artículo!

Otras publicaciones

Mira otras publicaciones