We The Protesters
The possum is Eleventy’s mascot

Eleventy Documentation

This is an older version of Eleventy. Go to the newest Eleventy docs (current path: /docs/plugins/cache/) or the full release history.

Cache Assets #

Fetch network resources and cache them so you don’t bombard your API (or other resources). Do this at configurable intervals—not with every build! Once per minute, or once per hour, once per day, or however often you like!

With the added benefit that if one successful request completes, you can now work offline!

This plugin can save any kind of asset—JSON, HTML, images, videos, etc.

Installation #

npm install @11ty/eleventy-cache-assets
Important Security and Privacy Notice

This plugin caches complete network responses. Unless you’re willing to perform a full review of everything this plugin caches to disk for privacy and security exposure, it is strongly recommended that you add the .cache folder to your .gitignore file so that network responses aren’t checked in to your git repository.

Are you 100% sure that private e-mail addresses aren’t being returned from a cached API? I’m guessing no—add .cache to your .gitignore file. Right now. Do it.

Usage #

Cache a JSON file from an API #

Consider the following example, perhaps in an Eleventy Global Data File.

const Cache = require("@11ty/eleventy-cache-assets");

module.exports = async function() {
let url = "https://api.github.com/repos/11ty/eleventy";

/* This returns a promise */
return Cache(url, {
duration: "1d", // save for 1 day
type: "json" // we’ll parse JSON for you

Options #

Change the Cache Duration #

After this amount of time has passed, we’ll make a new network request to the URL to fetch fresh data. The duration option currently supports the following shorthand values:

Type #

Cache Directory #

The directory option let’s you change where the cache is stored. It is strongly recommended that you add this folder to your .gitignore file.

Read the Important Security and Privacy Notice.
const Cache = require("@11ty/eleventy-cache-assets");

Cache("https://…", {
directory: ".cache"
Eleventy Cache Assets can work inside of a Netlify Function (or AWS Lambda) by using directory: "/tmp/.cache/".

Remove URL query params from Cache Identifier #

(Version 2.0.3 and newer) If your fetched URL contains some query parameters that aren’t relevant to the identifier used in the cache, remove them using the removeUrlQueryParams option. This is useful if an API adds extra junk to your request URLs.

const Cache = require("@11ty/eleventy-cache-assets");

Cache("https://www.zachleat.com/img/avatar-2017-big.png?Get=rid&of=these", {
removeUrlQueryParams: true

What happens with a request fails? #

  1. If this is the first ever request to this URL (no entry exists in your cache folder), it will fail. Use a try/catch if you’d like to handle this gracefully.
  2. If a failure happens and a cache entry already exists (even if it’s expired), it will use the cached entry.
const Cache = require("@11ty/eleventy-cache-assets");

module.exports = async function() {
try {
let url = "https://api.github.com/repos/11ty/eleventy";

/* This returns a promise */
return Cache(url, {
duration: "1d",
type: "json"
} catch(e) {
return {
// my failure fallback data

Running this on your Build Server #

If you’re attempting to use this plugin on a service like Netlify and you are definitely not checking in your .cache folder to git, note that the cache will be empty with every build and new requests will go out. It’s important to be aware of this, even if it’s what you want for your production build!

More Examples #

Cache a Remote Image #

This is what eleventy-img uses internally.

const Cache = require("@11ty/eleventy-cache-assets");

module.exports = async function() {
let url = "https://www.zachleat.com/img/avatar-2017-big.png";
let imageBuffer = await Cache(url, {
duration: "1d",
type: "buffer"
// Use imageBuffer as an input to the `sharp` plugin, for example

// (Example truncated)

Fetch Google Fonts CSS #

Also a good example of using fetchOptions to pass in a custom user agent. Full option list is available on the node-fetch documentation.

const Cache = require("@11ty/eleventy-cache-assets");

let url = "https://fonts.googleapis.com/css?family=Roboto+Mono:400&display=swap";
let fontCss = await Cache(url, {
duration: "1d",
type: "text",
fetchOptions: {
headers: {
// lol
"user-agent": "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_5) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/74.0.3729.169 Safari/537.36"

Fetching GitHub Stars for a repo #

Manually store your own data in the cache #

You probably won’t need to do this. If you’d like to store data of your own choosing in the cache (some expensive thing, but perhaps not related to a network request), you may do so! Consider the following Global Data File:

const {AssetCache} = require("@11ty/eleventy-cache-assets");

module.exports = async function() {
// Pass in your unique custom cache key
// (normally this would be tied to your API URL)
let asset = new AssetCache("zachleat_twitter_followers");

// check if the cache is fresh within the last day
if(asset.isCacheValid("1d")) {
// return cached data.
return asset.getCachedValue(); // a promise

// do some expensive operation here, this is simplified for brevity
let fakeTwitterApiContents = { followerCount: 1000 };

await asset.save(fakeTwitterApiContents, "json");

return fakeTwitterApiContents;

Change Global Plugin Concurrency #

const Cache = require("@11ty/eleventy-cache-assets");
Cache.concurrency = 4; // default is 10

Command line debug output #

DEBUG=EleventyCacheAssets* node your-node-script.js
DEBUG=EleventyCacheAssets* npx @11ty/eleventy

Other pages in Plugins: