2015 performance still ahead of us?

Posted on

pokedex

A few years ago, I came across Nolan Lawson's article from 2015 describing how he created pokedex.org - a demo on how one by employing the best practices (of 2015) could create an experience on the web that could rival that of native mobile applications:

It still is a great POC and an impressive piece of machinery, and in some sense, it is jarring how this describes a utopia that most 2025 pages are nowhere near achieving. But this begged some questions ... why are we not doing this and how does our current best practices stack up against this?

Achieving great frontend experiences (2015)

As Nolan writes, it's not rocket science. All native developers try to do these two things:

  1. Eliminate network calls.
  2. Use background threads.

He does it. It's not magic. Back then, in 2015, these technologies (Service Workers, Web Workers, GPU enabled animations, IndexedDB) were pretty new, but not super-new, either: my first task as a frontend developer at Making Waves in 2013 was to build an abstraction layer on top of LocalStorage, WebSQL and IndexedDB for browser-side persistence. But the use was not wide-spread, and it still is not.

I re-read it today, and I was reminded of a few nice tricks:

All the rest still works too: the performance is no less than ten years ago.

🤯 So why does no-one bother implementing PWA features?

Because for many apps, those advanced features are not and were not critical and UX speed is about perception. Developers (and users) of modern frameworks get:

PWA tech (service workers, local DBs, etc.) and modern frameworks solve different problems. But the perceived UX improvements that PWAs promised — speed, resilience, instant loading — got absorbed by SSR/CDN-first frameworks through other means.

"Why struggle with service workers and IndexedDB when this new stack gives us the same perceived speed with less risk?"

Pokedex envisioned as a Remix app

Next.js might have wiped the SSR floor with Remix (now React Router), but I still much prefer the standards based approach of Remix any day. Here is how I envision a Pokedex app of 2015 would look like:

Concern Old PWA-style Approach Remix Way (Modern Approach)
Data caching IndexedDB + Cache API Route loaders + automatic data prefetching on navigation
App shell model Service worker loads minimal shell, then fetches data Nested layouts + static HTML + route data = app-like UX by default
Instant transitions Manual cache logic + JS routing <Link preload="intent"> + automatic data loading and transition
Image optimization Cache API or base64 preloading Lazy <img> or external CDN proxy (Cloudflare, Vercel, etc.)
Offline mode Full service worker with offline fallback Optional: use Workbox or vite-plugin-pwa
State persistence IndexedDB or localStorage manually synced Use localStorage, sessionStorage, or React state as needed
Background sync Service worker + sync event Not built-in; possible with Workbox + background sync plugin
Push notifications Service worker + Push API Not supported directly by Remix; requires manual SW + push setup