Cada número de esta página se midió, no se estimó. Salvo que una tabla diga lo contrario, la máquina era un Apple M2 Max, 32 GB de RAM, macOS 26.6.2. Nada de esto es una comparación con otra herramienta.
El fixture detrás de la mayor parte es next16_framework_runtime: 185 KB del runtime del framework que publica un build real de Next.js 16. Es un único bundle de producción ya minificado, que es la forma de código sobre la que AfterPack se ejecuta realmente.
Tiempo de build
Medido el 2026-09-29, en la máquina indicada arriba, con AfterPack 0.2.0 en el preset light por defecto.
| Qué se ejecutó | Entrada | Tiempo | Rendimiento |
|---|---|---|---|
| El paquete npm, sobre el bundle de 185 KB | 185 KB | 229 ms | 0.79 MB/s |
| El motor por sí solo, mismo bundle | 185 KB | 243 ms | 0.74 MB/s |
| El paquete npm, sobre un build de varios archivos de 766 KB | 766 KB | 1,362 ms | 0.55 MB/s |
La fila de npm es la que debes usar para planificar. Es el paquete publicado haciendo el trabajo igual que lo hace un plugin o npx afterpack@latest, así que incluye el coste de llevar tu código al motor y sacarlo de vuelta. La fila del motor es el mismo bundle con el mismo preset sin ese coste, cronometrado con un arnés de medición aparte. Las dos quedan a menos de 15 ms una de otra, así que el empaquetado no añade un coste medible.
El pico de memoria en la fila del motor fue de 20.8 MB por encima de la base para un único archivo de 185 KB. La ejecución de varios archivos de 766 KB llegó a 76 MB en su punto máximo.
La ofuscación es un paso posterior al build, así que este tiempo se suma a tu build, no a la carga de página de tus usuarios. Un build de 766 KB en aproximadamente 1.4 segundos es el orden de magnitud del coste con el preset por defecto; un preset más alto cuesta más.
El build wasm
@afterpack/wasm es el mismo motor compilado a WebAssembly, para un Cloudflare Worker, para Node y para el playground de este sitio.
| Tiempo, por preset | Node 24 |
|---|---|
Bundle de 110 KB, light | 147 ms |
Bundle de 185 KB, light | 237 ms |
Bundle de 185 KB, medium | 1,011 ms |
Bundle de 185 KB, extreme | 2,603 ms |
Cada tiempo es la mediana de nueve ejecuciones con el Protection Map activado, medida el 2026-10-17 con @afterpack/wasm 0.2.6 en la máquina indicada arriba. El bundle de 110 KB es el chunk de polyfills del mismo build de Next.js 16.
La descarga ocupa 4.36 MiB sin comprimir y 1.25 MiB con gzip. Ocurre una vez por isolate de Worker o por pestaña del navegador, no una vez por build.
La velocidad se hace cumplir: una comprobación de CI cronometra el motor sobre el fixture de 185 KB con el preset extreme y el Protection Map activado, junto a un motor de referencia fijado en la misma ejecución, y hace fallar el build si la ejecución más rápida del motor tarda más de 13.5 veces lo que tarda la de la referencia.
Wasm es más lento que el build nativo, y su velocidad es una concesión deliberada: un build anterior optimizado para tamaño salía un 39% más pequeño con gzip y 2.1x más lento, lo que llevó un build real de 66 archivos más allá del plazo límite del motor en la nube. Ganó la velocidad.
Son tiempos de un portátil, no de Cloudflare. Un isolate de Worker en la red de Cloudflare tiene menos CPU, una caché más fría y un límite de CPU por petición, así que la misma entrada tarda más allí de lo que dice esta tabla. Mide en la plataforma en la que vas a ejecutarlo antes de dimensionar un presupuesto con estos números.
Tamaño de salida
La ofuscación añade bytes. Medido el 2026-10-16 con AfterPack 0.2.6, sobre cinco fixtures (el runtime de 185 KB de arriba, otros dos chunks de Next.js 16, un bundle de React con Vite y un chunk de PostHog), por preset, con la salida comprimida con gzip frente al mismo archivo minificado:
| Preset | Multiplicador de la salida con gzip |
|---|---|
minify | de 1.09x a 1.17x |
light | de 1.29x a 1.60x |
medium | de 6.04x a 8.33x |
hard | de 6.62x a 9.23x |
extreme | de 8.25x a 11.19x |
Cada rango es la dispersión entre los fixtures, no un intervalo de confianza, y aumenta de forma monótona con el preset.
El objetivo de complejidad fija el tamaño de salida; estos rangos son mediciones de lo que produjo cada preset. Establece un inflation.max explícito cuando quieras que un build falle en lugar de superar un tamaño que elijas; consulta Presets.
Los archivos pequeños salen proporcionalmente más grandes que cualquiera de estos valores, porque toda salida lleva la sobrecarga fija del runtime del motor. Mide la proporción sobre un bundle real.
Carga de página
Un preset más pesado hace que una página tarde más en arrancar, porque el navegador analiza y ejecuta más código antes de que la página responda. Medido el 2026-10-24 con AfterPack 1.0.0, en la máquina indicada arriba, en Chromium headless: cinco apps pequeñas de los tests de extremo a extremo de los plugins de AfterPack, cada una construida una vez sin AfterPack y una vez por preset con todo el bundle en ese preset, y servida desde localhost, así que no se incluye tiempo de red. Cada cifra es el tiempo desde la navegación hasta el primer clic sobre el contador de la app que lo cambia, la mediana de cinco cargas en frío, cada una en un contexto de navegador nuevo.
| App | Sin AfterPack | light | medium | hard | extreme |
|---|---|---|---|---|---|
| Vite y React | 35 ms | 52 ms | 253 ms | 295 ms | 596 ms |
| Vue sobre Vite | 31 ms | 36 ms | 176 ms | 117 ms | 199 ms |
| Islas de Astro | 44 ms | 48 ms | 205 ms | 249 ms | 622 ms |
| SvelteKit | 27 ms | 32 ms | 84 ms | 89 ms | 162 ms |
| Next.js, webpack | 42 ms | 74 ms | 462 ms | 573 ms | 1,010 ms |
| Next.js, webpack, CPU limitada 4x | 145 ms | 234 ms | 1,652 ms | 2,215 ms | 3,844 ms |
La última fila hace la CPU de Chromium cuatro veces más lenta, una aproximación a un móvil de gama media.
Sin protección, las páginas cargan de 168 KB a 453 KB de JavaScript. El tamaño crece aproximadamente en el mismo factor en todas las apps (las proporciones están en Presets); el tiempo de arranque crece según cuánto de ese código se ejecuta antes del primer clic. El tiempo de script en el hilo principal en medium fue 4.5x el del build sin proteger en Vue y 14.7x en Next.js. El runtime del propio framework forma parte de cada bundle, y todos los presets también lo protegen.
En light, el primer clic que funciona llegó de 4 ms a 32 ms más tarde. A partir de medium, mide tus propias páginas antes de publicar el preset en todo el bundle; lo que cada nivel te permite acotar está en Presets.
Coste en tiempo de ejecución
El código protegido se ejecuta más despacio que el original, y el coste sube con el preset. Medido con AfterPack 0.2.4 en el runner de CI x86_64 autoalojado, Node 22: cuatro programas de bucles cerrados; cada cifra es el tiempo de ejecución protegido dividido por el del original, la mediana de los cuatro.
| Preset | Tiempo de ejecución frente al original |
|---|---|
minify | 1.0x |
light | 2.1x |
medium | 32.5x |
hard | 35.0x |
extreme | 37.3x |
Son el peor caso: los bucles no hacen más que aritmética protegida, y el código de una aplicación normal pasa mucho menos tiempo en bucles así. Una comprobación de CI hace fallar el motor si la mediana de un preset supera 2.5 veces su cifra de aquí.
Un núcleo numérico caliente, como un filtro de imagen, un paso de física o el bucle interno de un parser, paga casi la cifra completa. Con una clave Pro, mantenlo en light con un preset de región y deja el resto del bundle en tu preset global. Un build Free ignora un preset de región más bajo, así que en Free mantén el preset global en light cuando importe un núcleo caliente.
Lecturas de globales del host
El código protegido lee una variable global del host, como URL, a través de una comprobación que lanza el mismo ReferenceError que tu código original cuando esa global no existe. Lo que cuesta la comprobación depende de dónde se ejecuta el código.
Medido el 2026-10-13 con AfterPack 0.2.4, en Node 24 sobre un Mac arm64, con un bucle que lee URL una vez por iteración. Cada cifra es el tiempo de ejecución del build protegido dividido entre el del mismo build protegido leyendo la global sin la comprobación. Un rango abarca dos semillas, cada una la más rápida de 5 a 7 rondas intercaladas.
| Preset | Contexto ordinario | Dentro de node:vm |
|---|---|---|
light | 1.00x | 2.7x |
medium | de 1.06x a 1.13x | de 2.0x a 2.1x |
hard | de 1.04x a 1.05x | de 1.9x a 2.1x |
extreme | de 1.10x a 1.18x | de 2.0x a 2.1x |
Un contexto ordinario es una página del navegador, un worker o el contexto principal de Node; esta columna se midió en un worker thread de Node. Ahí la comprobación no cuesta nada medible en light. A partir de medium, la protección añadida del preset envuelve la comprobación, y eso se paga en cada lectura.
Un contexto node:vm pasa cada búsqueda en su objeto global por un callback, así que ahí el mismo bucle tarda de 1.9x a 2.7x lo que tarda sin la comprobación. Un test o benchmark que ejecuta código protegido dentro de node:vm ve este coste en su límite superior, así que mide el código que lee globales del host en un bucle caliente donde lo ejecutan tus usuarios.
Caché entre releases
Una semilla nueva cambia los bytes de cada chunk protegido, incluidos los chunks cuyo código fuente no cambió. Los plugins de bundler incorporan la semilla al nombre de archivo de cada chunk, así que tras un release los visitantes que vuelven descargan de nuevo todo el JavaScript protegido. Una semilla fija mantiene un chunk sin cambios idéntico byte a byte y en caché, y ese chunk conserva entonces su forma entre releases. Con salida de Next.js, Angular, Vite o webpack, la CLI renombra los archivos con hash de contenido igual que los plugins; con cualquier otra salida los nombres se mantienen, así que fija seed o da a esa salida una vida de caché corta. Consulta Nombres de archivo y caché.
Siguiente
- Presets: el presupuesto de tamaño que fija cada preset y lo que cuesta subirlo.
- Build y CI: dónde encaja el paso en un pipeline.
- Cloudflare Workers: ejecutar el build wasm en un isolate.
- Playground: el build wasm, ejecutándose en tu navegador y cronometrándose a sí mismo.