A website can look simple and still ask the browser to do far too much. Ours did. The interface was clean, but the production folder contained old images, duplicate assets, oversized files, and debugging output that no visitor needed.

We cleaned it up and reduced the complete production build from 5.15 MB to 0.64 MB—about 87% lighter. The estimated first homepage download fell from 654 KB to 286 KB, while the blog index dropped from 381 KB to 102 KB.

This was not a redesign. We kept the same visual language and focused on what the browser actually had to download, decode, and execute.

Measurement Before After
Complete production build 5.15 MB 0.64 MB
Homepage first load 654 KB 286 KB
Blog first load 381 KB 102 KB

Start with a production baseline

Performance work should begin with evidence. A development server hides some problems, and a source repository does not show what a deployed visitor receives. Build the production version first, then inspect the output by file size and type.

We looked at three different numbers:

  1. Total deployment size: every file copied into the production build.
  2. Initial page weight: the HTML, CSS, JavaScript, fonts, and images requested during the first visit.
  3. Deferred page weight: resources requested only when a visitor scrolls or starts an interaction.

These measurements answer different questions. Removing source maps makes the deployment smaller, for example, but it does not necessarily make a normal page view faster because browsers do not download source maps unless development tools request them. Compressing an eager hero image directly reduces the first load.

That distinction kept us from celebrating a smaller folder while leaving the visitor experience unchanged.

Remove assets before compressing them

The cheapest request is the one that does not exist.

Our largest single file was a legacy team image of almost 2 MB that was no longer referenced anywhere. Several older logos and duplicate portraits were also copied into every production deployment despite never appearing on a page. Together, unused assets accounted for more than 2 MB.

We searched the application, blog templates, metadata, and public files for each filename before deleting anything. This matters because an image may not appear in a React component but may still be used as an Open Graph preview, favicon, structured-data logo, or blog cover.

A safe cleanup sequence is:

  1. list production files from largest to smallest;
  2. search the complete repository for each suspicious filename;
  3. replace any remaining references with the intended asset;
  4. remove only files with no consumers;
  5. rebuild and check for missing requests.

Compression cannot compete with deletion. Optimizing an unused 2 MB image into a 400 KB image still ships 400 KB that nobody needs.

Deliver images at an appropriate size

The next savings came from images that were genuinely part of the design but much larger than their rendered dimensions.

Our navigation logo was a 500×500 PNG weighing about 170 KB, even though it normally appears at roughly 30 pixels. Resizing it to 256×256 and preserving transparency reduced it to about 23 KB.

Four 720×720 hero illustrations were converted to 480×480 WebP files. Their combined weight fell from roughly 369 KB to 63 KB. Two 900×900 team portraits became 640×640 WebP images and dropped from about 325 KB combined to 35 KB.

The useful rule is not “convert everything to WebP.” It is:

  • choose dimensions based on the largest real display size and high-density screens;
  • select an encoding suited to the image;
  • preserve a broadly supported social-preview format where external crawlers need it;
  • keep explicit width and height so the layout does not jump while the image loads;
  • inspect the result rather than trusting a quality number.

An image that is blurry, incorrectly cropped, or missing from a social preview is not an optimization.

What deferred loading actually means

Deferred loading means postponing a resource until it is likely to be useful. It reduces competition for bandwidth and CPU during the initial page load.

For an off-screen image, the browser already provides a simple mechanism:

<img
  src="/images/team/member.webp"
  alt="Team member"
  width="640"
  height="640"
  loading="lazy"
  decoding="async"
/>

The browser decides when the image is close enough to the viewport to fetch. This works well for team portraits, lower-page project images, and supporting article media.

It should not be applied blindly. A hero image or another likely Largest Contentful Paint element should normally remain eager. Delaying the most important visible asset can make a performance score worse rather than better. Google’s web performance guidance similarly recommends loading images in the initial viewport eagerly while lazy-loading those farther down the page.

Scripts have a related choice. A normal script can pause HTML parsing while it downloads and executes. defer allows the HTML parser to continue and executes the script after parsing, while preserving script order. async also avoids blocking parsing, but executes as soon as the file is ready, so order is not guaranteed.

Use deferred loading for work that is genuinely non-critical: analytics initialization after consent, a large interactive tool below the fold, an embedded video, or code for a modal that the visitor may never open. Do not defer the navigation, the primary call to action, or code required to render the first screen simply to make a report look better.

Source maps, JavaScript, and the less visible weight

Images were the largest opportunity, but production weight is not only visual.

Our JavaScript and CSS source maps contributed about 1.34 MB to the deployment. Source maps connect minified production code to readable source files for debugging. They can be valuable when a team relies on production error tooling, but a small marketing site may not need to publish them openly with every build.

We disabled public production source maps after confirming they were not part of our debugging workflow. This reduced deployment size without changing what visitors saw.

JavaScript deserves the same practical review. Shipping a library has three costs: transfer, parsing, and execution. Before adding a dependency, check whether the browser or a small component already provides the behavior. For code used only on a specific route or interaction, route-level or component-level splitting can keep it out of the first bundle.

The goal is not zero JavaScript. The goal is to make the initial experience pay only for the functionality it needs.

Does a lighter website improve Google ranking?

Potentially—but not as a direct “smaller megabytes equals higher position” rule.

Google says its ranking systems use Core Web Vitals and seek to reward a good overall page experience. Faster loading, responsive interaction, and stable layout can therefore contribute to search success. Google also makes an important qualification: strong Core Web Vitals do not guarantee top rankings, and relevant, helpful content remains more important.

That is the right way to think about performance and SEO:

  • fewer unnecessary bytes can improve loading behavior, especially on mobile connections;
  • appropriately deferred resources reduce contention during the first screen;
  • explicit image dimensions help visual stability;
  • a faster, clearer site is easier for people to use;
  • none of this replaces useful content, accurate metadata, crawlable pages, internal links, or authority.

Performance is part of technical SEO and product quality. It is not a substitute for either.

Useful references include Google’s guidance on page experience in Search, native image lazy loading, and the performance effects of excessive lazy loading.

A practical lightweight-site checklist

Use this order because the largest savings usually appear near the top:

  1. Build the real production output and record the baseline.
  2. Sort assets by size and remove files with no references.
  3. Resize images to match their actual presentation.
  4. Use modern formats where browser and crawler support fits the use case.
  5. Keep above-the-fold assets eager and defer lower-page media.
  6. Add explicit image dimensions to prevent layout movement.
  7. Review public source maps and unused JavaScript.
  8. Test the complete site on desktop and mobile after every change.
  9. Compare real-user Core Web Vitals after deployment, not only a local score.

Our largest improvement did not come from a clever framework migration. It came from understanding the files we already shipped and being deliberate about when the browser needed them.

Voicepls builds and improves production software, AI systems, integrations, and web platforms. Talk to our engineering team if your product feels heavier, slower, or harder to operate than it should.