s that are in the
visible viewport, with stubs for everything else. This cuts down on
memory usage, making the animations and touch interactions much
snappier. And once again, all of the list computation and diffing is
done inside of the web worker, so scrolling is kept buttery-smooth.
This works with as many as 649 Pokémon being shown at once.
3. Be careful what libraries you choose! I'm using MUI as my "Material"
CSS library, which is great for bootstrapping, but sadly I discovered
that it often wasn't doing the optimal thing for performance. So I
ended up having to re-implement parts of it myself. For instance, the
side menu was originally being animated using margin-left instead of
transform, which leads to janky animations on mobile.
4. Event listeners are a menace. At one point MUI was adding an event
listener on every
(for the "ripple" effect), which slowed down
even the hardware-accelerated CSS animations due to memory usage.
Luckily the Chrome Dev Tools has a "Show scrolling perf issues"
checkbox, which immediately revealed the problem:
To work around this, I attached a single event listener to the entire
, which is responsible for animating the ripple effect on individual
s.
Browser support
As it turns out, a lot of the APIs I mention above aren't perfectly
supported in all browsers. Most notably, ServiceWorker is not available in
Safari, iOS, IE, or Edge. (Firefox has it in nightly and will ship very
soon.) This means that the offline functionality won't work in those
browsers – if you refresh the page without a connection, the content won't
be there anymore.
Another hurdle I ran into is that Safari does not support IndexedDB in a
web worker, meaning I had to write a workaround to avoid the web worker in
Safari and just use PouchDB/LocalForage over WebSQL. Safari also still has
the 350ms tap delay, which I chose not to fix with the FastClick hack
because I know Safari will fix it themselves in an upcoming release.
Momentum scrolling is also broken in iOS, for reasons I don't yet
understand. (Update: looks like it needs -webkit-overflow-scroll: touch.)
Surprisingly, Edge and FirefoxOS both worked without a hitch (except for
ServiceWorker). FirefoxOS even has the status bar theme colors, which is
neat. I haven't tested in Windows Phone yet.
Of course, I could have fixed all these compatibility issues with a million
polyfills – Apple touch icons instead of Web Manifests, AppCache instead of
ServiceWorker, FastClick, etc. However, one of my goals for this app was to
make a high-quality experience with progressive degradation for the less
standards-compliant browsers. On browsers with ServiceWorker, the app is a
rich, high-quality offline app. On other browsers, it's just a web site.
And I'm okay with that. I strongly believe that web developers need to push
the envelope on this stuff, if we expect browser vendors to have any
motivation to improve their implementations. To quote WebKit developer Dean
Jackson, one of the reasons they didn't prioritize IndexedDB was because
they "don't see much use." In other words, if there were a lot of
high-quality sites that depended on IndexedDB, then WebKit would have been
pushed to implement it. But developers didn't step up their game, so
browser vendors just shrugged it off.
If we only use features that work in IE8, then we're condemning ourselves
to live in an IE8 world. This app is a protest against that mindset.
TODOs
There are still more improvements to make to this app. Some unanswered
questions for me, especially involving ServiceWorker:
1. How to handle routing? If I do it the "right" way with the HTML5
History API (as opposed to hash URLs), does that mean I need to
duplicate my routing logic on the server side, the client side, and
in the ServiceWorker? Sure seems that way.
2. How to update the ServiceWorker? I'm versioning all the data I store
in the ServiceWorker Cache, but I'm not sure how to evict stale data
for existing users. Currently they need to refresh the page or
restart their browser so that the ServiceWorker can update, but I'd
like to do it live somehow.
3. How to control the app banner? Chrome will show an "install to home
screen" banner if you visit the site twice in the same week (with
some heuristics), but I really like the way Flipkart Lite captures
the banner event so that they can launch it themselves. It feels like
a more streamlined experience.
Conclusion
The web is quickly catching up on mobile, but of course there are always
improvements to be made. And like any good Pokémaniac, I want Pokedex.org
to be the very best, like no app ever was.
So I encourage anyone to take a look at the source on Github and tell me
where it can improve. As it stands, though, I think Pokedex.org is a
gorgeous, immersive mobile app, and one that's tailor-made for the web. My
hope is that it can demonstrate some of the great features that the web of
2015 can offer, while also serving as a valuable resource for the Pokémon
fan who's gotta catch 'em all.
Thanks to Jacob Angel for providing feedback on a draft of this blog post.
For more on the tech behind Pokedex.org, check out my "progressive webapp"
reading list." />