AlpineJS compared to VueJS
Tags: alpine, vue, javascript
Published: 2020-05-17 19:53:40

[AlpineJS](https://github.com/alpinejs/alpine) calls itself _A rugged, minimal framework for composing JavaScript behavior in your markup_ and asks you to _think of it like Tailwind for JavaScript._ 

While I have little to no idea what the first phrase means I know what to think of the second, even if I've never used Tailwind CSS so far: **stuff a lot of data into HTML attributes**.

**I'm fan of that!** I'm fan of [Unpoly](https://unpoly.com/) and [intercooler.js](https://intercoolerjs.org/)/[htmx](https://htmx.org/), and I love the approach of writing HTML and add some javascript behavior. Heck, I'm still a fan of jquery! There is nothing wrong with that.

So I set out to give AlpineJS a try and while I expected to work with server-side rendered HTML fragments, I ended up consuming JSON. In this regard, AlpineJS is closer to VueJS (and it's not hiding the fact that some of the syntax is heavily borrowed from Vue) and therefore I just wrote a little thing one in AlpineJS and one in VueJS, to compare them.

It has been a little bit of a challenge to understand the variable scope, since all the AlpineJS examples work with fixed JSON values and not dynamic data, fetched from an external data source. The one example that showcases `fetch` shows it directly used in an attribute, which w a little bit too much simplified.

```js
<div
    x-data="alpineInstance()"
    x-init="fetch('https://jsonplaceholder.typicode.com/users')
        .then(response => response.json())
        .then(data => users = data)">
        <!-- -->
</div>
```

**TL;DR**

So **how would I `fetch()` data on `x-init` and transform it?**

For my experiment I decided to 

- pull a list of Github Gists,
- parse the description [Lepton - GitHub Gist Client](http://hackjutsu.com/Lepton/) style
- save them into `sessionStorage` to get around the API rate limit while testing (60 calls per hour)
- and just show them.

Bonus: use TailwindCSS.

The barebone HTML looks like this:

```html
<div x-data="gistsData()" x-init="init()">
  <ul>
    <template x-for="gist in gists" :key="gist.id">
      <li>
        <a x-bind:href="gist.html_url" x-text="gist.parsed.title"></a>
      </li>
    </template>
  </ul>
</div>
```

`x-data` declares the scope of the component, means all the data and methods you want to use in this component. In Vue, this is the `data`, `methods` and maybe `computed` fields.

`x-init` is a method that run on initialization or just some JSON. In this case it's a method, that fetches the data and saves the response in the `gists` key so it's accessible in the HTML. 

```js
function gistsData() {
  return {
    title: 'Latest Gists',
    gists: [],
    init() {
      // Testdata
      /*
        this.gists = [
          {
          "id": "8f6af49ffe693c15faca67a7f3bf1a31",
          "html_url": "https://gist.github.com/8f6af49ffe693c15faca67a7f3bf1a31",
          "description": "[Lepton Title Style] Some description and #hash #tags"
          }
        ];
        return;
      */

      // get gists
      fetch('https://api.github.com/users/marcus-at-localhost/gists')
        .then(response => response.json())
        .then(response => {
          this.gists = gists;
      });
    }
  };
}
```

So this is the most basic example how to structure your code.

Check out the two codepens and compare them.

## AlpineJS

{% codepen https://codepen.io/localhorst/pen/vYNVxyX default-tab=js,result %}

💡 If you want to debug `console.log(this.gists)` it's pretty noisy. Checkout the [AlpineJS Devtools](https://github.com/Te7a-Houdini/alpinejs-devtools) extension, that is similar to the Vue Devtools.

## VueJS

{% codepen https://codepen.io/localhorst/pen/ExVdByo default-tab=js,result %}

And Tailwind?  In its most basic form, it's the Atomic CSS approach, similar to Bootstrap, down to some of the same class names, like `mt-5` for `margin-top: x;`.  Just add classes as if you would write inline css.

You can also ["compose" custom classes](https://tailwindcss.com/docs/functions-and-directives/#apply) from those micro classes, almost as if you were writing CSS. :-o

I can see that this is fun to use, but it's not superior to other frameworks. Use whatever works for you.

Also on my [blog](https://marcus-obst.de/blog/alpinejs-vuejs)