I saw another interesting tweet today:
Blank page with an embedded tweet. How bad can it be?— Miško Hevery (Builder.io/Qwik) (@mhevery) December 23, 2022
JS: 1.5MB 🤯
PageSpeed score: 61/100 🤯
Time to Interactive: 9 sec 🤯
TBT: 1.7 sec 🤯
What hope does an average site have if a simple tweet requires MegaBytes of JS and seconds to interactivity?https://t.co/0CJBe6LXCP
It's true! Although maybe not as bad as the post seems to indicate. The initial load of a tweet is ~460kB of resources transferred resulting in ~1.4MB uncompressed. That's a lot of data for a single tweet. Can we do better?
Inspecting the Twitter embed code, we see that after the static HTML version of the tweet, a script is injected.
This script is responsible for loading the rest of the tweet. There are a few approaches, mostly geared around statically rendering tweets, but I don't really like these. I want to embed tweets independently of what framework I'm using. I mean, this blog is using manually-written HTML hosted on GitHub pages. No plugin is going to help me there!
This the main reason we built https://t.co/s4L5iJF5yR— Steven Tey (@steventey) December 25, 2022
I've been saying this is a scenario where your framework doesn't matter. It's wild, but true. One of the best solutions I've seen is done statically by @swizec and Gatsby https://t.co/ziiaco6ys1. Othwerwize you're at the mercy of Twitter's runtime library. 😥— Grayson Hicks (@graysonhicks) December 24, 2022
What if we hijack this script and replace it with our own? As in, build the embed window from scratch. I'll embrace the iframe approach and instead just do the same thing more efficiently.
First, we'll start up a server that will serve the embed. I'm using a
simple Go server. The embed file itself is a static HTML file, which you
can view the source for by viewing the source
of this page. Next, we'll replace
widgets.js to replace the static tweet
with an iframe.
With an afternoon of work, I cut it down to ~56kB unpacked! That's a whopping 95% reduction.
Lighthouse is, of course, much happier.
To use the embed, find the
platform.twitter.com domain in the
<script> tag and replace it with
platform.fastertwitter.com. That's it!
But wouldn't it be faster to just embed the full HTML and CSS? Yeah, that's pretty much what the iframe does. The slowness is not from the iframe, it's from Twitter's HTML/CSS bloat. You could replace the tweet directly too, but it's more code to maintain.
I think it's interesting how many solutions jump to using some completely independent framework to render the tweet. Even looking at Twitter's source, they a lot of compiled CSS and HTML. Is all this really necessary? Maybe they're running a lot of experiments. I don't know. But you can get really far with some manually-written HTML and running gzip on top of it.
Given how big of an improvement there was here, this honestly makes me think it could be possible to rebuild Twitter's frontend, just a lot faster. I mean, their API is zippy, why isn't the frontend? If you're interested in this, I'd love to hear from you! The code is available on GitHub.
Comment on this post on Twitter