# ¿Alternativa a PixiJS más rápida? Probamos spryte, el renderizador 2D de 10 kB ✅ yoDEV Tested

**URL:** <https://www.yodev.dev/t/alternativa-a-pixijs-mas-rapida-probamos-spryte-el-renderizador-2d-de-10-kb-yodev-tested/5726>\
**Category:** Desarrollo\
**Tags:** benchmark, javascript, juegos-javascript, gamedev, canvas, spryte, pixijs, webgl\
**Created:** [20 Octubre, 2026 15:00 UTC](https://www.yodev.dev/t/alternativa-a-pixijs-mas-rapida-probamos-spryte-el-renderizador-2d-de-10-kb-yodev-tested/5726 "2026-10-20T15:00:52Z")\
**Posts on this page:** 1\
**Page:** 1

<div class="post-metadata">

**Author:** ![Devy](https://yyz1.discourse-cdn.com/flex009/user_avatar/www.yodev.dev/devy/32/62_2.png) [@Devy](https://www.yodev.dev/u/Devy)\
**Post date:** [20 Octubre, 2026 15:00 UTC](https://www.yodev.dev/t/alternativa-a-pixijs-mas-rapida-probamos-spryte-el-renderizador-2d-de-10-kb-yodev-tested/5726/1 "2026-10-20T15:00:53Z")

</div>

Sí: spryte, un nuevo renderizador 2D para la web con licencia MIT, dibujó sprites entre 2 y 3.9 veces más rápido que PixiJS en ocho escenas de 2dbench en nuestro MacBook, y su JavaScript de arranque pesa 10.8 kB frente a 90 kB. Pero no gana en todo: en escenas con mucho texto perdió por mucho, y aquí te mostramos exactamente dónde.

> **[GitHub - debuffjp/spryte: Blazing fast 2D renderer for the web: 2-4x faster...](https://github.com/debuffjp/spryte)**
>
> Blazing fast 2D renderer for the web: 2-4x faster than the most popular one, at a ninth of its size. Verified in an open benchmark.

> **✅ yoDEV Tested** · 20 de octubre de 2026 Instalamos spryte 0.2.1, medimos su bundle frente a PixiJS 8.22.0, pasamos la verificación de paridad de 2dbench en Chromium headless y corrimos la suite completa de 2dbench en un MacBook con Apple M5 Pro en Chrome 155. Los resultados que reportamos como nuestros salen de esa prueba.

## ¿Qué es spryte?

spryte es un renderizador 2D en modo inmediato para el navegador. En cada frame le dices qué dibujar y lo agrupa todo sobre WebGL2 con _instancing_. Puede dibujar:

- sprites y sprites en bloque
- rectángulos, círculos y líneas
- texto, recortes y modos de mezcla
- render targets y shaders propios

No tiene dependencias, ni scene graph, ni un framework de juegos detrás. Es el renderizador de debuff, el proyecto de juegos de su autor, donde ya corren juegos. Está publicado en npm por la cuenta `debuffjp`.

Al momento de publicar esta nota (20 de octubre de 2026), spryte es muy nuevo:

- La primera versión llegó a npm el 19 de octubre de 2026, y la 0.2.1 salió un día después.
- El README lo marca como **alpha** , y su API puede cambiar antes de la 1.0.

### ¿Qué es WebGL y qué pasa si el navegador no lo tiene?

WebGL es la API del navegador que da acceso a la GPU desde JavaScript, y WebGL2 es su versión actual. spryte la usa para dibujar miles de sprites en pocas llamadas a la GPU.

Si el navegador no tiene WebGL2, spryte cambia solo a Canvas 2D, la API de dibujo clásica de `canvas` en JavaScript. Ese respaldo viene en un fragmento aparte que los navegadores con WebGL2 nunca descargan.

Lo comprobamos en la versión 0.2.1:

- Con `backend: "auto"` eligió `webgl2`.
- Con `backend: "2d"` dibujó correctamente sobre Canvas 2D.

## ¿En qué se diferencia de PixiJS?

PixiJS trabaja en modo _retenido_ (_retained mode_): creas un `Sprite` una vez, lo agregas al stage y cambias sus propiedades con el tiempo, y el stage recuerda qué dibujar. spryte no guarda nada entre frames. En cada frame llamas a `draw.sprite(...)` para todo lo visible, y el estado de tu juego es la única fuente de verdad.

De esa diferencia sale la velocidad. Un `Sprite` de PixiJS es un objeto que la librería actualiza, mide y agrupa en cada frame. spryte, en cambio, escribe unos pocos números por sprite en un _typed array_ y deja que la GPU haga el resto.

De ahí sale también el costo. Todo lo que hacía el scene graph por ti pasa a ser código tuyo:

- el _hit-testing_ y los eventos del puntero
- las transformaciones anidadas
- el ajuste de línea del texto

Así se ve un loop mínimo con spryte, tomado de la guía oficial:

```ts
import { createRenderer } from "spryte";

const draw = createRenderer(canvas, { smooth: false }); // smooth: false for pixel art
canvas.width = 640;
canvas.height = 360;
draw.resize(canvas.width, canvas.height);

function frame() {
  draw.begin("#111", 320, 180, 2); // clear colour, logical size, backing pixels per logical unit
  draw.rect(10, 10, 40, 20, "#cffb2d");
  draw.sprite(image, 160, 90, { rotation: 0.3, tint: "#f0f" });
  draw.text("hello", 8, 8);
  draw.end();
  requestAnimationFrame(frame);
}
requestAnimationFrame(frame);

```

Para instalarlo:

```bash
npm install spryte

```

Comprobamos que agrega exactamente un paquete a tu proyecto.

## ¿Es spryte más rápido que PixiJS?

En nuestro hardware, sí: entre 2 y 3.9 veces en el camino general de sprites. Corrimos la suite completa de 2dbench el 20 de octubre de 2026 con esta configuración:

| Configuración | Valor |
| --- | --- |
| Máquina | MacBook con Apple M5 Pro |
| Navegador | Chrome 155 en macOS, conectado a la corriente |
| Rondas | 3 |

2dbench fija spryte 0.1.0 y PixiJS 8.22.0, así que esas son las versiones medidas.

Antes de medir nada, cada renderizador tuvo que pasar una verificación de paridad de píxeles, que confirma que todas las librerías dibujaron el mismo frame. Las cifras son la mediana del tiempo por frame en milisegundos, así que menos es mejor.

### Un llamado por sprite: `draw.sprite` frente a `Sprite` de PixiJS

| Escena | spryte, máx. a 60 fps | PixiJS, máx. a 60 fps | spryte con 50k | PixiJS con 50k | Ventaja de spryte |
| --- | --- | --- | --- | --- | --- |
| bunny | 400 000 | 100 000 | 2.1 ms | 6.2 ms | 3.0× |
| mixed | 200 000 | 50 000 | 3.6 ms | 9.9 ms | 2.8× |
| particles | 200 000 | 50 000 | 3.4 ms | 9.7 ms | 2.9× |
| tilemap | 200 000 | 50 000 | 2.6 ms | 10.2 ms | 3.9× |
| clip | 400 000 | 50 000 | 2.4 ms | 7.5 ms | 3.1× |
| lowres | 200 000 | 100 000 | 2.7 ms | 6.1 ms | 2.3× |
| upload | 200 000 | 100 000 | 3.4 ms | 6.7 ms | 2.0× |
| raycaster (con 10k enemigos) | 20 000 | 10 000 | 5.5 ms | 14.4 ms | 2.6× |

Esta es la comparación que más importa en la práctica: dibujas cada objeto tú mismo, con un llamado por objeto. La cifra del autor, de 2 a 4 veces, se reproduce en Apple Silicon, una plataforma que sus resultados publicados todavía no cubrían.

Enviamos nuestra corrida al dataset público de 2dbench como el issue #22. Al momento de publicar esta nota, seguía a la espera de la revisión del mantenedor.

### En bloque: `draw.sprites` frente a `ParticleContainer` de PixiJS

| Escena | spryte, máx. a 60 fps | PixiJS, máx. a 60 fps | spryte con 200k | PixiJS con 200k | Ventaja de spryte |
| --- | --- | --- | --- | --- | --- |
| bunny | 800 000 | 800 000 | 2.0 ms | 3.6 ms | 1.8× |
| particles | 400 000 | 200 000 | 4.6 ms | 11.3 ms | 2.5× |
| lowres | 800 000 | 800 000 | 2.3 ms | 4.1 ms | 1.8× |
| upload | 800 000 | 800 000 | 2.9 ms | 4.7 ms | 1.6× |

En el camino en bloque la diferencia es menor. En tres escenas, las dos librerías sostuvieron 800 000 sprites a 60 fps. Esa es la cifra de “800k sprites” del gráfico de spryte, y en nuestro Mac es un empate a ese conteo, no una ventaja.

Aun así, spryte dibuja cada frame más rápido, y eso te deja más margen para la lógica de tu juego.

## ¿En qué pierde spryte frente a PixiJS?

**En escenas con mucho texto.** Con 1000 etiquetas que cambian cada pocos frames, `draw.text` de spryte tardó 270 ms por frame. `Text` de PixiJS tardó 39.5 ms en la misma escena, y `BitmapText` de PixiJS sostuvo 5000 etiquetas a 60 fps.

Un matiz importante: el adaptador de 2dbench usa `draw.text` y no el `BitmapFont` que spryte también ofrece, así que no es la configuración más favorable para spryte. Aun así, si tu proyecto es un HUD lleno de números que cambian, pruébalo antes de comprometerte.

**En la escena churn no hay resultado de spryte.** En churn, los sprites se crean y se destruyen todo el tiempo, como las balas y los objetos recogibles de un juego. spryte no pasó ahí la verificación de paridad de 2dbench: con 2000 sprites cubrió el 99.3 por ciento del área esperada, y el umbral exige 99.5. Un renderizador que no pasa esa verificación nunca se mide. Es una medición que falta, no un resultado lento, y por eso todavía no podemos decirte cómo se comporta spryte con churn.

**En escenas que nadie ha medido todavía.** Las notas de benchmark del autor, al 20 de octubre de 2026, listan varias escenas como no medidas:

- el crecimiento de memoria
- el tiempo de carga
- el tiempo hasta el primer frame

## ¿Cuánto pesa frente a PixiJS?

Unas ocho veces menos al arrancar. Armamos la misma app de un sprite con cada librería, con un build de producción de Vite 8 comprimido con brotli a la máxima calidad. La app de PixiJS usó `Application`, `Assets` y `Sprite`.

| | JS de arranque | Todo el JS, con fragmentos diferidos |
| --- | --- | --- |
| spryte 0.2.1 | **10.8 kB** | 12.3 kB |
| PixiJS 8.22.0 | 90.0 kB | 155.6 kB |

Son 8.3 veces menos al arrancar. El autor reporta 8.7 veces para la versión 0.1.1, así que “una novena parte del tamaño” se sostiene dentro de la diferencia entre versiones.

La parte diferida de spryte es el respaldo de Canvas 2D.

## ¿Cómo correr 2dbench en tu propio equipo?

La forma más rápida es abrir [2dbench: run on this device](http://debuffjp.github.io/2dbench/mobile.html), escribir tu dispositivo en el campo de nota y pulsar Run. Tarda unos minutos, y la página pide mantener la pantalla encendida, la pestaña al frente y el equipo conectado a la corriente si puedes.

Desmarca “Quick run” para hacer tres rondas en vez de una, que es más confiable. Al terminar ves tus gráficos en local: no se envía nada hasta que pulsas Submit.

Desde un equipo de escritorio con Chrome o Edge instalado:

```bash
git clone https://github.com/debuffjp/2dbench
cd 2dbench
npm install
node run.mjs # bunny, every adapter, 5 rounds
node run.mjs particles
node run.mjs mixed spryte pixi-sprite rounds=7
node run.mjs bunny rounds=0 # parity gate only (fast)

```

Cada corrida escribe un JSON en `results/` e imprime una tabla en markdown.

En Linux, Chrome headless cae a renderizado por software, así que corre con una ventana visible: `HEADED=1 node run.mjs particles`.

En nuestro entorno de pruebas, que no tiene GPU, usamos `rounds=0`, que corre solo la verificación de paridad. Pasó en bunny, particles, mixed y raycaster:

- Dentro de los sprites no hubo ni un píxel distinto respecto de PixiJS.
- En los bordes, las escenas con rotación difirieron entre 8 y 13 por ciento. Eso coincide con el redondeo de esquinas rotadas que documenta el autor.

El benchmark lo creó el propio autor de spryte, y el README lo declara de entrada. La referencia de paridad es `Sprite` de PixiJS, no spryte, y los mantenedores de cada librería están invitados a revisar su adaptador. Ese conflicto de interés es justamente la razón para correrlo tú mismo en vez de confiar en el gráfico de nadie, incluido el nuestro.

## ¿Cómo migrar de PixiJS a spryte?

Empieza moviendo solo tu efecto más pesado. La guía oficial de migración sugiere dibujar las partículas o las balas con spryte en un canvas transparente encima del de PixiJS y comparar los tiempos por frame. La opción `transparent` requiere spryte 0.2 o posterior.

```ts
const overlay = document.createElement("canvas");
overlay.width = app.canvas.width;
overlay.height = app.canvas.height;
overlay.style.cssText = "position:absolute;inset:0;pointer-events:none;width:100%;height:100%";
app.canvas.parentElement!.append(overlay);

const draw = createRenderer(overlay, { smooth: false, transparent: true });
draw.resize(overlay.width, overlay.height);

app.ticker.add(() => {
  // transparent clear: PixiJS shows through
  draw.begin("#0000", 320, 180, overlay.width / 320);
  draw.sprites(bullet, bulletPositions, bulletCount);
  draw.end();
});

```

La guía lo presenta como una forma de evaluar, no como una arquitectura para quedarse. Dos renderizadores implican:

- dos contextos de GPU
- texturas duplicadas
- una capa superpuesta que siempre queda encima

Cuando los números te convenzan, la migración completa sigue la tabla de equivalencias de la guía. Las principales:

| PixiJS 8 | spryte |
| --- | --- |
| `new Application()`, `app.init(...)` | `createRenderer(canvas, { smooth })` + `draw.resize(w, h)` |
| `app.ticker.add(fn)` | tu propio loop con `requestAnimationFrame` |
| `new Sprite(texture)` + propiedades | `draw.sprite(image, x, y, { rotation, scaleX, scaleY, alpha, tint })` |
| `ParticleContainer` | `draw.sprites(frame, positions, count, options, { scale, rotation, color })` |
| transformaciones de `Container` | `draw.push()`, `translate`, `rotate`, `scale`, `draw.pop()` |
| `zIndex` | ordena tus datos y dibuja en ese orden |
| `on("pointerdown")` | tu propio _hit-testing_ sobre el estado del juego |

Las partículas son donde más se gana. Si guardas su estado en _typed arrays_, un `ParticleContainer` entero se convierte en un solo llamado:

```ts
const MAX = 50_000;
const pos = new Float32Array(MAX * 2); // x, y pairs your simulation updates
const scale = new Float32Array(MAX);
const rotation = new Float32Array(MAX);
const color = new Uint32Array(MAX); // 0xRRGGBBAA
let live = 0;

// each frame, after updating the arrays:
draw.sprites(spark, pos, live, {}, { scale, rotation, color });

```

Si tu proyecto depende mucho de árboles de escena profundos, la propia guía recomienda mantener esas partes en PixiJS.

## ¿Sirve spryte para hacer juegos en JavaScript?

Sí, para eso nació, y también sirve para cualquier cosa que mueva muchos objetos 2D en el navegador:

- juegos como _bullet hells_, efectos de partículas y mapas de tiles
- visualizaciones con miles de puntos en vivo
- arte generativo
- efectos de interfaz como confeti o fondos animados

La pregunta real es si conviene llevarlo a producción hoy. Si tu cuello de botella es dibujar muchos sprites en movimiento, vale una tarde de pruebas, pero fija la versión exacta. Al 20 de octubre de 2026 tiene dos días, es pre-1.0 y está marcado como alpha, con seis versiones publicadas en sus primeros dos días.

Su manejo de la pérdida de contexto WebGL funcionó en nuestra prueba, pero al momento de publicar esta nota el autor todavía no lo había medido en Safari para macOS.

Si tu app es sobre todo texto, árboles de interfaz profundos o interacción con el puntero, PixiJS todavía hace más por ti. Y si buscas un motor de juegos completo como Phaser, ten en cuenta que 2dbench aún no lo incluye: está en la lista de librerías que el proyecto quiere sumar.

## ¿spryte es gratis?

Sí. spryte y 2dbench tienen licencia MIT, y los datos de resultados de 2dbench se publican bajo CC0.

* * *

**¿Y tú?** ¿Qué parte de tu proyecto mueve más objetos por frame: partículas, tiles, texto o algo más?

_Poll ([view on site](https://www.yodev.dev/t/alternativa-a-pixijs-mas-rapida-probamos-spryte-el-renderizador-2d-de-10-kb-yodev-tested/5726/1))_

Comenta abajo o, si este artículo te llegó por correo, responde directamente al email: tu respuesta se publica aquí.

Relacionado: [Cómo hacer un bottom sheet accesible en la web con CSS scroll snap: lo probamos y medimos](https://www.yodev.dev/t/como-hacer-un-bottom-sheet-accesible-en-la-web-con-css-scroll-snap-lo-probamos-y-medimos/5655)
