Back to all articles

everything about frontend performance

Real examples on how you can improve your frontend performance and not your average use memo use callback explainer

3 min read

Everything Frontend Performance

Hmm, let's make your frontend more performant! (And nah, this ain't a blog post that talks about useMemo or useCallback, chill.)

Identifying the Performance Bottleneck

Before optimizing anything, ask yourself: Which part of my frontend is slow? If you don't identify the bottleneck, you can't improve it.

Make React Profiler, Chrome DevTools and React DevTools (chrome extension) your best friend.

Common Frontend Performance Issues

1. UI Freezing or Lagging

Rendering large lists? Virtualization is your best friend.

  • Don't map over an array of 10,000 items and render all at once.
  • Use pagination or virtualization (e.g., react-window or react-virtualized) to render only what's in the viewport.

2. Heavy Computation Blocking the Main Thread

JS is single-threaded. If you run expensive computations on the main thread, your UI will freeze.

Example 1: Blocking the main thread

const blockThread = () => {
  const start = Date.now();
  while (Date.now() - start < 3000) {
    Math.random() * Math.random();
  }
};

blockThread(); // UI is frozen for 3 seconds

Example 2: Offloading to Web Workers

Use Web Workers to move heavy computation off the main thread. read more Docs

const worker = new Worker("worker.js");
worker.postMessage("heavy-task");
worker.onmessage = (e) => console.log("Result:", e.data);

3. Caching Expensive Computations

Maintain a small cache (e.g., LRU cache) to store frequently accessed values instead of recomputing them.

const cache = new Map();
const getCachedValue = (key, computeFn) => {
  if (cache.has(key)) return cache.get(key);
  const result = computeFn();
  cache.set(key, result);
  return result;
};

4. Preventing Unnecessary Re-renders

Wrap components in React.memo to prevent unnecessary re-renders due to parent state changes.

import React, { memo } from "react";

const AboutPage = memo(({ user, isAuthenticated }) => {
  return <div>AboutPage</div>;
});

export default AboutPage;

Why? React re-renders components when the parent re-renders and if this AboutPage was used as a component in one of the parent components and on state change in parent component even AboutPage would re-render. Hence memo prevents this unless the props change.

5. Improving First Contentful Paint (FCP)

Avoid blocking UI rendering by running expensive operations after the initial render.

import React, { useEffect } from "react";

const HomePage = () => {
  useEffect(() => {
    const blockThread = () => {
      const start = Date.now();
      while (Date.now() - start < 3000) {
        Math.random() * Math.random();
      }
    };
    blockThread(); // Freezes UI
  }, []);

  return <div>HomePage</div>;
};

export default HomePage;

Fix: Use Web Workers to defer non-essential operations.

6. Dynamic Imports for Reducing Bundle Size

If a library isn't needed on the first render, lazy load it dynamically.

import dynamic from "next/dynamic";
const HeavyComponent = dynamic(() => import("./HeavyComponent"), { ssr: false });

7. Tree Shaking

Ensure your bundler removes unused code from your final bundle.

// Instead of importing the entire lodash library:
import _ from "lodash";
console.log(_.debounce);

// Import only the required function:
import { debounce } from "lodash";
console.log(debounce);

Frontend Pitfalls & Oopsies

useEffect Dependency Array Issues

Using objects or functions as dependencies in useEffect causes unnecessary re-renders.

useEffect(() => {
  // do something
}, [user]); // ❌ Bad: Objects have different references every time

useEffect(() => {
  // do something
}, [user.id]); // ✅ Good: Use primitive values

JS compares object references, not values. Always use primitive values where possible.


Apply these techniques and make your frontend blazing fast!


Thats pretty much it! If you found the content helpful i would love to connect with you on Twitter and Github