xlsx-fire

Blazing fast Excel (.xlsx) parser powered by Rust + WebAssembly. Lightweight, works in React, Vue, and plain JS frontends.
5,506 14
Install
npm install xlsx-fire
Latest Version:1.0.0
License:MIT
Last Updated:Aug 24, 2025
Links: GitHub  ·  npm
Maintainer: bunvader

npm version License: MIT

⚡ xlsx-fire

WASM beast (Rust-powered) to kill your SheetJS freezes

Stream and parse huge Excel files directly in the browser — without blocking the UI.
Built with Rust + WebAssembly, streaming ZIP + SAX XML parsing.
Async. Yield. Streams. No workers required.


📦 Installation

npm install xlsx-fire

🚀 Why?

Parsing .xlsx in JS with libraries like SheetJS often means:

  • Loading the whole 100 MB file into memory
  • Blocking the main thread
  • Tabs freezing, fans spinning

xlsx-fire does it differently:

  • ✅ Streams ZIP entries (no inflate-to-Vec)
  • ✅ Async + cooperative yielding — browser paints while parsing
  • ✅ Batch-based parsing (rows in chunks)
  • ✅ Memory stays flat, UI stays responsive

🎯 Try It Yourself

👉 Live Demo: https://shyam20001.github.io/xlsx-fire/


🧪 Benchmarks (100 MB .xlsx, 4 sheets, Chromium, batch = 500)

Library File size Batch rows First batch Next batches Rows/sec (avg) Notes
SheetJS (pure JS) 100 MB n/a ❌ froze tab ❌ froze tab ~0 Blocks UI, crashes beyond ~40 MB
xlsx-fire (Rust+WASM) 100 MB 500 5757 ms 2–3 s ~170–240 rows/s Smooth, async, UI usable

Log sample:

[1:00:14 PM] Batch: +500 rows (start=1)   | next=500  | 5757.5 ms
[1:00:19 PM] Batch: +500 rows (start=501) | next=1000 | 2571.4 ms
[1:00:24 PM] Batch: +500 rows (start=1001)| next=1500 | 3055.3 ms
...

👉 On the same file where SheetJS hangs the browser, xlsx-fire streams rows smoothly.


⚡ Quick Start Examples

🌐 Vanilla JavaScript

import init, { list_sheets, xlsx_batch_async } from "xlsx-fire/sheetx.js";

await init();

const file = document.querySelector("input[type=file]").files[0];
const bytes = new Uint8Array(await file.arrayBuffer());

// List sheets
const { sheets } = list_sheets(bytes);

// Parse first 500 rows
const res = await xlsx_batch_async(bytes, sheets[0], 0, 500);

console.log(res.rows);

⚛️ React Example

import { useEffect, useRef, useState } from "react";

export default function XlsxFireDemo() {
  const wasmReadyRef = useRef(false);
  const listSheetsRef = useRef(null);
  const batchAsyncRef = useRef(null);

  const [status, setStatus] = useState("loading");
  const [rows, setRows] = useState([]);

  useEffect(() => {
    (async () => {
      try {
        const mod = await import("xlsx-fire/sheetx.js");
        if (typeof mod.default === "function") {
          try {
            const wasmUrl = (await import("xlsx-fire/sheetx_bg.wasm?url"))
              .default;
            await mod.default(wasmUrl);
          } catch {
            await mod.default();
          }
        }
        listSheetsRef.current = mod.list_sheets;
        batchAsyncRef.current = mod.xlsx_batch_async;
        wasmReadyRef.current = true;
        setStatus("ready");
      } catch (err) {
        console.error("WASM init failed:", err);
        setStatus("error");
      }
    })();
  }, []);

  const onFile = async (e) => {
    const file = e.target.files?.[0];
    if (!file || !wasmReadyRef.current) return;
    const bytes = new Uint8Array(await file.arrayBuffer());

    const { sheets } = listSheetsRef.current(bytes);
    if (!sheets.length) return;

    const res = await batchAsyncRef.current(bytes, sheets[0], 0, 500);
    setRows(res.rows);
  };

  return (
    <div>
      <p>WASM: {status}</p>
      <input type="file" accept=".xlsx" onChange={onFile} />
      <table>
        <tbody>
          {rows.map((row, ri) => (
            <tr key={ri}>
              {row.map((cell, ci) => (
                <td key={ci}>{String(cell ?? "")}</td>
              ))}
            </tr>
          ))}
        </tbody>
      </table>
    </div>
  );
}

🟢 Vue 3 Example

<script setup>
import { ref, onMounted } from "vue";

const wasmReady = ref(false);
const status = ref("loading");
const rows = ref([]);

let listSheets = null;
let batchAsync = null;

onMounted(async () => {
  try {
    const mod = await import("xlsx-fire/sheetx.js");
    if (typeof mod.default === "function") {
      try {
        const wasmUrl = (await import("xlsx-fire/sheetx_bg.wasm?url")).default;
        await mod.default(wasmUrl);
      } catch {
        await mod.default();
      }
    }
    listSheets = mod.list_sheets;
    batchAsync = mod.xlsx_batch_async;
    wasmReady.value = true;
    status.value = "ready";
  } catch (err) {
    console.error("WASM init failed:", err);
    status.value = "error";
  }
});

const onFile = async (e) => {
  const file = e.target.files?.[0];
  if (!file || !wasmReady.value) return;
  const bytes = new Uint8Array(await file.arrayBuffer());

  const { sheets } = listSheets(bytes);
  if (!sheets.length) return;

  const res = await batchAsync(bytes, sheets[0], 0, 500);
  rows.value = res.rows;
};
</script>

<template>
  <div>
    <p>WASM: {{ status }}</p>
    <input type="file" accept=".xlsx" @change="onFile" />
    <table>
      <tbody>
        <tr v-for="(row, ri) in rows" :key="ri">
          <td v-for="(cell, ci) in row" :key="ci">
            {{ cell ?? "" }}
          </td>
        </tr>
      </tbody>
    </table>
  </div>
</template>

🙌 About

Built for the Web Dev Community by Shyam Repo: xlsx-fire

Async, yield, streams enabled — no workers required. Compared to SheetJS, which lacks streaming and freezes on big files.

Contributions & feedback welcome 🚀


Related Packages

vue-canvas-sheet

A high-performance, modular Canvas-based spreadsheet engine with WASM-powered ca...

5
xlsx-vue-viewer

Vue 3 component for the Excel spreadsheet editor. Self-contained: includes the e...

2,632 25
@composy/excel-vue

Excel 文档查看器 Vue 3 组件

0
wasm-onlyoffice-sdk

Offline OnlyOffice document editor SDK for React and Vue, powered by WebAssembly

1,743 8
ooxml-excel-editor

High-fidelity OOXML (.xlsx) preview & editor — canvas renderer, framework-agnost...

3,345 3

Version History

Version Released License
1.0.0 MIT