250 comments

[ 3.5 ms ] story [ 224 ms ] thread
Alpine.js is seeing an increase in utility as it pairs nicely with htmx[0], Phoenix LiveView[1] and the likes for lightweight interaction that doesn't require the server.

[0]: https://htmx.org

[1]: https://github.com/phoenixframework/phoenix_live_view

Actually, HTMX has a fundamental flaw if it comes to history restoration: In some scenarios it takes snapshots of the DOM for history navigation, just before navigating away from a page. If the DOM was previously modified by other JS libraries like Alpine, jQuery or any other tool, these changes end up in the history snapshot, leading to unexpected results [1]. I've had a much smoother experience with Alpine + swup [2]. Disclaimer: I became a maintainer of swup this year.

[1] https://github.com/bigskysoftware/htmx/issues/1015

[2] https://github.com/swup/swup

To illustrate:

Say you have a collapsible menu (Burger etc.) which you just implement with a simple CSS based toggle. You open the menu and then navigate to a different page (via htmx). All good. But now your back button will break because it will send you to the previous page but with the menu open.

In this particular case it's _kind of fine_ depending on your navigation concept and design. It might even be a feature! But this behavior just proliferates little workarounds and caveats and can lead to surprising UI bugs, especially if you need some state management in-memory etc.

So htmx is great the less JS you use on top of it, except you are very aware of how it operates and how you interact properly with it's events. It's a very well designed and small library overall - with caveats.

I don't know as much about the underlying issue as the sibling, but I've also found that LiveView and AlpineJS interact in complex and unexpected ways in the case of components. The only sane way I found to integrate them was to make an Alpine-based component which is solely responsible for rendering itself, and then communicate updates back and forth with the LiveView process via custom events. That works but it's fairly heavyweight.
I would just make the jump to JS Commands if you're able.
I would like to be able to use Alpine in precisely the cases where the JS commands aren't enough. This case was one of those accursed custom form controls that designers love to come up with (a dropdown with checkboxes and a search filter).
Ha, right. I was in that same position. Unless you're working with a fixed, non-search, massive dataset, I found the performance is just fine doing it in pure Liveview over the socket, but I don't know your situation.
Yeah, indeed, doing it in pure LiveView is a realistic option, but it does degrade the user experience for e.g. someone on a crappy 3G mobile connection.
When I see tools like this, I remember once again what a great revolution angularjs was. If people are happy with tools like this, of course that's important, but I don't think I'll understand the logic of writing javascript code in an attribute.
I tried Alpine.js a very long time ago. Managed to build some small web apps with Haml[0], but never everything big. It's generally very easy to use but when it comes to scaling it doesn't scale very well. Building a todo app with it requies many lines of JS objects, combined with that every object is defined in a string makes the code look a bit ugly. Useful for prototyping and small web apps if you dont want to use complex stuff.

[0]: https://haml.info/

I was fully expecting Alpine Linux running in a browser when clicking the link. I am disappoint.
I was expecting either the Alpine Linux, or a port to js of the mail client. :)
Of course it's Bellard. I wish I had like, a day with him, just asking whichever questions I want.
(comment deleted)
His email is right there on his website, I say just write to him!
Yeah - 100%. I have pulled this off successfully with some crazy household names in tech. I really value some of those random emails - I go back and read them from time to time.

People are often really chill and kind about answering questions and love to help people who take a genuine interest in their work!

Yes, but imagine the luxury of casually hanging around with Bellard for a day and just ask random stuff you come to think of, no regrets.
Is what?

You forgot the rest of the headline.

I use this in one project but its bundle size is very large for what it does. I think Preact is usually a nicer option (and no, it doesn't require build tools and NPM if your IDE of choice is notepad) with a React compatible API.

It's 3KB. Even less if you opt to not have any React compatibility at all.

Alpine is 13KB.

https://bundlephobia.com/package/alpinejs@3.10.5

https://bundlephobia.com/package/preact@10.11.3

What is wrong with build tools?
More complexity and friction.
I think it's more that these libraries are sometimes used in projects that aren't already using a build tool.
The largest, most painful and apparent issue with JS related build tools is that they change and break. Frequently.

And no, `package.lock` is not enough of a solution, because you will have to update dependencies at some point. Congrats, you now have multiple moving, breaking parts in your dependency tree that throw the weirdest and unrelated errors. So you're hunting down github issues, workarounds and patches, while still not really knowing what the problem was. The bonus here is that you need to remove these workarounds at some later point because your build tools and libraries have fixed the issues, so your code breaks again with very fun error messages or just straight up opaque and weird behaviors.

At some point we have to ask why we're doing this to ourselves. It's not fun at all.

Agreed. Try inheriting a project that hasn’t been updated for a few years. Between the absolute dependency hell, and major breaking changes, there is huge temptation to just rewrite the whole thing.

Even a basic application requires layers upon layers of dependencies. Many of them are not as mature as people like to think either.

they change and break. Frequently.

Any notable examples? (apart from that “force everyone ESM overnight because we feel like” movement)

I have encountered a mix of several weird bugs and breaking changes with gulp, webpack, rollup and what ever Nextjs uses. Also build related bugs with several popular libraries and the resulting versioning and dependency issues. NPM has disappointed me in similar ways at least a couple of times too. Babel is its own hell.

Basically touching a JS project that hasn't been updated monthly is incredibly anxiety inducing.

And now there are several new build tools since a relatively short while, which makes the issue even worse. They might be improvements in some dimensions but they all invent their own little world again, promising this or that. But it all sounds so familiar and I already lost trust.

I'm proud to say I recently published a library on npm and decided to specifically deliberately not publish anything other than ESM. Now bundle sizes are significantly smaller.
That’s the right thing to do. The issue that I mentioned included switching suddenly in highly depended-on packages without waiting for major end-user tools to catch up, splitting NPM across ESM for few months. It was a deliberate and non-systematic action. That’s why it’s worth ignoring it here.
Which build tools churn this badly, exactly?

Rollup has always been a straightforward path. Vite (built on rollup) is super clean. Before that even, webpack was relatively stable between versions.

If you just used Gulp / Grunt / Browserify I am a little more sympathetic, especially with Grunt / Gulp, but I always felt their limitations were obvious.

Browserify somehow managed to snatch defeat from the jaws of victory IMO

I think almost of these are on the list of past and present enemies. I haven't used Vite but I have better things to do than change the build tool in dozens of projects a year without any guarantees that it will not break like the rest of them.
if you adopted vite from 1.0, you wouldn't have a need to change build tools in dozens of projects a year. Its really stable. Same with rollup. Webpack (was?) a little less stable, but it didn't churn at that rate either.

I'm just not sure where the churn is from. If you're talking about meta frameworks, like create-react-app, that churn alot and change things underneath, I get it, though with tools like that, one should always seek to stay on the happy path only, as its otherwise a recipe for disaster.

Seems like I didn't win in the JS build too lottery then.
Break? I don't agree.

Change, sure. We've had browserify, parcel, rollup, webpack. Then the next wave hit with snowpack, esbuild, vite, lasso, turbopack etc.

There's a few that have hung around like rollup and webpack, but there's definitely a constant feel of chasing the dragon when it comes to js bundlers/builds, if not JS tooling as a whole.

Everything you said is true, but it's not limited to JS once you add 'package.lock' isn't a solution.

I've had compatibility issues with rebar, rubygems, pip, go modules and many more.

Once you're pulling in third party dependencies and the tools that manage them - in any development environment - you open yourself up to these issues. At some point, you have to update dependencies and/or tools (for security reasons if nothing else). And at some point, either the dependencies or the tools will break in a way that has you hunting down issues and workarounds that are outside the scope of what you're actually trying to accomplish.

Is JS significantly worse in this regard? It does seem like the propensity for many small packages increases the surface area of things that can go wrong, but that doesn't seem to be a flaw in the tooling.

The problem is that if your underlying stuff, like npm, webpack, babel or w/e changes or breaks, then _everything else_ breaks too. _All_ your dependencies can have potential issues. Meaning you have to update them and boom you code breaks too now, because someone decided to change the API.

And yes that means that bigger surface area leads to more problems.

This is less severe if you are only working on few projects at a time that you gradually update. It still sucks and is completely unnecessary, but only in tiny bits over a spread out time period.

However if touch code from just a year ago, then you might get some of these fun, breaking changes and bugs. Even more fun if you're not familiar with the build tool, or the packaging tool, because there are a dozen of those around as well and someone decided to use X at the time because why not. And you need a specific version of those too.

The Go modules thing is similarly painful, but it's not the best example of what I describe, because there is a very clear cut change from the previous way of doing things. It sucks but there is a clear path forward. With a JS project you get the feeling that you are walking on a minefield.

JS is significantly worse. npm, yarn, webpack, babel, rollup, vite etc etc. Too many dependencies. Too many breaking changes. if build fails, error messages are horrendously cryptic.
Absolutely nothing and I advocate and push for them wherever possible.

But I mentioned them for the usually very vocal crowd on HN (and others) that dominate any JS orientated conversation by pissing and crying that build tools exist.

Apparently, to this crowd, the act of compiling code is perfectly OK everywhere else but a travesty to need or want to do any of that for software that runs in a browser. Weird.

Build and dependency management is the worst part of the javascript ecosystem. Other languages do this much better. We're not against build tools for javascript. We're against bad ones. I'm only against adding a build tool when it's a small project that shouldn't require that complexity. I've seen projects where maintaining the build setup was more work than maintaining the code.
Yes, I've seen that too and it's a testament to how bad the ecosystem is.

However, the kinds of problems that existed in 2015 thanks to detracting tools like WebPack and Babel don't really exist now with the fact that browsers support ES modules and Node is dragging its heels but now mostly supports ES modules.

With things like typescript and vite I now never have the problems that used to be common. In fact when I see people creating brand new projects in 2023 using WebPack I cry a little in side.

At some point having a bad tooling experience can't be solely blamed on the tools. It's a choice.

Can you use Preact to build on server-rendered HTML?
I have. We used stimulusjs otherwise and wrote a controller that took in a component name and JSON props (embedded in HTML as a data attribute).

It works well. You end up with HTML like:

<div data-controller=“component” data-name-component-value”example” data-props-component-value=“{a: 1}”></div>

I’m all about minimizing bundle size but if your project is at the point of optimizing for 10kb, I’m pretty sure you’re working on the Mars Rover. ;)
Or for people with bad connections. If you expect high latency it can be worth it to embed js code to avoid the additoinal roundtrip. 10kb makes a big difference for that.
Which sites do that for any meaningful reason? I see this argument often, but have a hard time either coming up with an idea of a business for which it would be non-marginally profitable or finding a real app/site which does that to cover the last mile of its world-wide scale.

Until that I believe this argument is equivalent to “what about Mars”. By supporting dead slow connections on Earth you simply support them to remain so.

> Which sites do that for any meaningful reason?

Literally none...this is just the argument of contrarians or people who've only ever worked on personal projects who take offense to real applications used by actual audiences.

In itself 10kb doesn’t make a difference. But it adds up so that this mindset can lead to noticeably faster pages.
As someone who has shipped thriftily-sized sites targeting developing countries, what you're describing is a needlessly extreme optimization. Inlining 3kb of data vs. 13kb would be a nearly unnoticeable difference for even the worst connections – like in Guinea, whose median download speed is around 3mbps.

Inflating the document size does impact paint time, but it scarcely matters here.

I'm currently on a roaming cell phone connection where T-mobile has graciously given me 256 Kbps down. That actually would be a noticeable size difference. I don't have a deeper point, just thought it was funny that I would love a 3 Mbps connection right now.
There are a lot of places in Europe where you won’t get 3mbits with your phone.
Bad advice.

You don't embed same piece of code on every page request but instead you make the code cached on first download.

Depends on users and usage. If most visitors haven’t been to your site in a while and visit few pages it can be worth embedding.
Chances are you’ll end up writing more than 10kb of custom JS to make your components work. Alpine comes with basic batteries already included.
Warning: Libraries like this don't work well with tight CSP policies.

See. https://alpinejs.dev/advanced/csp

Yeah, this is the dealbreaker for me with alpine.js and htmx.

And I wouldn't even say "tight CSP" as much as "standard CSP." To make alpine.js play nice with CSP, you have to allow unsafe-eval, which severely weakens your protection against XSS.

alpine.js claims to have a compatibility build with CSP, but it's not officially available, doesn't fully work, and the parts that are broken in the CSP build aren't documented.[0]

htmx works under CSP, but it opens a new vector for attackers to inject JS into your page, which effectively neuters CSP.[1]

[0] https://github.com/alpinejs/alpine/discussions/1944

[1] https://htmx.org/docs/#security

Is there a minimalist js library you would suggest that is better for security? Mithril?
I've desperately searched for one, but I can't find anything. Stimulus[0] I believe is compatible with CSP, but I've found that it's more work than just writing vanilla JS.

I've heard good things about mithril, but I've never tried it.

[0] https://stimulus.hotwired.dev/

Regarding htmx https://htmx.org/docs/#security

> htmx allows you to define logic directly in your DOM. [...] One concern with this approach, however, is security. This is especially the case if you are injecting user-created content into your site without any sort of HTML escaping discipline.

You should, of course, escape all 3rd party untrusted content that is injected into your site to prevent, among other issues, XSS attacks. Attributes starting with hx- and data-hx, as well as inline <script> tags should be filtered.

That's been SOP for web development for aeons. I'd say the rewards vastly outweigh the costs. Not a deal breaker for me.

>That's been SOP for web development for aeons. I'd say the rewards vastly outweigh the costs. Not a deal breaker for me.

You should always sanitize inputs and encode outputs, but it's difficult to get that right 100% of the time. With CSP, you have a pretty robust safety net against XSS for when you encode user-controlled data incorrectly. With htmx, you're forfeiting the safety net.

I understand that not everyone wants to use CSP because a lot of libraries break it, but to me, giving up CSP is a pretty big sacrifice.

I agree that htmx warrants an extra level of awareness as to the loss of that safety net. Especially if your encoding/escaping is done manually and is very localized (i.e. you explicitly call escaping functions from your templates or other output functions), In such cases, CSP is crucial.

That been said, that's not how XSS has typically been handled. Usually, those encoding/escaping steps are already made part of the tight Request/Response stack in the backend (e.g. as middlewares, as part of a data mapper library, or as a filter activated on the template engine or Response library). Also, this is usually a default behavior that often requires to be explicitly disabled. And as long as you don't have some "rogue" I/O processes completely outside of that pipeline, you're set.

Because of this typical setup, I tend to consider CSP a mere redundancy for XSS. If you lose that extra protection due to htmx, what you gain seems far more valuable to me.

> That's been SOP for web development for aeons. I'd say the rewards vastly outweigh the costs. Not a deal breaker for me.

Very true, but it seems from my reading of the docs that standard escaping mechanisms are not enough. i.e. you also need htmx-specific ones.

> Attributes starting with hx- and data-hx ... should be filtered.

Exactly my experience as well.

IMO, Libraries like these should state their CSP compatability upfront, Any JavaScript minimalist who are likely the target developers for these libs likely has full CSP implementation on their back-end.

Telling our library isn't compatable with CSP in a footnote seems disingenuous.

I’d argue the “good” route shown as an example should be the “default” way you use it. The alternative is arguably worse in most ways imho.

Edit: not used their Alpine or Alpine-CSP, just commenting on the example syntax in the link shared by GP.

Similar arguments apply to all CSS-in-JS approaches to. I've made sure all projects were CSS-in-CSS moving forward.
Ive been waiting for a new JavaScript framework
...all week.
...5 minutes. (however alpine is hardly new, not sure why it's even posted unless it was a changlog, but it was the main page, etc...)
Alpine is a few years old already
Mods can we add [legacy] to the title please ?
Never seen that be a convention here, and what makes you think this is legacy? who decides that? Is Linux legacy too?
I think he/she is joking
Because of JS churn. A few years old? Might as well be jQuery!
I’m picturing the VC pitch deck for a LLM-based tool that updates your web properties from yesterday’s JS framework to today’s JS framework, nightly.
DAMN. Saves a lot of code and effort for most websites.

Very easy to use too!

This is pretty neat. I think being lightweight, and having a very small API is important.

But honestly, at this point function-style JSX/TSX is hard to beat in terms of API. There's basically no DSL to learn (`x-for`, `x-if` and so on), you just use plain old JS with all of its existing capabilities. And it's just a JS function, in come props, out comes HTML. You technically don't even need JSX to do this, it's just syntactic sugar over plain JS function calls.

Sure, React is bloated, its full API has huge surface area (that you almost never need), and there are some icky parts (state, side effects, basically the whole hook system is ehh and doesn't fit the functional paradigm).

There's definitely room for improvement there, but I think it will probably not come from React, but some other JSX-based framework (Preact and SolidJS suffer from some of the same issues).

In any case JSX is going to be super hard to beat IMO.

There seems to be an unoccupied design space for a mix between JSX and shell languages. Both effectively compose concurrent processes.
I don't see how JSX has anything to do with processes, much less concurrency.
I think what he meant was that the style of JSX does lend itself well to parallelism (e.g different subtrees can execute in parallel), though to the best of my knowledge no such implementation exists (maybe something can be done with WASM or WebWorkers)
Any componentized UI system can do that though, in theory. JSX isn't special in that regard.
JSX gives you the appearance of HTML with a boat-load of unexpected rules/exceptions to learn further hidden behind a compile step. Because of the rules, it's harder to onboard and riddled with complexity. To top it off, being XML-like it's hard to read and write. I miss the days when the docs had a toggle to show it as simple, trinary functions. If JavaScript had better function application syntax (like spaces), it'd be easier to reason about and read/write.
Which rules/exceptions are there that are an inherent part of JSX (and not React)?

The only ones I can think of are className instead of class (unfortunately a reserved word in JS), and the addition of convenient event handler attributes (like onClick), which aren’t real attributes in HTML (where handlers are attached to elements manually via JS). Other than that, it’s just like HTML, no?

(Now that I think about it, I’m not even sure that those are parts of JSX and not the React API)

Regarding being XML-like, it’s a matter of personal preference I suppose, but I prefer it that way since it’s basically HTML with tags that you can make yourself.

className and onClick are not part of the JSX spec though.

The biggest differences between JSX and HTML5:

1. In JSX, all elements need to be explicitly closed whereas in HTML5 elements like img and br should not be closed.

2. In JSX, attribute values are quoted strings, JS expressions in curly braces, or nested JSX expressions. In HTML5, you can leave e.g. numbers unquoted.

3. In JSX, you can use the 242 character entity references from HTML4 but not the 2231 from HTML5.

A topic not mentioned in the JSX spec is how whitespace between tags is handled, but HTML5 errs on the side of including too much whitespace in the output whereas a React app sometimes includes too little.

What we so though is there exists obvious differences. This means you need to understand HTML but also intimately understand JSX and how it differs. It does not match expectations, and looking like HTML doesn't make it more approachable. The original function syntax (more often I seen referenced as hyperscript now) was a simple DSL of functions that took 3 arguments: string name of the element, object of attributes, array of children (technically varg with keys needed for arrays). These functions are understandable by anyone with a cursory understanding of JavaScript.
Don't forget about htmlFor. And to to camelCase your attributes. And style attributes need a double curly brace (never mind the obtuse error message if you only put one!). Fix all those <br> elements, they're no longer acceptable. width=100, nope. What's that funny looking <></> for? Good luck Googling it. WTF did they put {foo && bar} everywhere?

Everyone likes to complain about the DSL that Vue or Angular use, but by the time you learn all the exceptions and oddities of JSX you could have easily learned how to use Vue's templating system.

And the fact that it's common for someone to have no idea whether a feature is part of the JSX syntax, or the framework they're using, or the HTML spec itself is problematic. It's very clear where the v- directives come from.

{foo && bar} is just JavaScript.
Yes, but it's not pragmatic or intuitive to use the && operator as a stand in for an inline if statement in non-JSX-land. Doing this is something of an ugly anti-pattern, `let foo = bar > 12 && "there are dozens of us!"`. The fact that it works as an inline if for JSX is almost an accident that has now been abused into convention.
Just because it's an abused accident doesn't mean it's not just JavaScript. There's nothing JSX-specific about it.
`className` bit is React specific. Preact, Solid JS and others allow you to use `class` (and sometimes both) no issue. Some just opted to follow React's lead there
AlLpine.js is a great jQuery replacement.

I'm using Alpine.js in a Django project and it does what it says on the tin. It blends well with the MVT style of Django along with HTMX and makes the client side interactions really easy. This is now my favorite JS framework for doing light client side JS magic.

I agree with your point. Django + HTMX + AlpineJS makes the web application development completes.
If you add in Tailwind you get the PHAT stack (python htmx alpine tailwind)
(comment deleted)
what's wrong with jQuery?
Nothing, if it works for you great! I’ve found Alpine code to be more declarative and easier to reason about. Also, jQuery often requires you to write more code to do the exact same thing in Alpine. One thing jQuery does better is AJAX, Alpine doesn’t have builtin AJAX tools. I’ve made a plug-in to bridge that gap though: https://imacrayon.github.io/alpine-ajax/
We use alpine as well, very simple to add in for some simple reactive uis. Flask+Alpine seems to work well for us.
Oh, I remember it now - this is the free framework with paid components [0]. Thanks, but no thanks!

[0]: https://alpinejs.dev/components

What's so bad about charging for a service or for tools? Just because some of the MegaCorps offer Javascript frameworks + tools for free, why shouldn't a small competitor be charging a bit of money for work that is built on top of the free framework to keep it financially sustainable?

It's an optional purchase for people who might want to rather save time, e.g. when you're a small dev team trying to build something, you need to calculate the opportunity costs.

Furthermore, sometimes I will even refuse to use a service if they don't charge money. The interests of a service will often be aligned to those who give the money. So if the money is not coming from me, the supposed customer, it has to come from someone else.

What is wrong with that?
Indeed, i dont get the "i want to make money by using software by peple who are not allowed to make money"
Nothing is stopping you from building those components yourself. Or, you can pay the author who’s already done the work for you.

I think it’s a great way to monetise an open source project.

Why are some dev so cheap? Everywhere else you want great tools, you are willing to pay the price. Especially if they help you earn something in return.

That's a strange mindset *pondering*

You can definitely build these components yourself.

If you are a developer or a company using open source buying components and even training courses is like printing money.

It's an investment to save time and level up your skills and put out better software in less time with more polish.

Have you checked out TailwindUI. It literally replaced having a designer at our startup. Amazing value.

If you're not paying for tools you're leaving money on the table.

Plus supporting open source means the maintainer can make improvements that wouldn't be possible otherwise.

Support, Learn, Save Time, Profit!

but, there are many paid component libraries out there, for various different frameworks, right? other than this being first-party, what’s the difference?
Creator of Alpine here! Those components are the reason I can work on open source full-time. If I didn't charge for anything, I wouldn't be able to pour as much effort into these tools.
thanks for your great work on alpinejs, i use alpinejs with django on all most of my works. eagerly waiting for headless-ui for alpine to be realesed.
Hi Caleb. Great work. Please continue keeping it simple and stable. I love that about alpine
I really enjoy Alpine.js and am happily financially supporting the components. Also enjoying the development of the component explanations.
Keep up the good work, all the developers I know who are clear thinking know that open source engineers need to make a living too. Thanks for your work.
I'm glad alternatives like Alpine exist for small sites that don't need many additional behaviours. But having used Alpine for a medium-sized art gallery website last year, I can't really recommend it for anything larger than a very simple site. The fact that all your code is scattered as strings everywhere without error checking or types makes it really hard to debug and work with long-term.

For lightweight front-end tooling, nothing has unseated the ease of Preact for me.

Basically the problem with every framework that think its fine to sprinkle in strings as code in html.
And for Alpine it's sort of fine. People have taken Alpine a lot further than the original intent, which is to add sprinkles of JS to what is otherwise a server rendered page.

For anything even slightly more complicated we have things like Mithril or Preact, and yeah they avoid this sort of thing for a reason.

I’m glad when tools like Alpine remain in their niche. Too many of them grow with their userbase, adding every requested feature, until they become as unwieldy as the framework they originally tried replacing. If you outgrow Alpine, migrate to another framework instead.
Then why not go with nextjs outright so you can apply the exact amount of interactivity for every little detail on your website without changing your entire setup halfway through.
Next.js is a fantastic solution if you're building a SPA.

Imagine I'm a very early stage startup so I start out with a simple app built on Laravel. All my engineers are relatively non-senior PHP folks, not great at JavaScript. So it's rendered server-side in PHP - easier to achieve enough performance, security, maintainability by leveraging the framework. Then I want to put some tiny bit of client-side interactivity. Going full SPA with Next.js would involve a lot of extra cost and complexity. jQuery and Alpine fit well into that niche, and Alpine particularly helps with reacting to state in a way that jQuery is hard.

At this point one of the main features I look for in a JS framework is whether its author values type checking like I do or not.
I don’t know much about your project but these tools are really meant to be used in conjunction with “html over the wire” frameworks. IE, your JS has zero business or app logic and is just taking care of small UI concerns like transitions and showing modals. They scale just fine in these situations.
exactly this, and honestly, I feel like we need to get back to this model as an industry.

There are times when full-blown SPA is superior, but not nearly as often as people currently think. And the toolchains get vastly simpler when you're not doing SPA too.

Exactly. I used alpine in combination with django for a project and it quickly became a nightmare to maintain when alpine started to take care of app logic / SPA-type reactivity.

Alpine is just not designed with that sort of application in mind, nor should it be.

I don't really understand why people want so bad to mix in code into HTML.

The whole fight since 2000 was to avoid doing that through minimalistic templating and naming elements semantically so you can attach the logic from outside.

That approach (i.e. the jquery style of attach logic to the DOM) just doesn't scale when you're writing a single page app where _everything_ needs to have JS logic attached to it. It turns into a complete mess of imperative UI twiddling and it's extremely easy to forget to update some little element in response to a change.

The bigger question IMHO is if you actually need a SPA. If you don't then yeah the old jquery style (now alpine.js or similar frameworks are spiritual successors) is perfectly fine.

Scaling comes from splitting your app into components and correctly mamaging staye not from the way you attach things to your view layer.

jQuery didn't scale because there was no recommend way to split it into components and managing state.

Those day Backbone.js was amazing innovation.

If jQuery came into existance today when we know what we know about components and their role in building large applications it would be perfectly suitable for many applications.

I think this is losing some to text and experience with what was available at that time.

Attaching to the don wasn’t mandatory and was completely manageable.

If anything building a web app has become much heavier and longer to develop than it ever has.

I agree with this, we managed to sometimes create SPAs faster even though we had to duplicate template/initial page logic on the server side for each page in case of direct link/page refresh. Nowadays sometimes figuring out which prop you misused from a 3rd party component based on a 100 lines TS error takes more time than the actual coding.
I've been using AlpineJS on various projects for about one year. The creator (Caleb) is actually a Laravel developer and maintains the Livewire meta framework.

I find the sweet spot for utility frameworks like AlpineJS is when used in conjunction with server-side components [1]. For example, when designing server-side Blade components, the more you can keep within the component itself (e.g. html, styles, interactivity), the easier it is to reason about and maintain the component going forward. If your x-data function becomes unwieldy, consider moving the code to a separate Javascript function that returns an object and calling that function from x-data.

Ultimately, using tools like Alpine or Tailwind is a tradeoff. My apps tends to be relatively small and only managed by myself or a small team. If you're building large, front-end heavy apps; React, Vue, Svelte, etc. are definitely a better fit.

[1] Laravel Blade Components: https://laravel.com/docs/9.x/blade#components)

The use with Livewire is part of what makes it such an awesome tool to pair with Elixir LiveView. I mainly just need enough js to do client-side things (like closing/opening menus) and it's perfect for that.
Livewire itself is worthy of attention.
And Elixir Phoenix LiveView for that matter
AlpineJS is actually going to be bundled by with Livewire 3, when released.
+1 for Preact. And its overall bundle size is smaller. I'd also recommend Svelte as well.

38.2kB Minified, 13.5kB Minified + Gzipped, https://bundlephobia.com/package/alpinejs@3.10.5

10.4kB Minified, 4kB Minified + Gzipped, https://bundlephobia.com/package/preact@10.11.3

It’s going to sound like a trope, but having discovered Svelte yesterday, I don’t understand how I ever could see React as "fine" anymore.

I’m just waiting for the other shoe to drop. It can’t just be that simple, can it? There has to be a catch.

Out of curiosity, and I'm asking this as a curious React dev, what made you change your mind about it?
So far, everything I’ve had to type in it was code specific to what I was doing. And that feels nice.

The extra boilerplate that doesn’t bring any value to me, as a dev, when needing to update values at runtime. I find two-way binding to just be simpler.

Same thing for the components and their props.

But I also get why some wouldn’t appreciate having things getting "automagically" done for them.

I had the same feeling with Vue2-3 a while ago, I'd say Svelte is relatively similar in feelgood as both eliminate a lot of annoyances to create "leaner" components compared to React.
Funnily enough, I've avoided react/angular/vue as much as possible specifically because I've _always_ felt it was fundamentally the wrong approach. When I first discovered svelte my reaction was "thank god someone else sees it too".

Over the years I've moved further and further from the web as a result of that belief. I still do web work when needed and as a result I'm familiar with vue and angular but I actively try to avoid knowing any more about them than I absolutely need to for accomplishing the goal.

Coming from iOS, with their Massive ViewControllers, and the occasional (usually half-baked) MVVM, it didn’t seem that bad at first.

On the contrary; components! Finally reusable pieces of UI! Try doing that when everyone on a team is hell-bent on their One Storyboard to Rule Them Al. Even if you did, @IBDesignable (used to preview components in Storyboards) would just crash anyway.

Instantaneous reloading! Even when it takes a bit of time, it takes less than 3 minutes. Pretty much instantaneous when coming from Xcode.

So, yes, React too was a pleasant surprise at first. The kind you get when you take of shoes that are just a tad too small.

The lack of libraries to work at a higher level, with more powerful UI components.

At the moment it's really just Material. (And that looks a bit messy on the inside)

We need a chakra or radix or?

I've been using daisyui + svelte and I'm pretty happy with it so far. It may not be as rich as some of the react UI libraries but the basics are all there.

https://daisyui.com/

That looks promising, and not stuck to a single tech (svelte, react).

So it's a tailwind plugin that uses apply to create new css classes for components.

Yeah the framework independence is one thing that drew me to it.
You couldn't pay me to write in another HTML template language like in Svelte or Vue.
Over Preact? I'm a little confused by your comment.
Not sure what part is confusing, Svelte and Vue have their own template languages inside HTML, I don't want to write another `v-for` or a `#if :else` instead of JS/TS.
Jsx is just js with a thin layer of sugar.
I have not tried it yet but I think https://unpoly.com/ is also a nice addition. I am thinking about trying it out in a project that I have in mind.
I want to try building something with either and see if it works for me. But last time I couldn't decide between it and alpine and ended up using neither :/
This was a concern for me but when the Remote Ruby devs had the AlpineJS guy on last year, he mentioned that you can pull them apart into data components, which provides a separation that I found quite tidy. Did you check this out and find it unsatisfactory?

https://alpinejs.dev/globals/alpine-data

I did! I actually forgot about that feature when making the parent comment. It was a useful addition to a degree.

I used it for more complicated components like a mobile nav with animations, and for some re-usable pieces like a subscribe form. The downside with Alpine.data is that it splits the HTML from the JS, so developing and refactoring was a bit of a pain, and caused errors because of old variables I accidentally left in the HTML (whereas Preact/TSX would give me an in-editor error).

It also didn't really mitigate the need to wire up all the pieces your data component exposes into an HTML correctly. Though, this was working inside a simple PHP-based templating engine — maybe one that supports better snippets with parameters would make that part of the experience better.

I wanted to use something light so I tried Preact without build tools. It was awful, nothing worked (like router and store), so I switched to Vue.js - where everything just worked out of the box. Not sure if I was just unlucky in my selection of js files, or what, but I can't recommend Preact from this experience.
>> The fact that all your code is scattered as strings everywhere without error checking or types makes it really hard to debug and work with long-term.

I'm afraid this doesn't match my experience.

All your code can be in a single file (or as many as you want) with window.app = function(){return{show:false}}

This feels like a less mature version of riot.js.
For someone with no JS experience who wants to learn, is this framework a good place to start?

(I don't mean learning JS/TS syntax, more the general paradigm for user-facing code which does something meaningful besides printing "hello world")

I would say you better start with using JS to manually manipulate the DOM, then start with a framework later.
I agree that you should start with vanilla JS, but Alpine is a good follow up because it just adds conventions around what you'd be doing in vanilla JS anyway.
Every framework will teach you a different way of looking at things… can’t go wrong picking one and going really deep, then exploring some others. I wouldn’t recommend one specifically, but definitely start with one and stick with it for a bit
> but definitely start with one and stick with it for a bit

Devs are paid quite a bit of money to play russian roulette with their tool choices.

Frameworks are an abstraction and not really key to understanding anything. And devs need to understand, at least conceptually what the framework is doing (or attempting to do) without too much magical BS. Ideally that starts with working with the dom and seeing first-hand the pains and joys of adding and removing elements, functions, sync and async behaviours, data handling, objects etc.

Then only will frameworks click and make sense, and so choose the right tool for the right job.

I think there is definitely value in both approaches and depending on your preference one may be more fun than the other. My point is not to get caught up in the framework of the day.
> devs need to understand, at least conceptually what the framework is doing (or attempting to do) without too much magical BS

This strongly aligns with how I like to learn, and is one of the reasons (besides lack of need) why I haven't touched JS thus far; everything seems to focus on the revolving door of frameworks, but it isn't clear as an outsider if any of them are "purer" than the others. The reason for asking about this one in particular is that at a glance, it appears minimal and clean - but I suppose that doesn't necessarily correspond to it being an idiomatic example of simple JS done well.

It's a wrong direction to start with: better learn separated behaviors (js vs css vs html) instead of mixing them together in a single "code".

You'll also have better tooling to help you.

No, not at all. Learn vanilla JS and manipulate the DOM directly. This allows you to understand most other frameworks later on.
Check out Joystick [1]. It's designed to be a logical next step from learning the fundamentals of HTML, CSS, and JavaScript. No surprises in terms of syntax or tooling (if it's in the specs/docs for those languages, it will work in Joystick). It's also full-stack, meaning you can start out building simple web pages with components and upgrade to a full-blown app as you learn more.

If you have any questions, feel free to get in touch: ryan.glover@cheatcode.co.

[1] https://github.com/cheatcode/joystick#writing-a-component

Yes definitely. It helps you mutate the dom easily and gives you reactivity.

I’ve used it fo years. It never breaks and I don’t need to recompile never

I"m not a programmer so I was learning js from basically nothing. As others have said, I have found it best to avoid frameworks if possible. One of the biggest reasons for me is a lot of the examples and things on places like stackoverflow is out of date so I would find myself learning a framework to do one little thing and then a few days later find out there was a new pure js way to do thing or that the way I figured it out was depreciated or something. SO try to stay pure at the start.
For lightweight JS interaction, I prefer the Stimulus controller approach that doesn't mess too much with your HTML, and doesn't try to sell you "components"...

https://stimulus.hotwired.dev/

The real power of Alpine.js is part of the TALL stack. Tailwind, Alpine, Laravel + Livewire.
Am I the only one who doesn't add random attributes to the existing HTML elements? I use the dataset `data-` attributes for that. You can go nuts with custom elements though.
What practical difference does it make?
Maintainability and browser compatibility (less of an issue these days). If you use a non-standard attribute and hand your code off to someone else, they likely won't catch it and can introduce bugs.
Regarding the bugs, what makes it more of a problem in HTML attributes than with any other code?
Nothing makes it more of a problem. Same as any other code. Just the idea of introducing non-standard things (especially if used inconsistently) increases the likelihood that things will break and be harder to fix.

For example, if someone binds an event listener to an element in two different places with something like clicker="button" in one place and then uses data-clickable="true" in another place, it can introduce confusion. Not only does the original developer have to remember all of their custom attributes but so does anybody else who comes on to the project.

Yet another JS framework. How fast is it really? The learning curve may not be worth it if it's slower than https://www.solidjs.com/ and according to https://krausest.github.io/js-framework-benchmark/current.ht... few things are faster than a very little-known framework called Mikado (https://github.com/nextapps-de/mikado). That being said, I would never sacrifice performance of my software for how trendy or popular something is, e.g. React is #1 in popularity yet it's overcomplicated, massive, slow as hell.
Looks interesting, I might take a deeper look into using this.

One thing to note, on my mobile browser (Firefox Nightly) the site is a bit broken. The page has the wrong width so periods etc are off screen and for the code example blocks I can't scroll them to see the whole line.

If you know (and like) Vue, look at petite-vue as an alternative.

https://github.com/vuejs/petite-vue

Petite Vue appears to be dead. ISTM that Evan You saw Alpine, made a quick proof of concept version using Vue, then handed the project off, and it died. Nothing wrong with that! But I don't think it makes sense to use it over Alpine for anything serious.
Sadly. It would have been perfect for me, I wrote an SPA and some smaller widgets with Vue, would have loved to use petite Vue elsewhere.
“petite-vue is indeed intended to fill the gap for progressive enhancement cases where Vue 3 would be too heavy-handed.

It is not abandoned, but rather it is considered "done" because the scope is well defined. I don't think it needs more features (as that would defeat the purpose of being lean and minimal). If you find yourself needing more than what petite-vue provides, you can either go up to Vue proper, or try https://alpinejs.dev/.

That said, I should update the README to indicate this more clearly.”

Github discussion: https://github.com/vuejs/petite-vue/discussions/53

Alpine is great. I've been using it in production since 2020, and I've never had any complaints. I like that it embraces JS instead of pretending that JS doesn't exist, like other microframeworks do. (I'm thinking of Stimulus and HTMX specifically.) Alpine's job is simple: it adds encapsulation and reactivity around JS. Other than that, it's more or less vanilla JS, and you can use it the same way you'd do things if you were doing document.querySelector yourself.
Horizontal scroll doesn’t work for code blocks in iOS Safari.