DEV Community

Marcus
Marcus

Posted on

AlpineJS compared to VueJS

AlpineJS 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 and intercooler.js/htmx, 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.

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

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 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:

<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>
Enter fullscreen mode Exit fullscreen mode

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.

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;
      });
    }
  };
}
Enter fullscreen mode Exit fullscreen mode

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

Check out the two codepens and compare them.

AlpineJS

💡 If you want to debug console.log(this.gists) it's pretty noisy. Checkout the AlpineJS Devtools extension, that is similar to the Vue Devtools.

VueJS

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 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

Top comments (0)