I cringed while watching my sister-in-law use Buckets on her iPhone. It was so painfully slow. I knew it was slow, but I didn’t know how bad it was. So I decided to make it faster—here’s how:

tl;dr

If you have previously put no effort into the speed of a webapp, then almost any effort will buy you huge gains :) It’s easy to make something 10x faster than molasses. Just try something.

1. Make something terrible

The first step to making something fast is to make something. It can be terrible. Mine was.

2. DevTools

The next step is to get some data. I pulled up Chrome DevTools and watched the landing page load:

Landing page load

Ouch! Twenty seconds just to load the first page. No real user would wait that long.

3. Images

Turns out I was asking the browser to download 180 KB of images. I reduced the quality and size of each of the three images (yes, 180 KB for three images) to about 27 KB of images. I used gifsicle and ImageMagick for that. Here’s a part of my Makefile:

PNGS := $(patsubst static/img/%.png,static/img/opt/%.png,$(wildcard static/img/*.png))
GIFS := $(patsubst static/img/%.gif,static/img/opt/%.gif,$(wildcard static/img/*.gif))

optimized-images: $(PNGS) $(GIFS)

static/img/opt/%.png: static/img/%.png
        convert -quality 90 -depth 5 $^ [email protected]

static/img/opt/%.gif: static/img/%.gif
        gifsicle -O -o [email protected] $^

I might get webpack to do this in the future.

4. Unused JavaScript/CSS

Some time ago, I had this bright idea of loading all the application JavaScript and CSS on the landing page, so that users would experience no delay when they went to use the app.

I repented.

And saved 1.1 MB.

5. webpack

I heard about webpack a while ago and thought it might be neat, but also thought, “Ugh… why another module bundler?” After watching my sister-in-law suffer through my app, though, I watched the following talk by Pete Hunt, which convinced me to give webpack a real try.

Webpack is confusing at first, but later it’s still confusing (okay, it gets a little better with practice). Eventually, you can get it to do what you want. And for Buckets it has been worth the effort. I see real speed benefits now, but I also foresee great modularity/reuseability benefits on the horizon.

Using webpack is a good choice.

6. Don’t embed YouTube videos

I had an embedded YouTube video on the landing page. It ate up ~500 KB over several sequential requests. Now, I have a fake “embedded” video link to YouTube. I might later make the embedded video load after the user clicks the fake “embedded” video link.

Results

Here are some measurements of three distinct pages of the app before and after doing the above. All measurements were taken by accessing a local dev server with Chrome’s DevTools simulating a Normal 3G connection (750 Kbps, 100ms RTT).

Before After
Landing page
  • time: 20.78 s
  • size: 1.8 MB
  • DOM: 20.13 s
  • load: 20.78 s
  • time: 2.07 s
  • size: 115 KB
  • DOM: 842 ms
  • load: 1.22 s
Sandbox
  • time: 16.51 s
  • size: 1.4 MB
  • DOM: 13.46 s
  • load: 16.51 s
  • time: 13.63 s
  • size: 1.1 MB
  • DOM: 645 ms
  • load: 12.87 s
App
  • time: 16.36 s
  • size: 1.4 MB
  • DOM: 13.31 s
  • load: 16.36 s
  • time: 12.60 s
  • size: 1.0 MB
  • DOM: 615 ms
  • load: 11.77 s

I’m rather pleased that the landing page loads visually in about 1 second and completely in 2. The other pages are slightly faster and smaller. I will continue to optimize them.

Feel free to give Buckets a try.