A real-world performance fix that made my app usable again.
Ever uploaded a file and watched your app turn into a brick?
That’s what was happening in my dashboard app — a CSV visualizer that lets users upload massive spreadsheets, crunch the data, and generate real-time stats + charts.
It was working great… until people started uploading actual real-world CSVs.
- 1 MB? Fine.
- 5 MB? Kinda slow.
- 20 MB? 🧊 Frozen UI. Zero response.
You clicked a button? Nothing.
Tried to scroll? Good luck.
Even the loader stopped spinning because… JavaScript was busy choking.
💡 Where It Went Wrong
JavaScript runs on a single thread.
That means any heavy CPU work (like parsing and summarizing CSV data) blocks everything else — buttons, scroll, animations, even paint.
I tried async/await. I tried debouncing. I tried optimizing my code like a maniac.
But the real problem?
My app was asking the main thread to do everything.
⚙️ What Was Happening Behind the Scenes
Every time a CSV was uploaded, I was doing this:
const reader = new FileReader();
reader.onload = (e) => {
const text = e.target.result;
const rows = parseCSV(text); // heavy loop!
const stats = generateStats(rows); // CPU-heavy
renderDashboard(stats); // React state update
};
reader.readAsText(file);
Looks simple — but parseCSV and generateStats were brutal on big files.
React choked. The browser hung. The UI stopped responding.
🔥 Enter Web Workers
I needed a way to move all that heavy lifting off the main thread.
That’s where Web Workers come in — basically background threads for JavaScript.
They can’t touch the DOM, but they can do all the grunt work without blocking your UI.
🛠️ Step-by-Step: How I Refactored with Web Workers
📁 Create a worker file
// csvWorker.js
self.onmessage = function (event) {
const csvText = event.data;
const rows = parseCSV(csvText); // custom parser
const stats = generateStats(rows); // summary metrics
self.postMessage(stats);
};
📥 Send work from your app
// inside App.jsx
const worker = new Worker(new URL('./csvWorker.js', import.meta.url), { type: 'module' });
worker.postMessage(csvText);
worker.onmessage = (e) => {
const stats = e.data;
setDashboardData(stats); // back on the main thread
};
Boom. 🎯
The UI no longer froze. The spinner kept spinning. And users could scroll and click freely — even with 30MB CSVs uploading in the background.
🎉 The Results
Before Web Workers:
- App froze for 3–5 seconds on every upload
- Some browsers showed “Page is unresponsive” warnings
- Rage-quits happened
After Web Workers:
- Smooth, non-blocking experience
- UI stays interactive while CSV is being parsed
- Feels like a native desktop app now
🧠 Lessons I Learned
- Web Workers are wildly underused. Especially for apps that deal with data-heavy processing.
- They’re not hard to set up. Especially with modern tooling (Vite, Webpack, etc. support importing worker files natively).
- You can’t share variables between threads. Use postMessage to send and receive data — no shared memory.
- They work great with React. Just don’t try to touch DOM or React state inside the worker.
🔚 Final Thoughts
If your JavaScript app feels sluggish during file uploads, data crunching, or image processing — don’t blame React.
Blame the main thread.
Then give it a break — and let a Web Worker do the dirty work.
They’re not the most glamorous tool in the toolbox, but they might just save your app from performance hell.
🙌 Enjoyed the post?
If this helped you think differently about performance in JavaScript apps, drop a 👏 or leave a comment — I’d love to hear what you’re building or struggling with!
🧑💻 Check out more dev tools & blogs I’m working on:
📁 Portfolio → https://sachinkasana-dev.vercel.app
🔧 JSON Formatter Tool → https://json-formatter-web.vercel.app
Let’s keep making the web faster — one main thread at a time. 🚀
Thank you for being a part of the community
Before you go:
- Be sure to clap and follow the writer ️👏 ️️
- Follow us: X | LinkedIn | YouTube | Newsletter | Podcast | Differ | Twitch
- Start your own free AI-powered blog on Differ 🚀
- Join our content creators community on Discord 🧑🏻💻
- For more content, visit plainenglish.io + stackademic.com
Top comments (0)