Fetching remote images with Eleventy

Following up on last month’s article about doing this in Hugo, we explain how to get there in a JavaScript-based SSG.


General note: This site’s appearance, configuration, hosting, and other basic considerations will change over time. As a result, certain content on this page could be at variance with what you’re currently seeing on the site, but the two were consistent when this post originally appeared.

Update, 2022-01-26: Please see the end of this post for additional info straight from the horse’s mouth, so to speak.

A few weeks ago, I described how a recent change to the Hugo static site generator (SSG) gives it the ability to fetch remote content for processing during the site-building process. In my case, I used it in the Hugo-based version of this site’s repository to grab tiny, low-resolution images from my free Cloudinary account and turn them into Base64-encoded low-quality image placeholders (LQIPs).

Well, this short follow-up shows how to do the same thing in the Eleventy SSG. The capability isn’t built into Eleventy, but a little code will make up for that. As I noted in my Eleventy-vs.-Hugo comparison slightly over a year ago:

. . . the same characteristic that makes Eleventy very much not an out-of-the-box solution — its being essentially a collection of npm JavaScript packages — also makes it much easier to adapt so it’ll suit your wishes and needs.

As in the Hugo example, we’ll do this in Eleventy by using a shortcode that we can reference in the site’s Markdown content. Please note that, to work with what we’re describing here, this Eleventy shortcode must be asynchronous — which, in turn, requires the shortcode to be in Nunjucks, Liquid, or .11ty.js JavaScript templating. You see, at least as of the initial publication of this post, those are the only three of Eleventy’s multiple templating languages that support async shortcodes.

But why does the shortcode have to be async in the first place? That’s because it uses the promise-based axios HTTP client to fetch the desired content. So, if you don’t already have axios installed in your Eleventy project, take care of that first:

npm install axios --save-dev

(This installs it as a development dependency, which is how I prefer to do it. However, if you don’t want to be that picky, it’s perfectly fine to install it as only a regular production dependency with npm install axios --save-prod. Eleventy won’t care.)

Then, in the shortcode, you have to require axios:

const axios = require('axios')

After that, we can do this within the shortcode’s module.exports section:

	async function getBase64(urlFor64) {
		const response = await axios
			.get(urlFor64, {
				responseType: 'arraybuffer'
		return Buffer.from(response.data, 'binary').toString('base64')

	// Then, earlier, we've defined the appropriate
	// LQIP's URL as `urlToGet`, so...

	let LQIP_b64 = await getBase64(urlToGet)

That last statement assigns to LQIP_b64 the Base64 representation of the LQIP, whose URL is supplied by urlToGet. Now we can use the LQIP_b64 variable within the CSS for the main image’s background div, as shown in this excerpt from the template literal which gets exported to any page that invokes the shortcode:

background: url(data:image/jpeg;base64,${LQIP_b64});

And there you have it. Using your browser’s Inspector tool on nearly1 any image shown within the site will reveal the resulting HTML and CSS, letting you see What The Shortcode Hath Wrought — which, now, will be true regardless of whether the site is on Eleventy or Hugo at the time.

Acknowledgment: I am especially grateful to two specific sources for making this post possible: an extraordinarily helpful conversation I had a few days ago with “Aankhen” in the Eleventy Discord community; and, to a lesser extent, a Stack Overflow-based answer from several years ago. As I told “Aankhen”: “Async and all that are pretty much Greek to me, no matter how much I read others’ articles about that stuff.”

And there’s more (2022-01-26)

The official Eleventy Twitter account graciously retweeted my announcement of this post and added the following, which I pass along for your further edification:

I would also note that the official Image plugin can do this as well!

Use dryRun: true to opt-out of file writing and include a `buffer` property in your output!
2:38 PM • January 26, 2022 (UTC)

  1. The lone exception — i.e., the only image on the site which doesn’t use this shortcode when the site is running on Eleventy — is the “My pet cat” image sample near the bottom of my post, “Using Eleventy’s official image plugin.” As that post’s title implies, in such cases this particular image uses a different shortcode that’s based on the Eleventy Image plugin. ↩︎