# Cutting a PWA homepage from 4.8 MB to 70 KB

> A dev.to report trims a PDF tools landing page to about 70 KB and retunes the service worker so the precache holds the app shell instead of the libraries.

On 2026-10-09 the dev.to account Shahzaib published a report on PdfWord, a PDF tools
site the post describes as free, no-signup and client-side, stating that the installed
PWA took a long time to open on phones and that users complained. The post calls what
followed a 20-minute fix that cut 98.5% of the weight, and it covers two separate
changes: what the landing page downloads, and what the service worker precaches on
install
([the post](https://dev.to/shahzaib11/how-i-cut-my-homepage-from-48mb-to-70kb-and-made-my-pwa-open-instantly-3673)).

## What the measurement found

The post's first move is a measurement rather than an optimisation. It states that the
author measured what the homepage actually downloads before any change was made
([the post](https://dev.to/shahzaib11/how-i-cut-my-homepage-from-48mb-to-70kb-and-made-my-pwa-open-instantly-3673)).

### The library weights the post lists

The post's table gives `html2pdf.bundle.min.js` at 884 KB, `xlsx.full.min.js` at
861 KB, `docx.min.js` at 725 KB, `pdf-lib.min.js` at 512 KB, `pptxgen.bundle.js` at
466 KB, `jspdf.umd.min.js` at 410 KB, and `pdf.min.js` at 312 KB, followed by a row
reading "plus 25 more scripts". The total the post prints under that table is 4.8 MB of
JavaScript on a landing page
([the post](https://dev.to/shahzaib11/how-i-cut-my-homepage-from-48mb-to-70kb-and-made-my-pwa-open-instantly-3673)).

### What the homepage actually needed

The post's account of the page's job is that the homepage is just cards that link to
tool pages, and that it needed none of the libraries in that table. Its explanation for
their presence is that every library was loaded "just in case", and it adds that the
page also carried 22 dead inline tool panels from an older design
([the post](https://dev.to/shahzaib11/how-i-cut-my-homepage-from-48mb-to-70kb-and-made-my-pwa-open-instantly-3673)).

## What the post removed

The fix the post describes is subtraction on the landing page, with the loading of
heavy dependencies pushed to the pages that use them
([the post](https://dev.to/shahzaib11/how-i-cut-my-homepage-from-48mb-to-70kb-and-made-my-pwa-open-instantly-3673)).

### The deletions on the homepage

The post states that it deleted the 22 dead tool panels from the homepage, noting that
dedicated tool pages already existed and putting 25 KB of dead HTML on the deletion,
and that it removed all 33 heavy `<script>` tags from the homepage. Its description of
the new loading rule is that each tool page still loads only the libraries it needs,
which the post labels selective per-page loading
([the post](https://dev.to/shahzaib11/how-i-cut-my-homepage-from-48mb-to-70kb-and-made-my-pwa-open-instantly-3673)).

### The file that stayed

One script survived the pass. The post states that it kept one file, `common.js` at
15 KB, for navigation, the theme toggle, and filters. The result it prints for the page
is 54 KB of HTML plus 15 KB of JavaScript, which it gives as roughly 70 KB in total,
down from 4.8 MB
([the post](https://dev.to/shahzaib11/how-i-cut-my-homepage-from-48mb-to-70kb-and-made-my-pwa-open-instantly-3673)).

## The service worker change

The post reports a second change on the service worker side
([the post](https://dev.to/shahzaib11/how-i-cut-my-homepage-from-48mb-to-70kb-and-made-my-pwa-open-instantly-3673)).

### From a library precache to an app shell precache

The post states that it also found the service worker was precaching about 2 MB of
libraries on install, that it trimmed the precache to the app shell only at about
120 KB, and that heavy libraries now cache on-demand when their tool page is first
opened. It adds that HTML uses a network-first strategy so updates reach installed apps
without reinstalls
([the post](https://dev.to/shahzaib11/how-i-cut-my-homepage-from-48mb-to-70kb-and-made-my-pwa-open-instantly-3673)).

MDN documents the caching mechanisms those moves use. On precaching, MDN states that
when a service worker is installed the browser fires an `install` event in the service
worker's global scope, and that at this point the service worker can precache
resources, fetching them from the network and storing them in the cache. MDN also
states that precaching is an appropriate strategy for resources that the PWA is certain
to need, that will not change for this version of the app, and that need to be fetched
as quickly as possible, giving the basic user interface of the app as its example and
adding that if this is precached then the app's UI can be rendered on launch without
needing any network requests
([MDN, Caching](https://developer.mozilla.org/en-US/docs/Web/Progressive_web_apps/Guides/Caching)).

On caching a resource the first time it is requested, MDN states that when a service
worker's `fetch` event fires, the service worker may forward the request to the network
and cache the resulting response, either if the cache did not already contain a
response or to update the cached response with a more recent one. On the strategy the
post names for HTML, MDN describes "network first" as trying to retrieve the resource
from the network, returning the response and updating the cache if the request
succeeds, and trying the cache if it fails, and states that this is useful for requests
for which it is important to get the most fresh response possible but for which a
cached resource is better than nothing
([MDN, Caching](https://developer.mozilla.org/en-US/docs/Web/Progressive_web_apps/Guides/Caching)).

### Versioning the cache

The post states the rule it now follows as bumping the service worker cache version on
every deploy, and gives the failure it is guarding against: installed apps serve stale
files forever
([the post](https://dev.to/shahzaib11/how-i-cut-my-homepage-from-48mb-to-70kb-and-made-my-pwa-open-instantly-3673)).

MDN states the same practice in its own words. Its page on the `Cache` interface says
that items in a `Cache` do not get updated unless explicitly requested and do not
expire unless deleted, that you are responsible for implementing how your script
handles `Cache` updates, and that you should make sure to version caches by name and
use the caches only from the version of the script that they can safely operate on. It
also states that you are responsible for periodically purging cache entries
([MDN, Cache](https://developer.mozilla.org/en-US/docs/Web/API/Cache)).

MDN's caching guide names where that purge belongs. It states that a PWA should clean
up any old versions of its cache in the service worker's `activate` event, because when
this event fires the service worker can be sure that no previous versions of the
service worker are running, so old cached data is no longer needed
([MDN, Caching](https://developer.mozilla.org/en-US/docs/Web/Progressive_web_apps/Guides/Caching)).

## The results the post reports

The post gives three results. It reports a page load of 422 ms, attributing the figure
to Cloudflare Web Analytics on real devices. It reports Core Web Vitals as 100% Good
across LCP, INP, and CLS. And it states that the PWA opens instantly on 4G. Its closing
advice is to audit what a landing page actually needs, and its characterisation of the
pattern it removed is that "just in case" script tags are the silent killer of mobile
performance
([the post](https://dev.to/shahzaib11/how-i-cut-my-homepage-from-48mb-to-70kb-and-made-my-pwa-open-instantly-3673)).

The three metric names in that second result have published targets. web.dev states
that Largest Contentful Paint measures loading performance and that to provide a good
user experience LCP should occur within 2.5 seconds of when the page first starts
loading; that Interaction to Next Paint measures interactivity and that pages should
have an INP of 200 milliseconds or less; and that Cumulative Layout Shift measures
visual stability and that pages should maintain a CLS of 0.1 or less. It adds that a
good threshold to measure is the 75th percentile of page loads, segmented across mobile
and desktop devices, and that tools assessing Core Web Vitals compliance should
consider a page passing if it meets the recommended targets at the 75th percentile for
all three metrics
([web.dev, Web Vitals](https://web.dev/articles/vitals)).

## Why it matters for PWA developers

The transferable mechanism in the post is the install-time fetch. MDN describes the
service worker's `install` handler as an opportunity to fetch resources from the
network and store them in the cache, a step that runs when the service worker installs
rather than when a page navigates
([MDN, Caching](https://developer.mozilla.org/en-US/docs/Web/Progressive_web_apps/Guides/Caching)).

MDN also states a criterion for what belongs in that precache. It names resources the
PWA is certain to need, that will not change for this version of the app, and that need
to be fetched as quickly as possible, and gives the app's basic user interface as the
example
([MDN, Caching](https://developer.mozilla.org/en-US/docs/Web/Progressive_web_apps/Guides/Caching)).

The cache-versioning rule the post adopts has a documented basis. MDN states that items
in a `Cache` are not updated unless explicitly requested and do not expire unless
deleted, that caches should be versioned by name and used only from the version of the
script that can safely operate on them, and in the same place that how long a `Cache`
lives is browser dependent and that a browser may delete all of an origin's Cache
Storage
([MDN, Cache](https://developer.mozilla.org/en-US/docs/Web/API/Cache)).

Finally, web.dev's framing of Core Web Vitals is a 75th-percentile threshold per
metric, segmented across mobile and desktop
([web.dev, Web Vitals](https://web.dev/articles/vitals)), which is not the method the
post states for its own load figure
([the post](https://dev.to/shahzaib11/how-i-cut-my-homepage-from-48mb-to-70kb-and-made-my-pwa-open-instantly-3673)).

## Related entries on this site

- [Performance](/reference/performance/): the post's subject is the startup path of an
  installed app and the Core Web Vitals metrics it reports against, and this page is
  where OpenPWA documents those metrics and the budgets around them.
- [Storage](/reference/storage/): the change the post makes on the service worker side
  is about what occupies the cache and when it is re-keyed, and this page is where the
  origin-scoped stores, their quotas, and their eviction rules are covered.
- [Capabilities](/reference/capabilities/): the libraries the post moved off the landing
  page exist to drive platform features from a tool page, and this page is where
  OpenPWA tracks which of those features a PWA can reach.

## Open and unverified

- Which browsers and versions the 422 ms figure was collected from is not stated by the
  post, so the timing cannot be pinned to an engine.
- How the Core Web Vitals result was collected, and whether it reflects the 75th
  percentile threshold web.dev describes, is not stated by the post.
- Which pages the reported page load covers, and whether it is the landing page alone or
  the site, is not resolved by the post's wording.
- Whether the 4.8 MB figure was measured over the network or summed from file sizes is
  not stated, so the 98.5% figure the post prints cannot be traced to a method.
- Whether the app shell precache the post describes is cleaned up in the `activate`
  event, which MDN names as the place for that work, is not addressed.
- What the on-demand caching of the heavy libraries does to the origin's storage
  footprint over time is not discussed; MDN states that how long a `Cache` lives is
  browser dependent and that a browser may delete all of an origin's Cache Storage
  ([MDN, Cache](https://developer.mozilla.org/en-US/docs/Web/API/Cache)).
- Whether the network-first strategy the post adopted for HTML has a documented offline
  fallback in this app is not stated.

## Sources

- [How I Cut My Homepage from 4.8MB to 70KB (and Made My PWA Open Instantly)](https://dev.to/shahzaib11/how-i-cut-my-homepage-from-48mb-to-70kb-and-made-my-pwa-open-instantly-3673) (dev.to)
- [Caching](https://developer.mozilla.org/en-US/docs/Web/Progressive_web_apps/Guides/Caching) (developer.mozilla.org)
- [Cache](https://developer.mozilla.org/en-US/docs/Web/API/Cache) (developer.mozilla.org)
- [Web Vitals](https://web.dev/articles/vitals) (web.dev)