He publicado tres librerías open source (y dos son de Excel)
He publicado tres librerías en npm. Dos atacan el problema de Excel desde frentes distintos — sheet-lite lee, edita y escribe archivos .xlsx sin destruir lo que no tocas, y excel-clipboard-paste convierte lo que pegas desde Excel o Google Sheets en una matriz con la que puedes trabajar. La tercera, nprogress-next, es un reemplazo moderno de NProgress, que no se actualiza desde 2015.
Las tres comparten filosofía: TypeScript, licencia MIT, cero dependencias (o una sola, en el caso de sheet-lite) y CI con presupuesto de tamaño en cada push.
Vamos por partes, de la más importante a la más anecdótica.
sheet-lite: edita un Excel sin romperlo
El problema que me llevó a escribirla es de sobra conocido: cuando abres un Excel, cambias una celda y guardas, la mayoría de librerías reconstruyen el archivo entero. Y en ese proceso se pueden perder por el camino validaciones de datos, formato condicional, imágenes... sin avisar. La primera vez que te pasa, dejas de fiarte de ninguna librería.
sheet-lite hace lo contrario: solo reescribe lo que has cambiado. El resto del paquete OOXML queda byte a byte idéntico. Y si no cambias nada, te devuelve los bytes originales tal cual.
import { Workbook } from 'sheet-lite'
const wb = await Workbook.readFile('./informe.xlsx')
const ws = wb.getWorksheet('Ventas')!
// solo estas celdas se reescriben
ws.getCell('B2').value = 1234.56
ws.getCell('B2').numFmt = '#,##0.00'
ws.getCell('A1').font = { bold: true }
ws.mergeCells('C1:D1')
await wb.writeFile('./informe-editado.xlsx')
// validaciones, formato condicional, imágenes... intactos
La API está inspirada en ExcelJS, así que si vienes de ahí te va a resultar familiar: getCell, addRow, mergeCells, fuentes, rellenos, bordes, alineación, texto enriquecido, hojas nuevas, anchos de columna, filas congeladas...
Los números
Generé un libro de 5000 × 8 celdas con ExcelJS y lo leí con las tres:
| Librería | Lectura (mediana) | Tamaño publicado (gzip) | Deps transitivas |
|---|---|---|---|
| sheet-lite | 149 ms | ~30 kB | 0 |
| ExcelJS | 192 ms | ~250 kB | 9 |
| SheetJS | 218 ms | ~136 kB | 7 |
El tamaño es engañoso a la hora de comparar: las ~30 kB incluyen la única dependencia directa (fflate, para el ZIP). Para archivos grandes hay un modo aparte, sheet-lite/stream, que lee fila a fila con memoria acotada: una hoja de 100 000 × 8 celdas se procesa con ~10 MB de heap en lugar de los ~673 MB de la lectura en memoria.
También trae adaptadores de navegador (readBlob / toBlob / download) y límites de seguridad por diseño: path traversal, número de entradas del ZIP, tamaño y ratio de compresión.
Como toda v0 honesta, no lo hace todo: no evalúa fórmulas, no crea gráficos ni tablas (los preserva, que es la gracia) y no soporta .xls ni CSV. La lista completa de limitaciones está en el README, a la vista de todos.
excel-clipboard-paste: del portapapeles a datos limpios
Cuando copias un rango en Excel o Google Sheets, el navegador recibe texto separado por tabuladores y saltos de línea. excel-clipboard-paste lo convierte en string[][], es decir, en algo que puedes iterar, validar y guardar:
import { parseClipboard } from 'excel-clipboard-paste'
document.querySelector('textarea')?.addEventListener('paste', (event) => {
event.preventDefault()
const rows = parseClipboard(event, { trim: true, rectangular: true })
// [["Ana", "25"], ["Luis", "31"]]
})
Lo interesante está en los detalles:
- Opciones encadenadas:
trim,dropEmptyRows,dropEmptyColumns,rectangular(iguala las filas cortas) ymaxRows. preferHtml: si el origen también manda una<table>entext/html(concolspan/rowspanexpandidos), la prefiere; si no hay tabla, cae al texto plano.toObjects():[["Nombre", "Edad"], ["Ana", "25"]]pasa a objetos usando la primera fila como cabecera.coerceMatrix()es europeo-friendly: convierte"1,234"en1234solo cuando los grupos de miles son consistentes; un decimal como"1,5"no acaba convertido en15.- Normaliza los finales de línea de Windows y del Mac clásico, ignora el BOM y no te inventa una fila fantasma por el salto de línea final.
Pesa ~2,8 kB gzip, no tiene dependencias y el repo incluye un playground interactivo para probarlo con pegados reales:

nprogress-next: NProgress por fin en TypeScript
Esta es la más sencilla de contar. NProgress está en millones de proyectos, y su última versión estable (0.2.0) es de 2015. Diez años sin una release, con la API que todos conocemos (start, done, set, inc, configure...).
nprogress-next mantiene esa misma API — migrar es, en la mayoría de los casos, cambiar el import — y la reconstruye con tipos, sin dependencias y en ~3 kB gzip: ESM + CJS + UMD, SSR-safe (Next, Nuxt, Astro), accesible (role="progressbar", aria-valuenow, respeta prefers-reduced-motion) y themable con variables CSS (--np-color, --np-height...).
import NProgress from 'nprogress-next'
NProgress.configure({ showSpinner: false })
NProgress.start()
// ... navegación
NProgress.done()
Si prefieres componentes, hay dos adaptadores oficiales publicados: nprogress-next-react y nprogress-next-vue, ambos con <ProgressBar /> y useProgress().
Tiene documentación propia con ejemplos en vanilla, React, Vue y Astro. Y por supuesto, es un homenaje al trabajo original de Rico Sta. Cruz: misma licencia MIT y crédito preservado en el LICENSE.
Y sí: la barra verde que aparece arriba mientras lees esto es esta librería, siguiendo el scroll del artículo en esta misma web.
Cómo las he construido (spoiler: con agentes de IA)
Estas tres librerías no las he tecleado línea a línea: las he construido con un flujo de desarrollo automatizado con IA. Pero no consiste en pedir "hazme una librería de Excel" y publicar lo que salga. El flujo tiene forma de ingeniería de siempre:
- Primero la especificación: cada repo nace con su plan por escrito (
PLAN.md,ROADMAP.md,docs/STATUS.md) que define qué soporta, qué no y por qué, antes de generar código. - Fases pequeñas y verificables: nprogress-next se construyó en seis fases (core, CSS y a11y, adaptadores, tests y CI, docs y publicación). Ninguna fase avanza sin tests en verde.
- Gates en CI, no en la fe: typecheck, tests, build,
npm packy presupuesto de tamaño — si el bundle crece sin motivo, el build falla. - Publicación con provenance: los tres paquetes se publican desde GitHub Actions con atestados de procedencia verificables en npm.
- Contraste contra la realidad: sheet-lite usa ExcelJS y SheetJS como devDependencies solo para generar fixtures y cruzar resultados en los tests; nunca viajan dentro del paquete publicado.
La IA escribió la mayor parte del código; las decisiones difíciles fueron humanas: qué preservar byte a byte, qué no soportar (y documentarlo en una lista honesta de limitaciones) y qué compromisos son aceptables en una v0. Ese es el verdadero trabajo cuando automatizas: definir bien el problema.
Enlaces
- sheet-lite → GitHub · npm
- excel-clipboard-paste → GitHub · npm
- nprogress-next → GitHub · npm · docs · React · Vue
Si trabajas con Excel en la web, las dos primeras te pueden ahorrar horas de dolor. Y si te sirven, una estrella en GitHub ayuda más de lo que parece; si encuentras un caso que no cubren, los issues están abiertos.