How Jampack optimizes our Eleventy website and improves performance
Tags: jampack, jamstack, webdev, tutorial
Published: 2023-06-20 14:00:00

I’ve written previously about the performance outcomes of [transitioning cloudcannon.com to Eleventy](https://cloudcannon.com/blog/cloudcannon-com-is-now-built-with-eleventy/), which include perfect Lighthouse scores and excellent Core Web Vitals scores. We’re now several weeks into the flow of building our site pages, as well as drafting, editing, and publishing blog posts on Eleventy with CloudCannon as our CMS, and it’s been, as we expected, a joy to work with. But I’ve also wanted to dig a little deeper into each of the tools we used to achieve our performance gains, and to share how we configured these tools. So let’s get started, shall we?

One of the easiest tools to include in our new stack was [Jampack](https://jampack.divriots.com/) from [<div>RIOTS](https://divriots.com/), who you may know as the developers of [Backlight](https://backlight.dev/); the Figma plugins [story.to.design](https://story.to.design/), [html.to.design](https://www.figma.com/community/plugin/1159123024924461424/html.to.design), and [code.to.design](https://www.figma.com/community/plugin/1222554159237609568/code.to.design); and the online IDEs [WebComponents.dev](https://webcomponents.dev/), [LWC.studio](https://lwc.studio/), and [Components.studio](https://components.studio/). Altogether, these tools are used by hundreds of thousands of developers and designers — and for a reasonably small core team, <div>RIOTS punches well above their weight.

## What is Jampack?

In brief, Jampack is a post-processing tool that takes the output of any static site generator and optimizes it for user experience and Core Web Vitals scores. Jampack is one of [several open-source tools](https://divriots.com/opensource) that the <div>RIOTS team have created. It was released at the end of January 2023, and as soon as we heard about it, we immediately started testing it out.

I’ll go into more detail below, but in brief, **I would recommend Jampack to any CloudCannon user**, or indeed anyone with a static site.

Why the blanket endorsement? Primarily because Jampack is SSG-agnostic. While we use [Eleventy](https://cloudcannon.com/eleventy-cms/) to build cloudcannon.com, everyone who works at CloudCannon uses a range of static site generators to build our personal sites, and Jampack works with all of them. (Even, of course, those built without an SSG — because all Jampack requires is a folder containing an output static site.)

## What does Jampack do?

Quite a lot, really! Here’s a quick summary of the major steps Jampack takes when it’s run:

### 1) Optimize images

Jampack compresses images with the high-performance [`sharp`](https://sharp.pixelplumbing.com/) processing module; `JPEG` and `PNG` images are converted to `AVIF` and `WebP`. Jampack also creates responsive images for smaller devices, and assigns image dimensions to avoid any [CLS issues](https://web.dev/optimize-cls/#images-without-dimensions).

### 2) Optimize above the fold

Jampack introduced a new `<the-fold></the-fold>` mark that you can add to your HTML to mark where a page’s fold should be. Based on this mark, Jampack prioritizes images above the fold and turns them into [progressive JPEGs](https://www.thewebmaster.com/progressive-jpegs/) for a better user experience. If images above the fold are smaller than 1500 bytes, Jampack embeds the image into html using [data URLs](https://developer.mozilla.org/en-US/docs/Web/HTTP/Basics_of_HTTP/Data_URLs).

Below the fold, Jampack lazy-loads all images and iframes.

### 3) Compress all assets

In its second and final pass, Jampack compresses all untouched assets, keeping the same name and same file format for each:

<table>

<thead>

<tr>

<th scope="col">Extension</th>

<th scope="col">Compressor</th>

</tr>

</thead>

<tbody>

<tr>

<td>.html, .htm</td>

<td>html-minifier-terser</td>

</tr>

<tr>

<td>.css</td>

<td>Elements of both csso and lightningCSS</td>

</tr>

<tr>

<td>.js</td>

<td>swc</td>

</tr>

<tr>

<td>.svg</td>

<td>svgo</td>

</tr>

<tr>

<td>.jpg, .jpeg</td>

<td>sharp</td>

</tr>

<tr>

<td>.png</td>

<td>sharp</td>

</tr>

<tr>

<td>.webp</td>

<td>sharp</td>

</tr>

<tr>

<td>.avif</td>

<td>sharp</td>

</tr>

</tbody>

</table>

Check out the [Jampack docs](https://jampack.divriots.com/) for more detail, and also the available [CLI options](https://jampack.divriots.com/cli-options/).

## How we use Jampack

To add Jampack to cloudcannon.com, we simply added a single line to our [postbuild](https://cloudcannon.com/documentation/articles/extending-your-build-process-with-hooks/) file, which runs on our production site. (While we could run Jampack on our staging branch, or on every single branch we make, we’re privileging the production branch here, and in the process shaving off a _very_ small amount of post-build time when we’re working on new site content earlier on in our publishing workflow.)

Because Jampack optimizes above the fold, we’ve also built a specific [Bookshop](https://github.com/CloudCannon/bookshop) component to indicate where the fold should be. If you use Bookshop to manage your components and would like to do the same for your site, here’s that component’s data file:

```yaml

spec:
  structures:
    - blocks
  label: "Fold"
  description: >-
    Indicates where the page fold is.
    Everything below this point will be lazy loaded.
  icon: folder_open
  tags: []

```

This component, when added to a page by editors using CloudCannon’s Visual Editor, simply inserts the following between other page components:

```html

<the-fold></the-fold>

```

It’s a really simple step, but it gives me and our team of editors a lot of control: we’re able to precisely determine which parts of a page should be more heavily optimized, and which should be lazy-loaded.

![](https://cc-dam.imgix.net/Fold-component-block+%282%29.png)

As you can see above, we generally set the fold at the end of the first ‘container’ component on each page. (We've set our Bookshop components to be shown or hidden, depending on mobile, tablet, or desktop breakpoints; to make sure that Jampack optimizes above the fold for all device types, we set the fold under all device-specific versions of that top component.)

## SSG chaining

Jampack fits into a workflow we refer to internally as ‘SSG chaining’ — like our open-source search tool [Pagefind](https://pagefind.app/), and our translation management tool [Rosey](https://rosey.app/). The general idea of SSG chaining, as we use the term, is that static sites can (and should) stay simple — and static site generators shouldn’t have to ship and build every single possible feature or optimization strategy. Instead, users can first build their sites using any SSG they like, and then ‘chain’ a series of post-build tools on the static output.

Rather than building an optimizer or a search plugin for a dozen different SSGs, tools like Jampack are able to share the benefits they offer across the whole static site ecosystem. And when a newer, shinier SSG comes along, there’s no question that these SSG-chaining tools will still work on them: because there’s not the sense of lock-in that can come with plugins we depend upon, developers are freer to shift between static site generators, while still using their preferred post-build tools.

## Final thoughts

Though I think we’re seeing some major development tools and frameworks feature-creep towards full meta-framework, jack-of-all-trades, gotta-catch-them-all status, Jampack reminds us that it’s possible to escape that particular rat race. Or at least to sidestep it, and give every developer the same Core Web Vitals advantages, regardless of the tools they choose to build their static sites.