Boltdocs 3.1.0 — Modo Turbo, MDX con Sätteri y CSS Crítico con Zig

3.1.0 trae la bandera --turbo: un compilador MDX impulsado por Rust, extracción de CSS crítico compilada con Zig y un modo parser de pasada única. Primera fase del camino hacia builds 4x más rápidos.
Esta se trata de los cimientos
3.0.0 fue sobre velocidad pura — el parser nativo. 3.1.0 es sobre la siguiente capa: el modo turbo. Esta es la Fase 1 del Proyecto Nitro, y cambia lo que corre por debajo cuando construyes.
Una bandera experimental --turbo que reemplaza el compilador MDX por Sätteri (Rust), Beasties por extracción de CSS crítico compilada con Zig, y activa un modo parser de pasada única. Este es el primer paso hacia builds 4x más rápidos.
Build output optimizado: Beasties de inlining de CSS crítico ha sido desactivado por defecto, reduciendo el HTML total en ~7.3 MB. El bug de duplicación del locale por defecto también ha sido corregido, ahorrando ~8 MB adicionales. Combinado, el output del build es ahora ~60% más pequeño.
--turbo — Modo Build Experimental
La nueva bandera --turbo activa tres optimizaciones nativas en un solo comando:
pnpm boltdocs build --turbo
O configúralo permanentemente con una variable de entorno:
BOLTDOCS_TURBO=true pnpm boltdocs build
Qué cambia por debajo:
| Componente | Sin --turbo | Con --turbo |
|---|---|---|
| Compilación MDX | @mdx-js/rollup + plugins remark/rehype JS | Sätteri (Rust) + plugins nativos |
| CSS crítico | Ninguno (CSS externo solamente) | @bdocs/zig-critters (Zig/WASM) |
| Parser | Modo multi-pasada | Pasada única con buffer compartido |
Esta bandera es experimental. Puedes encontrar problemas de compatibilidad de CSS por zig-critters o diferencias de compilación MDX por Sätteri. Si algo falla, elimina --turbo y reporta el problema — tu build estándar no se ve afectado.
Sätteri MDX — Compilación Impulsada por Rust
El cambio más grande en modo --turbo es el compilador MDX. Sätteri reemplaza @mdx-js/rollup con un procesador basado en Rust, construido sobre pulldown-cmark con extensiones MDX.
El pipeline:
- El parser Rust (
satteri-pulldown-cmark) parsea Markdown/MDX a un AST asignado en arena - Los plugins MDAST corren sobre la arena (remark-meta, remark-gfm)
- El AST se convierte a HAST
- Los plugins HAST corren (rehype-slug, rehype-shiki)
mdxToJs()compila el HAST a salida JSX
Benchmarks del sitio de documentación de Boltdocs (241 páginas):
| Métrica | Default (@mdx-js/rollup) | Turbo (Sätteri) | Diferencia |
|---|---|---|---|
| Build Time | 97.3s | 43.9s | 2.2x más rápido |
| SSG Total | 98.7s | 45.1s | 54% más rápido |
| Salida JavaScript | 10.5 MB | 8.4 MB | 20% menos |
| Salida HTML | 25.65 MB | 15.51 MB | 40% menos |
Sätteri también incluye tres sub-plugins nativos que reemplazan los equivalentes estándar de remark/rehype:
satteriRemarkMetaPlugin— captura las meta strings de las cercas de código enhProperties.metastringsatteriRehypeSlugPlugin— agrega atributosida los encabezadossatteriRehypeShikiPlugin— resaltado de sintaxis Shiki via visitante HAST
Comportamiento de fallback
Si Sätteri falla al compilar un archivo, automáticamente vuelve a @mdx-js/rollup con plugins básicos (remark-gfm, remark-frontmatter, rehype-slug). Tu build no se rompe — simplemente no es turbo para ese archivo.
Limitación conocida: compatibilidad con plugins legacy
Sätteri usa una arena Rust para los nodos HAST. Los plugins estándar de unified/remark/rehype que mutan nodos en su lugar no funcionan — Sätteri requiere un patrón de retorno-para-reemplazar. Si usas plugins personalizados via remarkPlugins o rehypePlugins en tu configuración, pueden no aplicarse en modo turbo. La capa de adaptador detecta esto y muestra un warning.
Por ahora, el modo turbo funciona mejor para sitios con MDX estándar (bloques de código, tablas GFM, frontmatter). Los sitios con muchos plugins personalizados deben usar el compilador estándar.
@bdocs/zig-critters — CSS Crítico Compilado con Zig
Beasties extrae CSS crítico cargando tu HTML y CSS, emparejando selectores, e inlineando solo las reglas que aplican above the fold. Funciona — pero está escrito en JavaScript.
@bdocs/zig-critters es una reescritura completa en Zig, compilada a WebAssembly. Mismo algoritmo, velocidad nativa.
Cómo funciona:
- Carga el binario WASM pre-compilado en el primer uso
- Codifica tu HTML y CSS en la memoria lineal de WASM
- Parsea CSS a reglas, parsea HTML a una lista plana de elementos
- Empareja selectores contra elementos, marca reglas no usadas
- Serializa solo las reglas críticas de vuelta a JS
El resultado se inyecta como un tag <style data-zig-critters>...</style> antes de </head>.
Qué soporta
- Contenedores
@mediay@supports— se mantienen si alguna regla hija coincide @keyframes— tres estrategias:critical(solo las usadas),all,none@font-face— inline opcional viainline_fonts- Reglas
@property— siempre se mantienen - Directivas de include/exclude basadas en comentarios
- Minificación de CSS (habilitada por defecto)
Limitación conocida: compatibilidad de CSS
zig-critters elimina pseudo-clases y pseudo-elementos al emparejar (comportamiento equivalente a Beasties). Esto significa que :hover, :focus y selectores dependientes del viewport se emparejan solo contra su elemento base. Algunos casos bordeos con cadenas de selectores complejas pueden producir CSS crítico diferente al de Beasties.
Si notas problemas de estilos en modo turbo, intenta eliminar --turbo para confirmar que es un issue de zig-critters, luego reportalo con una reproducción.
Modo Parser de Pasada Única
El parser nativo en Zig ya corre 5-6x más rápido que el antiguo parser JS. En modo turbo, cambia a un algoritmo de pasada única:
- Modo normal:
parseDoc()— dos pasadas (una para frontmatter/headings, otra para texto plano) - Modo turbo:
parseDocSinglePass()— una pasada con unParseContextbuffer compartido
Misma salida, menos asignación de memoria. El modo de pasada única genera encabezados, texto plano y contenido en un solo escaneo con estilo de arena.
Feature Flags y Borradores
Controla qué páginas son visibles en cada entorno sin cambios de código ni builds condicionales.
Borradores
Marca cualquier página como borrador en el frontmatter:
---
title: Próxima Función
draft: true
---
Las páginas en borrador se excluyen automáticamente de los builds de producción. En desarrollo, los borradores son visibles por defecto. Controla la visibilidad via config:
export default defineConfig({
drafts: {
visible: false, // Ocultar en todos los entornos
environments: ['development', 'staging'], // O por entorno
},
})
O usa la variable de entorno BOLTDOCS_DRAFTS=true forzar la visibilidad.
Feature Flags
Define feature flags en tu config:
export default defineConfig({
featureFlags: {
'new-dashboard': true, // Siempre visible
'beta-api': 'development', // Solo en desarrollo
'experimental-search': false, // Siempre oculto
},
})
Luego marca las páginas con flags requeridos:
---
title: Nuevo Dashboard
featureFlags:
- new-dashboard
- beta-api
---
La página solo se renderiza cuando todos los flags declarados están activos. Perfecto para lanzamientos progresivos, pruebas A/B u ocultar herramientas internas de producción.
Los feature flags se integrarán con el plugin Ask AI en v3.2.0 para habilitar respuestas contextuales basadas en funciones habilitadas.
Optimizaciones del Build Output
Beasties Desactivado — Por Qué?
Beasties estaba habilitado por defecto, extrayendo CSS "crítico" e inlineandolo en cada página HTML como tags <style>. El problema: Beasties no tiene conciencia del viewport — no usa un navegador headless. Simplemente empareja selectores CSS contra el DOM y clasifica cualquier regla que coincida con cualquier elemento como "crítica."
Con Tailwind CSS, casi cada clase de utilidad se usa en algún lugar de la página. Esto significa que Beasties inlineó casi todo el bundle CSS (~37 KB) en cada página. A través de 246 páginas, eso es 7.3 MB de CSS duplicado — 75x de bloat sobre el archivo CSS real de 99 KB.
Consideré dos alternativas:
-
Agregar inteligencia de viewport a Beasties — Esto requeriría ejecutar un navegador headless durante el build para determinar qué reglas CSS están realmente above-the-fold. Funciona, pero hace el build significativamente más lento (Beasties ya es el paso más lento del pipeline).
-
Desactivar Beasties completamente — Las páginas cargan CSS via un solo tag
<link>externo. El navegador lo cachea después de la primera carga. Sin tags<style>inlineados, sin CSS duplicado, sin ralentización del build.
Elegí la opción 2. El archivo CSS es solo 99 KB y se comprime bien con gzip. Los navegadores modernos manejan stylesheets externos eficientemente — la tasa de aciertos de caché entre páginas es excelente.
Diferencia en modo turbo: En modo --turbo, @bdocs/zig-critters (Zig/WASM) maneja la extracción de CSS crítico. Es órdenes de magnitud más rápido que Beasties y puede extraer inteligentemente solo el CSS verdaderamente crítico. Si necesitas inlining de CSS crítico para despliegues sensibles al rendimiento, usa --turbo.
Corrección de Locale Duplicado
Anteriormente, generateI18nFallbacks() creaba copias con prefijo de locale del contenido del locale por defecto. Para un sitio con locales en (por defecto) y es, cada página en inglés existía dos veces:
/docs/api/cli— el original/docs/en/api/cli— una copia idéntica
Esto resultó en 74 archivos HTML duplicados totalizando ~8 MB de espacio desperdiciado. La corrección omite la generación de rutas de fallback para el locale por defecto — su contenido ya existe a nivel raíz.
Resultados
| Métrica | Antes | Después | Ahorro |
|---|---|---|---|
| HTML output (total) | 25.4 MB | ~10.1 MB | ~15.3 MB (60%) |
| Tamaño por página (promedio) | ~217 KB | ~180 KB | ~37 KB por página |
| Páginas duplicadas | 74 | 0 | 74 archivos eliminados |
Otros detalles
- Visibilidad de tiempos de plugins — el build turbo ahora reporta tiempos por plugin en la salida del build, para que veas exactamente dónde se pasa el tiempo
- Sätteri lazy-loaded — el plugin Sätteri se importa dinámicamente en el primer uso, no al iniciar. Si no usas
--turbo, no hay sobrecarga - Separación de caché — Sätteri y el compilador MDX estándar usan namespaces de caché separados (
v6-fallbackvsv3). Cambiar entre modos turbo y no-turbo no corrompe los transforms cacheados - Fallback de Beasties — si el binario WASM de zig-critters no existe, Beasties toma el control con un warning. Tu build nunca falla por un binario faltante
crossoriginduplicado corregido — el regex que agregacrossorigina los links de stylesheet ahora evita duplicar el atributo cuando ya está presente- Integración con PostHog — soporte integrado para PostHog. Configura via
integrations.analytics.posthogcon tu clave API del proyecto, y el snippet de PostHog se inyecta automáticamente. Soporta nube de la UE, grabación de sesión y autocapture (desactivado por defecto)
Actualización
Sin breaking changes. La bandera --turbo es optativa — tu comando de build existente funciona exactamente igual.
Para probar el modo turbo:
pnpm boltdocs build --turbo
Si tienes problemas, elimina la bandera. El build estándar no cambia.
Qué Sigue
La Fase 2 de Nitro ya está en progreso:
- FileStore shardeado — reemplazando la caché monolítica de rutas con shards por archivo
- Caché por ruta + parches delta — cambiar un archivo no invalidará todas las rutas
- HMR delta de frontmatter — editar un título no recargará el navegador
- Worker threads para MDX — transforms MDX en paralelo entre núcleos del CPU
- Mapa de dependencias de código cliente — reconstruir solo las páginas afectadas por un cambio CSS
Instala o actualiza:
pnpm add boltdocs@latest
Revisa la documentación completa para explorar todo lo nuevo.