Alpine JS

  • UpdatedApr 30, 2021

  • Reading time2 min

I my last update I briefly mentioned choosing Alpine as a way to fetch the I my last update I briefly mentioned choosing Alpine as a way to fetch the listening statistics, on the journal page. I previously used SWR, a plug-in created by the Next team. Without React I had to find a new method way. Firstly I wanted to find a lightweight library to do this, while possible I did not want the headache of writing vanilla JS, which might mean finding a compiler and adding extra build steps.

Recently I’ve been hearing lots about Hotwire, a suite of libraries that to build reactive applications using declarative markup and semantic JS. This is super interesting and an excellent example of progressive enhancement. However, I would still need to compile the JS, which means choosing a build tool etc. Ugh! Also the JS bundle is quite large for such a small application.

Fairly soon after getting hyped about Hotwire I stumbled upon a lighter, but very philosophically similar alternative, Alpine!

Alpine shares a similar declarative markup syntax, but removes the need for the separate JS controllers, everything is inline. There is also no need to install any dependency, you can simply include a <script> tag in the document head. It’s about 8kB compressed, super compact.

The Alpine documentation has plenty of useful examples to get started with, for example tabs:

<div x-data="{ tab: 'foo' }">
	<button :class="{ 'active': tab === 'foo' }" @click="tab = 'foo'">Foo</button>
	<button :class="{ 'active': tab === 'bar' }" @click="tab = 'bar'">Bar</button>

	<div x-show="tab === 'foo'">Tab Foo</div>
	<div x-show="tab === 'bar'">Tab Bar</div>
</div>

For my use case I can simply store the result of a fetch in the state (x-data), then pass the data to a string. It’s also simple to add an empty state using an isLoading boolean:

<section
	x-data="{ totals: {}, isLoading: true }"
	x-init="fetch('/api/music/lastweek')
          .then(response =>  response.json())
          .then(json => { isLoading = false; totals = json })"
>
  <p x-show="isLoading">Loading...</p>
  <a href="https://open.spotify.com/user/lkemitchll"
	   target="_blank"
	   rel="noreferrer"
	   x-show="totals.tracks"
	   x-text="`${totals.tracks} Tracks, from ${totals.albums} Albums`"
  ></a>
</section>

I’m a big fan of Alpine and its brutalist approach, the entire functionality is laid bare in a readable and sensible format. Inspecting the source code in a browser reveals the inner workings in a readable and accessible format. No obfuscation or minified JS to trawl through. It’s also very easy to get started with, and pairs with Eleventy perfectly.