¿Cómo abrir un Excel de 300.000 filas en el navegador con React? office-engine lo carga sin backend ✅ yoDEV Tested

Sí: office-engine, una librería de React con licencia MIT, abre un XLSX de 300.000 filas en el navegador sin backend y muestra las primeras filas en unos 300 ms. Lo probamos con un archivo de 23 MB: también edita, guarda de vuelta en XLSX y abre DOCX y PPTX con el mismo componente.

:white_check_mark: yoDEV Tested · 3 de noviembre de 2026
Probamos office-engine 0.3.0 dentro de una app de React construida con Vite, en Chromium 153 en modo headless, sobre Linux en la nube con 2 vCPU. Usamos un XLSX propio de 300.000 filas por 12 columnas. Los resultados que reportamos como nuestros salen de esa prueba.

Al momento de publicar esta nota (3 de noviembre de 2026), la versión más reciente en npm es la 0.3.0. El paquete se creó el 2 de noviembre y publicó ocho versiones en sus primeras 28 horas, así que espera que la API y la lista de funciones sigan cambiando.

¿Qué es office-engine?

office-engine (@p10node/office-engine en npm) es un motor de documentos que funciona del lado del cliente para los tres formatos de Office Open XML: Word (DOCX), Excel (XLSX) y PowerPoint (PPTX). Se distribuye como componente de React, como hook, como función mount() sin framework, como web component y como un único script autocontenido. Su autor lo presentó en Hacker News como Show HN (item 50348361) con el titular “Open a 300k-row XLSX in the browser in ~300ms, no server”.

Lo interesante no es que abra archivos de Office, porque muchas herramientas lo hacen. Lo interesante es que lo hace sin subir el archivo a ningún servidor y sin congelar la pestaña mientras lo procesa.

¿Por qué un Excel muy pesado congela el navegador?

Un archivo XLSX es un ZIP de documentos XML, y la hoja de un libro grande puede ocupar decenas de megabytes de XML. Si lees el archivo completo, lo descomprimes y procesas todo ese XML en el hilo principal, la página deja de responder hasta que termina; y después intentas meter 3,6 millones de celdas en el DOM.

office-engine ataca cada uno de esos pasos:

  • Lectura perezosa del ZIP. Lee las entradas del archivo a medida que las necesita, en lugar de descomprimir todo al principio.
  • Peticiones HTTP Range. Cuando la fuente es una URL, descarga solo los rangos de bytes que necesita. Si el servidor no admite Range, recurre a descargar el archivo completo.
  • Parser XML en streaming dentro de un Web Worker. El procesamiento ocurre fuera del hilo principal, así que la interfaz sigue respondiendo mientras carga la hoja.
  • Vistas virtualizadas. Solo se renderizan las páginas, celdas o diapositivas visibles.
  • Guardado rápido. Al guardar, solo se regeneran las partes que editaste; el resto conserva sus bytes originales.

¿Cómo instalar office-engine en un proyecto de React?

Con un solo comando, y con React 18 o superior como dependencia peer:

bun add @p10node/office-engine   # peer: react >= 18, react-dom >= 18

El CSS se inyecta automáticamente. El único requisito de diseño es que el contenedor tenga una altura definida.

¿Cómo abrir un archivo XLSX en el navegador con React?

Importa DocViewer y pásale el archivo. src acepta un File, un Blob, un ArrayBuffer o un Uint8Array:

import { DocViewer } from '@p10node/office-engine'

<DocViewer src={file} style={{ height: 600 }} />

Si le pasas una URL, el componente carga el archivo con peticiones Range:

<DocViewer src="https://cdn.example.com/report.xlsx" />

Esa forma con URL es la que importa para archivos realmente grandes: el navegador no tiene que descargar el libro completo antes de mostrar las primeras filas.

Un visor de Excel en cinco minutos

La forma más rápida de verlo funcionar es un selector de archivos que entregue el File elegido directamente a DocViewer. El archivo nunca sale de la máquina del usuario:

import { useState } from 'react'
import { DocViewer } from '@p10node/office-engine'

export default function App() {
  const [file, setFile] = useState<File | null>(null)
  return (
    <>
      <input type="file" accept=".xlsx,.docx,.pptx"
        onChange={e => setFile(e.target.files?.[0] ?? null)} />
      {file && <DocViewer src={file} style={{ height: 600 }} />}
    </>
  )
}

Elige un libro grande y verás aparecer las primeras filas antes de que termine de cargar el resto. Así montamos nuestra app de prueba.

¿Qué tan rápido abre un Excel de 300.000 filas?

En nuestra prueba, las primeras filas aparecieron en pantalla entre 286 y 379 ms, en seis ejecuciones. Eso coincide con los unos 330 ms que reporta el autor. La carga completa fue más lenta que la suya: entre 4,3 y 8,4 segundos, frente a unos 2 segundos en su medición.

Prueba (XLSX de 23 MB, 300.000 filas × 12 columnas) Primeras filas Carga completa
Desde una URL (peticiones Range), 3 ejecuciones 301–379 ms 4,3–8,4 s
Desde un objeto File, 3 ejecuciones 286–306 ms 4,3–5,1 s
Medición del autor (Apple M-series) ~330 ms ~2 s

La diferencia en la carga completa es razonable: el autor midió en un equipo con Apple silicon y nosotros en una máquina Linux de 2 vCPU. Lo importante es que la hoja se puede usar mientras carga: a 1 segundo ya había 10.321 filas disponibles y a 3 segundos, 84.626.

También medimos si se congelaba la pestaña. Durante una carga completa, el hilo principal tuvo como máximo dos tareas largas, la más larga de 231 ms. Ese es el punto de usar un Web Worker.

Y comprobamos cuánto descarga antes de mostrar algo. Desde una URL, antes de las primeras filas solo bajó unos 0,57 MB: el índice del ZIP, que está al final del archivo, y los primeros 256 KB. Después transmitió la hoja en un solo rango. Para terminar la carga sí descarga el archivo completo; lo que evita es esperar a tenerlo todo para empezar a mostrarlo.

Los otros dos números del autor, un DOCX de 20.000 párrafos (2.073 páginas en unos 2 segundos) y un PPTX de 305 diapositivas, no los reprodujimos.

¿Se puede editar un Excel online y guardarlo como XLSX?

Sí, y sin servidor. Añade editable y un manejador onSave, que recibe el archivo editado como Blob junto con su nombre:

<DocViewer src={file} editable onSave={(blob, name) => upload(blob, name)} />

upload es tu propia función: envía el Blob a tu API o dispara una descarga. El editor tiene una barra de herramientas al estilo de Google Docs. En XLSX puedes editar celdas, fórmulas, formatos, bordes, filas, columnas y hojas; el motor de fórmulas implementa 134 funciones. En DOCX, texto, estilos, listas, imágenes y tablas. En PPTX, texto, formas, imágenes, diapositivas y un modo de presentación.

Lo probamos sobre el mismo archivo de 300.000 filas: editamos una celda, guardamos con Ctrl+S y onSave recibió el archivo unos 5 segundos después. Abrimos el resultado con openpyxl, una librería de Python independiente:

  • La edición estaba guardada.
  • Las 300.000 filas seguían completas.
  • Las fórmulas de la segunda hoja (SUM y AVERAGE sobre las 300.000 filas) seguían siendo fórmulas.
  • Al comparar las partes del ZIP con el original, solo había cambiado la hoja editada. Estilos, libro, la otra hoja y metadatos eran idénticos byte a byte. La promesa de “solo se regenera lo que editas” se cumple.

El motor también calculó esas fórmulas en el navegador: el promedio de 300.000 precios dio 499,450, el mismo valor que obtuvimos con Python.

El menú Archivo, además, crea documentos nuevos, abre CSV, texto, Markdown y HTML, importa CSV, exporta a PDF, HTML, texto o CSV e imprime. Eso no lo probamos.

¿office-engine o SheetJS?

Resuelven problemas distintos. SheetJS es una librería para procesar datos de hojas de cálculo: lee y escribe los formatos de Excel, pero no dibuja una interfaz. Su propia documentación la combina con componentes de grid de terceros, como React Data Grid, Handsontable o x-spreadsheet, para la parte visual. office-engine es el visor y el editor en un solo componente: abre el documento con su formato, te deja editarlo y lo guarda en el formato original.

Si lo que necesitas es leer los datos de un Excel en JavaScript para procesarlos, SheetJS sigue siendo la herramienta. Si necesitas que el usuario vea y edite el documento dentro de tu aplicación, office-engine te ahorra montar el grid. No comparamos el rendimiento de ambos.

¿Funciona sin React?

Sí. La carpeta dist/ incluye office-engine.embed.js, que empaqueta React y el worker, y expone un web component <office-viewer>:

<script src="office-engine.embed.js"></script>
<office-viewer src="/files/report.docx" style="height:600px"></office-viewer>

También hay una función mount() sin framework, documentada en la referencia de la API. Esta vía no la probamos. Como referencia de peso: nuestra app de prueba con React y office-engine quedó en un único archivo JavaScript de 947 KB, 318 KB con gzip.

¿La colaboración en tiempo real necesita servidor?

Sí, y es el único punto donde “sin backend” deja de ser cierto. Ver y editar funcionan por completo en el navegador. La edición multiusuario en vivo (cambios compartidos, avatares, cursores de los colaboradores y cambios sin conexión que se sincronizan al reconectar) necesita un hub que ordene los lotes de cambios, guarde el registro de operaciones y retransmita la presencia de cada usuario.

El proyecto incluye un hub de referencia, CollabHub, que se ejecuta con Bun y escucha en el puerto 8787. Guarda las salas en un directorio local (DATA) o en un bucket de S3 (S3_BUCKET). Puedes conectarlo a cualquier servidor WebSocket o implementar la interfaz Transport para tu propio backend. No usa Yjs: usa un esquema propio en el que cada cliente aplica sus cambios al instante y, si el hub ordenó antes el lote de otro colaborador, deshace los suyos y los vuelve a aplicar.

En el cliente es una prop más de DocViewer:

<DocViewer
  src={`https://hub.example.com/rooms/${id}/file?seq=${snapshot}`}
  editable
  collab={{ transport: 'wss://hub.example.com/collab', room: id, base: snapshot, user: { name: 'Ann' } }}
/>

base debe coincidir con el número de secuencia del archivo de src; si lo omites, el cliente vuelve a aplicar todo el historial de la sala. El README muestra una demo con tres usuarios, pero no probamos el hub y, al momento de publicar, nadie ajeno al proyecto había reportado haberlo ejecutado.

¿Qué no soporta office-engine?

El proyecto documenta sus carencias en una tabla de funciones. Al 3 de noviembre de 2026:

  • Sin soporte: los formatos binarios antiguos (.xls, .doc, .ppt) y los archivos cifrados.
  • XLSX: todavía no muestra gráficos, formato condicional ni imágenes. Las fórmulas no admiten nombres definidos, referencias estructuradas a tablas ni referencias 3D. No se pueden editar gráficos, tablas dinámicas, formatos condicionales, validación de datos ni filtros, y al insertar o borrar filas no se desplazan los formatos condicionales ni la validación de datos.
  • DOCX: faltan el cuerpo de las notas al pie, los gráficos, el ajuste exacto de objetos flotantes y los párrafos divididos entre páginas. Encabezados, pies de página, cuadros de texto, tablas anidadas y campos de varios párrafos, como una tabla de contenido, son de solo lectura.
  • PPTX: los gráficos aparecen como marcadores; faltan SmartArt, animaciones, transiciones y reproducción de video. No se puede editar el texto dentro de tablas ni insertar tablas, no se pueden rotar formas con el ratón y no se puede deshacer añadir, borrar o mover diapositivas.
  • Compatibilidad de navegadores: la documentación no publica una lista. El motor depende de la API nativa DecompressionStream y de Web Workers. Nosotros solo probamos Chromium.

¿Está listo para producción?

Trátalo como un proyecto muy joven. Tiene un único mantenedor identificable, que publica en npm como pierreneter; el repositorio no tiene releases etiquetadas en GitHub, y en aproximadamente un día salieron ocho versiones en npm. Tiene licencia MIT y se instala hoy, así que es fácil probarlo detrás de un feature flag.

Donde mejor encaja ahora es en una herramienta interna o un panel de administración donde los usuarios necesitan previsualizar hojas de cálculo grandes y prefieres no montar un servicio de conversión. Fija la versión exacta y revisa la tabla de funciones antes de depender de gráficos o del formato condicional.

Nuestro veredicto: en lo que probamos, cumple lo que promete. Las primeras filas llegan en el tiempo anunciado, la pestaña no se congela y el archivo guardado sale limpio. La carga completa depende mucho del hardware, y la colaboración en tiempo real es otro proyecto, con su propio servidor.


¿Y tú? ¿Cuál es el archivo de Excel más grande que has tenido que mostrar dentro de una aplicación web?

¿Cómo muestras hoy archivos de Office en tu aplicación?
  • Los convierto en el servidor (a PDF o HTML)
  • SheetJS más un componente de grid
  • Los envío a un visor externo (Google o Microsoft)
  • Prefiero otra opción (cuéntanos cuál)
0 votantes

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

Relacionado: MarkItDown: La Herramienta de Microsoft que Convierte Cualquier Documento en Contexto para tu IA