2HAASStart a project
All posts

Guides

How to reduce JavaScript bundle size

Every kilobyte of JavaScript is downloaded, parsed and run before a page responds. Measure the bundle, split it by route, lazy load the rest and trim dependencies.

The 2HAAS team2 min read

JavaScript is the most expensive thing a page ships. An image only has to be decoded. A script has to be downloaded, parsed, compiled and executed, all on the main thread, before the page reacts to a tap. On a mid-range phone, a large bundle is the difference between a page that responds and one that feels stuck.

Here is the order we work in.

1. Measure before you cut

You cannot shrink what you cannot see. A bundle analyzer draws the bundle as a map of boxes, one per module, sized by weight.

  • Webpack: webpack-bundle-analyzer
  • Vite and Rollup: rollup-plugin-visualizer
  • Any build with source maps: source-map-explorer

The surprises are usually the same: a date library with every locale, a full icon set, or two versions of the same package.

2. Split the code by route

A visitor on the home page does not need the checkout code. Dynamic import() tells the bundler to put a module in its own file and load it on demand.

import { lazy, Suspense } from "react";

const Checkout = lazy(() => import("./pages/Checkout"));

export function App() {
  return (
    <Suspense fallback={<p>Loading…</p>}>
      <Checkout />
    </Suspense>
  );
}

Frameworks such as Next.js split by route for you. In a custom setup, routes are the first place to add it.

3. Lazy load heavy features

Some components are large and rarely needed at first paint: charts, rich text editors, maps, image galleries. Load them when the user opens the tab or scrolls near them, not on page load.

On a shop, that means the gallery script loads on the product page and the payment scripts load on the checkout page. Nothing else pays for them.

4. Trim the dependencies

  • Replace heavy libraries with lighter ones, or with the platform. Intl.DateTimeFormat covers many uses of a date library.
  • Import only what you use, and make sure it can be removed. See how tree shaking really works.
  • Check the cost of a package before you add it.

5. Ship a real production build

  • Minify the code and serve it with Brotli or gzip compression.
  • Build in production mode so development warnings are stripped.
  • Target modern browsers. Transpiling for very old ones adds helper code and polyfills that most visitors never need.

6. Keep it small

Bundles grow back one import at a time. Add a size budget to CI with a tool such as size-limit, so a pull request that adds 80 kB fails with a clear message instead of slipping through.

What to expect

Route splitting and one or two dependency swaps commonly cut the initial JavaScript by a third or more. To confirm the result on a real page, measure it with Chrome DevTools.

Keep reading

  1. Guides2 min read

    Find performance bottlenecks with Chrome DevTools

    Stop guessing why a page is slow. Use the Network and Performance panels in Chrome DevTools to find the heavy files, long tasks and layout shifts that cost you speed.

  2. Code Snippets2 min read

    Web Workers: move heavy work off the main thread

    Heavy JavaScript freezes the page because it shares a thread with the interface. A Web Worker runs that work in the background. A working example and the limits to know.

  3. Code Snippets2 min read

    Intersection Observer: react when elements scroll into view

    Scroll listeners that measure element positions are slow and fiddly. Intersection Observer tells you when an element enters the viewport, with a few lines of code.

Tell us what’s in the way.

A few lines is enough. You get a candid yes, a candid no, or a sharper question.

  • Working software in week four
  • A reply in one business day
  • Handover is the deliverable

Prefer email? [email protected]

The problem, who it is for, and what is in the way right now.

One business day to a real reply. No sales sequence, no call required.