JavaScript as a Last Resort

My favorite fantasy novel is Douglas Crockford’s JavaScript: The Good Parts, because I don’t think JavaScript has any good parts and should be used as a last resort. This puts me at odds with most web developers, and probably puts me at odds with Kev Quirk, who holds the opinion that JavaScript is only bad when misused.

Let me start by explaining why JavaScript has a bad reputation. You see, it’s a programming language that can be used to do all kinds of things on websites. These can range from benign uses, like formatting a hamburger menu on mobile devices, to more nefarious uses like browser fingerprinting.

The problem comes when web developers try bundle megabytes upon megabytes of JS into their websites. This can make websites extremely heavy and slow to load, which doesn’t sit well with me as I’m all about optimised websites.

I don’t have any argument with this, but I stand by my opinion that JavaScript should only be used as a last resort. I’m probably a bit old-fashioned here. I think that HTML, HTTP, and server-side processing should be the first technologies a web developer uses. They work for just about everybody. If you’re on 56K dialup in some godforsaken Kansas farm town it’s likely to be the only web tech that will work. But if you’re on an unmetered 10 gigabit connection in New York City it will fly like a bat out of Hell.

Of course, raw HTML can be ugly unless you like your websites oedipal, so let’s slather some CSS on top of the HTML, HTTP, and server-side code so that it doesn’t frighten off the suits.

Wait? What’s that? We don’t want to render entire pages on the server side any longer because we’re getting 10,000 requests a minute, the server’s wheezing like Donald Trump at the eighteenth hole, and the DevOps team has threatened to unionize and do work-to-rule? OK, fine, let’s layer some AJAX calls on top of the raw HTTP methods and use those when the client side has enough processing power and sufficient bandwidth to handle it.

We used to call this approach “progressive enhancement”, and it worked when developers were given time and latitude to do their jobs and deliver performant, reliable software that solved legitimate use cases. The developers working on the BBC’s website called it “cutting the mustard”. They delivered a reasonable baseline experience in less than 25KB of data and less than ten HTTP requests, and then used feature detection to deliver a fancier experience to visitors that could handle it.

Of course, I’m not the BBC. I’m just some metalhead who codes for a living, writes crappy science fantasy, and insists on having his own website instead of being content with a social media profile or three. But I like sharing music videos and most of them are on YouTube.

This presents a problem. The default method for sharing a YouTube video in a more visually appealing manner than a plain link is to use an embed. YouTube encourages this by providing markup you can paste into your blog. It looks like this.

<iframe width="560" height="315" src="https://www.youtube.com/embed/DLzxrzFCyOs" frameborder="0" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture" allowfullscreen></iframe>

It looks easy, doesn’t it? Just past that snippet of text into your web page and boomshakalaka! You’ve got Rick Astley on your blog.

But there’s a catch. You see all that stuff in the “allow” property? That gives YouTube all kinds of device access that it shouldn’t need just to play “Never Gonna Give You Up”. It gets worse, though. For every YouTube embed you add to a page on your site, anybody visiting that page will end up downloading hundreds of kilobytes of JavaScript, much of it spyware analytics, just to play a video. Not to mention a bloated preview image that itself might weigh over 100kb.

a brown tabby cat with his tongue out
“Dude, there’s got to be a better way to share YouTube videos on your website than using an iframe that pulls in over 100KB of JavaScript. I’m just a cat but even I know better.”

Smudge is pretty smart for a cat who keeps forgetting to pull his tongue back into his mouth when he’s done washing himself. He’s right; there are ways to share YouTube videos without inflicting Google’s spyware on unsuspecting visitors.

It just involves work. Let’s consider that Rick Astley song that everybody is sick of hearing every time they click the wrong link (and never mind that it could be goatse). Its URL is https://www.youtube.com/watch?v=DLzxrzFCyOs. A preview image for this video is available at https://i.ytimg.com/vi/DLzxrzFCyOs/sddefault.jpg. sddefault.jpg is 640 pixels wide and 480 pixels tall, and its size is less than 15K.

Here’s the fun part: if you know a YouTube video’s URL, you can get its ID. If you have its ID, you can pull its standard definition preview image. It’s low-resolution, but good enough for our purposes, which is to provide a visual preview of a YouTube video inside a link to the video without using JavaScript.

a brown tabby cat yawning
“Hey, boss, why do we have to pull YouTube video preview images? Can’t we just hit https://i.ytimg.com whenever we need an image instead of self-hosting them?”

Purrseus isn’t as smart as Smudge. Then again, he’s still just a big kitten. Hopefully he’ll learn. What he’s talking about is called hotlinking. It’s generally a bad idea for the following reasons:

  • Every somebody visits your site, they’re hitting the other site too.
  • It takes longer for your site to load because you’ve got to wait for the other site.
  • You can’t cache data from other people’s sites.
  • It annoys sysadmins, who aren’t necessarily subtle but are quick to anger.
  • If the image gets moved or deleted, you’re shit out of luck.
  • A clever sysadmin could redirect your requests to something foul.
  • You wouldn’t want somebody doing it to your site.

How do I avoid hotlinking? I grab the preview image once and upload it to my site. Then I wrap the image inside a link with a caption instructing visitors to click the image if they want to watch the video. Doing it my way looks like this:

YouTube preview image
Click the image to watch “Never Gonna Give You Up” on YouTube.

The resulting HTML looks somewhat like this:

<figure>
  <a href="https://youtu.be/DLzxrzFCyOs?autoplay=1" target="_blank" rel="noopener">
	<img loading="lazy" width="640" height="480" src="/assets/images/yt-thumb-DLzxrzFCyOs.jpg" alt="YouTube Preview Image" />
  </a>
  <figcaption>Click the image to watch &#8220;Never Gonna Give You Up&#8221; on YouTube.</figcaption>
</figure>

I say ‘somewhat’ because I’m using WordPress and the actual HTML generated by WordPress might just be capable of giving Clive Barker nightmares. I’m as serious as a public explosive rectal prolapse here. If you right-click and select “view source” on the average WordPress site, well…

Kirsty Cotton just aced her front-end developer interview…

OK, I’m just having a bit of fun at my readers’ expense. WordPress-generated HTML isn’t terrible; there’s just a metric shitload of CSS classes involved that would have gotten in the way of my example and distracted from my point, which is…

You can provide a visually appealing YouTube preview that links to the original with nothing but HTML, some CSS, and a bit of elbow grease.

Smudge

I suppose, however, that you think it might be tedious to manually download a preview image every time you want to share a YouTube video. That’s what shell scripts are for. I don’t do this manually; I don’t get paid enough for that shit.

Instead, once I figured out how to do it consistently, I wrote a little shellscript called yttget (YouTube thumbnail get). It depends on curl and the display tool from ImageMagick—which is a brilliant and versatile toolkit once you learn to use it.

#!/bin/sh -e

# yttget (YouTube thumbnail get)
# © 2021 Matthew Graybosch <contact@matthewgraybosch.com>

# Permission to use, copy, modify, and/or distribute this software for
# any purpose with or without fee is hereby granted, provided that the
# above copyright notice and this permission notice appear in all
# copies.

# THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL
# WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED
# WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE
# AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
# DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA
# OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
# TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
# PERFORMANCE OF THIS SOFTWARE.

# usage: yttget https://www.youtube.com/watch?v=DLzxrzFCyOs

URL="$1"
ID=$(echo $URL | cut -d = -f 2)
FILE="${HOME}/Downloads/ytt-${ID}.jpg"
THUMB_URL="http://i.ytimg.com/vi/${ID}/sddefault.jpg"

curl ${THUMB_URL} --output ${FILE}

echo "Thumbnail available at ${FILE}"
echo "Video URL: https://youtu.be/${ID}?autoplay=1"
echo "Suggested Caption: Click this image to watch on YouTube..."

display ${FILE}

Yes, it’s absolutely trivial as far as shell scripts go, but it works for me and you’re welcome to copy the code, save it, make the file executable, and use it yourself.

Does this seem like overkill compared to using the embed code YouTube provides? Perhaps, but I honestly think that blindly using iframe snippets provided by corporate-owned platforms like YouTube is taking the easy way out and does a disservice to people visiting my site.

Besides, since I’m using WordPress and have learned to cope with the Gutenberg block editor, I can make my previews into reusable blocks. If you’re using a static site generator, or even building your site with m4 macros, shell scripts, and duct tape, it shouldn’t be hard to create a partial or macro that accepts a YouTube video ID.

But if you absolutely must use JavaScript, write it yourself. Don’t use it unless you’ve run into a problem you can’t solve without it. The people using your site might not thank you, but it might help you avoid some headaches down the line.