Frontend Development 8 min read

How to Generate Excel‑Based Posters in the Browser Without Crashing

This article walks through building a front‑end‑only tool that reads student data from Excel, creates customized poster images using SheetJS, html2canvas, and JSZip, and solves out‑of‑memory crashes by analyzing JavaScript heap usage, refactoring recursive code, and optimizing DOM cloning with ignoreElements.

Tencent IMWeb Frontend Team
Tencent IMWeb Frontend Team
Tencent IMWeb Frontend Team
How to Generate Excel‑Based Posters in the Browser Without Crashing

1. Requirement Background

We received an urgent request to generate posters from student information and exam scores stored in an Excel file.

Excel data and the desired poster style are shown below:

Excel data
Excel data
Poster style
Poster style

Because the deadline is tight, the entire data parsing and poster generation must be implemented on the front end.

Key Technical Points

Use SheetJS and

XLSX.utils.sheet_to_json

to convert Excel data to JSON.

Generate poster images with html2canvas , then obtain a Blob via

canvas.toBlob

.

Package the images into a zip file using JSZip .

Import/export form configuration with

FileReader.readAsText

(refer to MDN for details).

Overall Development Flow

Create a form to collect configurable text for each exam score.

Iterate over each row of the Excel file, generate an HTML template for the poster based on the form configuration.

Render the HTML template to an image and add the image data to a zip object.

After processing all rows, download the zip file.

Testing with 100 rows of data on our machine succeeded, and the operations team was satisfied.

2. Testing Issue

When the operations colleague tested the tool on their computer, the page crashed with an “Out Of Memory” error after processing more than 20 rows.

Crash screenshot
Crash screenshot

3. Problem Analysis

3.1 JavaScript Memory Issue

The JS heap keeps growing after each Excel row is processed because the JSZip object is never released until the download finishes.

Solution: split the zip into smaller batches (e.g., download every 10 rows) to free memory.

However, the memory growth was still excessive (≈20 MB for 20 images), so we used the browser’s Performance and Memory tools.

JS Heap growth
JS Heap growth

The snapshot showed continuous memory increase, and further inspection revealed recursive code that created a large call stack.

We replaced the recursion with an iterative loop, which stopped the heap growth.

3.2 DOM Issue

Even after fixing the JS side, the page still stalled when processing more than 40 rows. The bottleneck was html2canvas cloning the entire DOM, including the React root,

script

and

link

tags, which triggered additional network requests.

We limited the cloning to the target node and ignored unnecessary elements using the

ignoreElements

option.

DOM structure
DOM structure
<code>const canvas = await html2canvas(root, {
  imageTimeout: 10000,
  ignoreElements: (ele) =>
    ele.id === 'root' ||
    ele.tagName.toUpperCase() === 'IFRAME' ||
    ele.tagName.toUpperCase() === 'SCRIPT' ||
    ele.tagName.toUpperCase() === 'LINK',
});
</code>

After applying the filter, processing 1,000 rows completed in under 4 minutes without any crashes.

4. Summary

JSZip’s memory consumption still requires batch processing, but the batch size can be increased to 1,000 rows after the DOM cloning issue is resolved.

This case demonstrates that thorough analysis—both of JavaScript heap behavior and DOM manipulation—is essential before applying generic optimizations like batching.

When a page shows “Oops, it crashed!”, careful debugging is the key to a reliable solution.

FrontendMemory Optimizationexcelhtml2canvasjszip
Tencent IMWeb Frontend Team
Written by

Tencent IMWeb Frontend Team

IMWeb Frontend Community gathering frontend development enthusiasts. Follow us for refined live courses by top experts, cutting‑edge technical posts, and to sharpen your frontend skills.

0 followers
Reader feedback

How this landed with the community

login Sign in to like

Rate this article

Was this worth your time?

Sign in to rate
Discussion

0 Comments

Thoughtful readers leave field notes, pushback, and hard-won operational detail here.