Cómo acelerar la compilación de MDX con Rust y Sätteri
Si alguna vez has construido documentación extensa o un blog con Astro, Next.js o Vite, probablemente te has encontrado con problemas de velocidad de compilación. Sientes como si acabaras de agregar unas pocas docenas de archivos con código y gráficos, y de repente tu proyecto tarda cuarenta segundos en compilarse en lugar de cinco.
El culpable casi siempre es el mismo: la cadena tradicional de unified, remark y rehype. Estas son herramientas excelentes con miles de plugins listos para usar, pero se ejecutan completamente en JavaScript single-threaded. Cuando necesitas parsear un montón de archivos .mdx pesados, dividirlos en árboles AST, aplicar transformaciones y reensamblarlos, Node.js rápidamente alcanza sus límites.
Los desarrolladores del colectivo Bruits decidieron abordar el problema de manera pragmática. Crearon Sätteri — un parser y compilador de Markdown/MDX donde todo el trabajo pesado se hace en Rust, mientras los desarrolladores continúan usando JavaScript familiar.
Cómo funciona este híbrido
Los creadores de Sätteri no reescribieron todo desde cero. En cambio, tomaron soluciones probadas de la comunidad y las unieron usando enlaces NAPI.
Dentro del monorepo, el proyecto se divide en dos niveles: crates de Rust de bajo nivel y wrappers para Node.js y Vite.
A nivel de Rust, se utilizan los siguientes componentes:
satteri-pulldown-cmark— un fork del popular parser pulldown-cmark con soporte añadido para sintaxis MDX.satteri-mdxjs-rs— un fork del compilador mdxjs-rs, adaptado para OXC — un parser de JavaScript/TypeScript basado en Rust y de rápido crecimiento.satteri-ast— tipos de nodos MDAST y HAST, así como operaciones de árboles.satteri-napi-binding— una capa puente entre C++ / Rust y JavaScript.
Encima hay una capa limpia de TypeScript. La idea principal es que no necesitas aprender Rust ni reescribir tus scripts de compilación. Instalas un paquete npm regular y trabajas con él como cualquier otra utilidad en tu archivo de configuración.
Interesante es el enfoque para el procesamiento de plugins. Escribir un compilador en Rust es una tarea directa. Los desafíos reales comienzan cuando necesitas dar a los usuarios la capacidad de modificar el árbol AST en JS. En Sätteri, el parsing y el ensamblaje del código final ocurren a máxima velocidad dentro de Rust, mientras que las llamadas a plugins de usuario en JavaScript ocurren selectivamente a través de un enlace rápido. Los autores fueron honestamente inspirados por la arquitectura de Lightning CSS, que usa un principio similar para los visitors.
Compilando proyectos con Vite
Para usuarios de Vite, los autores prepararon un paquete separado vite-plugin-satteri. Convierte la conexión de archivos .md y .mdx en un par de líneas de configuración.
import { defineConfig } from 'vite';
import satteri from 'vite-plugin-satteri';
export default defineConfig({
plugins: [
satteri({
// Ваши настройки и плагины
}),
],
});
El bundle incluye un plugin satteri-expressive-code para renderizado hermoso de bloques de código. Si tu documentación tiene muchos ejemplos con resaltado de sintaxis, esta combinación reemplaza los usuales plugins pesados de Rehype.
Beneficios prácticos y compromisos
¿Por qué agregar otra herramienta a tu proyecto cuando tienes librerías probadas durante años?
Primero, la velocidad de compilación en CI/CD y desarrollo local. Cuando tienes cientos de páginas, la diferencia entre ejecutar operaciones en V8 y código Rust compilado se vuelve muy notable.
Segundo, la conveniencia de la migración. Si tu proyecto ha alcanzado el techo de rendimiento de remark, generalmente se te ofrece esperar pacientemente o reescribir todo en Go o Rust. Sätteri proporciona un término medio: el parsing se vuelve rápido, mientras la infraestructura de plugins de JS permanece accesible.
Pero hay matices. El proyecto todavía es joven, con poco más de mil estrellas en GitHub y 23 issues abiertos al momento de escribir esto. Esto significa que algunos casos extremos de sintaxis MDX o plugins específicos del ecosistema pueden necesitar trabajo. También existen limitaciones de los bindings de JS: si tu plugin de JS hace un millón de pequeñas llamadas al AST dentro de la memoria de Rust, la sobrecarga de marshalling podría comerse parte de las ganancias de velocidad.
¿Vale la pena probar?
Sätteri es un gran hallazgo para quienes construyen sitios grandes de contenido, sistemas de documentación o generadores de sitios estáticos. Si tu proyecto de Vite o Astro tarda segundos en cargar cuando editas archivos MDX, la herramienta definitivamente merece una prueba.
Puedes probar el compilador en acción sin instalación directamente en tu navegador a través del playground oficial en el sitio web del proyecto, o unirte a la comunidad de Discord de los autores para discutir características.
Si has estado buscando una forma de acelerar tu compilación sin reescribir radicalmente todo el pipeline en otro lenguaje, prueba instalar satteri y ejecutar benchmarks en tus propios archivos.
Proyectos relacionados