Trying out AMP

February 2nd, 2018
amp, tech
I'm going to be working with AMP some at work, so to get more familiar with it I decided to try making an AMP version of my site. Switching everything over would be a bunch of work, so I decided to limit this to the blog posts themselves (everything under /p/ except for the index). I'm now running a 50-50 A/B test where half the time these pages load as AMP and half the time they load normally. I've labeled the page either [amp] or [html] in the upper right, and if you refresh a few times you should see both versions.

Things I ran into:

  • The hand-rolled software that builds these posts was in terrible shape, with over a decade of hacks on top of hacks. This made it very hard to make the small changes I needed in order to generate AMP versions of pages. I rewrote it to work more sensibly (parsing html with a parser instead of linebreaks and regexps, to start with) which was a surprising amount of work. [1]

  • The comments were the hardest part. This page is served statically, and then it fetches the comments in the background. The original version uses JS for this, making requests in parallel for the different services, and then uses JS to build the HTML to display the comments.

    In AMP you can't use custom JS, so I needed to build this out of an existing component (or, in theory, write a new component). It looked like amp-list was the closest to right, but it doesn't seem to support nesting. I gave up on nesting, and decided to use '→' to mark reply comments.

    This meant creating a new endpoint on my comment server for AMP pages, and having it serve JSON in a form that AMP would be able to work with.

  • AMP uses amp-img tags instead of standard image tags. They're pretty similar, except that in AMP everything needs to have a deterministic size. Luckily I'd already sorted out a system of automatically injecting the sizes of my images a few months ago, or this would have been much more work.

  • I needed to convert my embedded youtube videos to amp-youtube, which wasn't too bad. This got me to fix some of my very old flash embeds that I still had kicking around.

  • AMP doesn't let you use style attributes, so I wrote something that automatically hoists these to a style block at the top of the page.

On my pages I expect AMP to slow things down a bit in general by adding a blocking script load, but it could make up for this on long pages with a bunch of images because AMP is able to better prioritize visible content. Example WebPageTest runs, all on a simulated Moto G on simulated bad 3G internet:

  • Ordinary Page:
    • Regular: 1, 2, 3
    • AMP: 1, 2, 3
  • Lots of Images:
    • Regular: 1, 2, 3
    • AMP: 1, 2, 3
As expected, the first page it loaded (going by "page load time") about a second faster without AMP (~5s vs ~6s) while on the second page it loaded ten seconds faster with AMP (~10s vs ~20s). Though that's not entirely fair, since AMP is still going to have to load the rest of the images once you start scrolling.

Update 2018-02-06: I went to check how this experiment was doing, and I realized I didn't set up the custom dimension properly in google analytics. In addition to making sure I'm sending it on each pageview (which I did) I also need to configure it server-side. I've done that now; hopefully I'll be able to look at this tomorrow. I had also set this up as a content experiment, but content experiments don't seem to let you analyze speed, only high level metrics like pageviews/session (which doesn't make sense with a random-per-pageview experiment) or bounce rate (which does, but is noisy).

Update2018-04-27: this experiment didn't really work; wrote up results.


[1] It's still a lot slower than the old version, around 25s instead of 5s. I looked at in with a profiler and nothing jumps out as nuts. I could rewrite it in something faster, or look more into speeding it up, but for now I just figured out how to run it in the background from emacs instead of having it block my workflow:

(require 'subr-x)
(defun process-sentinel (process event_type)
  (message (format "%s: %s%s" process
                   (string-trim event_type)
                   (if (string= event_type "finished\n")
                        ""
                        " (see buffer make-rss)"))))
(defun publish-news-entries ()
  (interactive)
  (message "publishing news entries in the background...")
  (start-process "make-rss" "make-rss"
    "~/bin/makerss-and-reverserss.sh")
  (set-process-sentinel
    (get-process "make-rss")
    'process-sentinel))

Comment via: google plus, facebook

Recent posts on blogs I like:

How Does Fiction Affect Reality?

Social norms

via Thing of Things April 19, 2024

Clarendon Postmortem

I posted a postmortem of a community I worked to help build, Clarendon, in Cambridge MA, over at Supernuclear.

via Home March 19, 2024

How web bloat impacts users with slow devices

In 2017, we looked at how web bloat affects users with slow connections. Even in the U.S., many users didn't have broadband speeds, making much of the web difficult to use. It's still the case that many users don't have broadband speeds, both …

via Posts on March 16, 2024

more     (via openring)