Moving from Svelte to HTMX

Published: 2022-06-21 9:00 AM |

Category: Code | Tags: code, htmx, programming, svelte


Last year, I built an event registration tool for our district, mainly to keep track of what professional development we were doing and try to get paper out of the workflow. I chose to use Flask and Svelte for this project and this year, I decided to move away from Svelte and rebuild the application using HTMX. In this post, I'll explain why I decided to make the change and highlight some situations where HTMX just makes more sense for a large app managed by a single person.

Making a Switch

I'm self taught. I started playing with Internety things in the late 00's, starting with WordPress and straight HTML/CSS. I added Javascript slowly and since then, have managed to cobble together some kind of useful tools. Mostly for myself, but some to benefit others.

I had tried taking a dive into React, Meteor, and Vue, all with little or no success. The complexity of the frameworks and the abstraction needed to get stuff to show up on the page went way over my head, especially as a hobbyist. Adding complexity was the requirement to use build systems (I know Vue can be added directly with script tags, but that's not where I was introduced to it) and those felt untouchable.

Over the 2019-2020 school year, I got what I'll call a "working prototype" of an events registration system published using Firebase, some HTML, and a lot of vanilla Javascript. That pushed me closer to understanding build systems and when Svelte came along, its syntax finally felt familiar - just some template tags with scoped Javascript and CSS. Not too hard to handle.

I had a published version of the registration site by fall 2021 and it worked well for a first "real" project. Python did the heavy lifting in the background and I was able to have a nice interaction on the front with Svelte. So, why the move?

There are two main reasons:

  1. It's essentially an application to create and maintain records. I don't need elements to be running continuously (ie, a video player) while the user does things. Having a Javascript-built application was overkill for the purpose of the site. Rich Harris (creator of Svelte) elaborates on this in a podcast on when to use single-page applications over multiple-page structures.
  2. Maintainability of large Javascript-based systems is very difficult. Granted, I'm an amateur and this was my first project, so there are things I can certainly do better to take advantage of the systems, but I found myself reluctant to touch the app for updates because it would take me so long to untangle how everything worked together.

With those issues in mind, that's why I decided to move to HTMX.

How is HTMX Different?

I started following Carson Gross, the author of HTMX (formerly IntercoolerJS) and reading some of his essays, arguing for a return to hypermedia as the main driver of the web rather than Javascript. For my background, this made a lot of sense. Servers exist to serve content. The modern Javascript frameworks were created to allow for non-full page refreshes of content. HTMX blends those two goals, allowing the server to send content to the client and allowing for dynamic and strategic (even surgical) updates to the page the user is on.

This provides instant benefit in several ways:

  • The client no longer has to manage state. The server already knows the application state, so why not just send content that is stateful based on the user session (ie, logged in vs not logged in)? Using Flask sessions makes this very simple.
  • Templating engines can still be used for dynamic content creation. Each template contains the content it needs and doesn't have to re-wire itself with the other items on the page once it loads.
  • Specific elements can be updated as a result of a user action. The user interaction is clean and does not require any full-page refreshes, but without any of the messy Javascript workarounds to make that kind of interaction possible (looking at you, shadow DOM [whatever that means]).
  • Each request returns everything the user needs. You're not required to make more network calls to get the data necessary for the view or template (I think that's what "hydration" is).

With any Create/Read/Update/Delete (CRUD) tool, form rendering is a common task. I want to dive into the difference between doing this in Svelte and HTMX as an example of why I decided to make the move.

Form Rendering

In Svelte, I created a FormWrapper component which would dynamically handle input element rendering and form submission. This pattern was extremely helpful and I actually took some of the principles I learned and applied them to HTMX. The snarls came in determining what actually needed to be rendered.

A simple example is this view: when the user clicks on one of the action buttons, a form is rendered. Depending on the action, the form is different. In Svelte, you need to first render the form and then fetch the fields - two network calls to render. It works this way because Flask is serving JSON - agnostic structured data rather than data which carries all the information it needs in order to render.

Svelte form wrapper

So, a couple hundred lines of code to render a form. Reusability is good, but when it came to editing a form, it got gnarly really quickly. The main drawback was that for the form to even render, it required several more requests to the backend to get the fields necessary. Because the backend was just a JSON cannon, even the data it returned needed to be mapped and filtered into a usable state.

HTMX form rendering

With HTMX, that form is pre-templated and then sent from the server. Instead of a single endpoint to return all the form data, individual endpoints can be used to send back whatever form is necessary in HTML. There is no needed to request more information or process the data in the client to make it usable.

Because of Flask's templating engine and thanks to the extremely helpful Jinja partials extension from Michael Kennedy, I was able to mimic the dynamic action where a temporary sidebar is used to load and display the form.

The obvious tradeoff is that there are more files to maintain. But because each file is single-purpose, they're smaller and more focused, which means maintaining is much easier. It's also much more clear what is being returned by each operation rather than firing the JSON cannon and then untangling everything on the client.

The Takeaway

I'm very happy with the decision to make a switch. In the cutover, I've made some incremental improvements that were on the list of "someday" changes, but had felt overwhelming to try and attempt because of all the side effect potential. I'm also not saying that Javascript frameworks like Svelte are a terrible idea - writing this app in Svelte to start helped me learn how to build resilient and flexible backends.

For me, the value in HTMX comes back to maintainability and developer experience. The language of the web is HTML. Svelte was a good entry point for the initial build because its syntax was very close to plain HTML. But in the end, it still relied on Javascript to work and instead of feeling flexible, it felt brittle.

HTMX's approach to adding functionality via HTML attributes is much closer to the surface of normal web structure and gives just as much flexibility for 99% of what I need to do at a much lower complexity. I just enjoy working with HTMX because I can spend less time trying to figure out where an emitted event goes to make an update and more time making the tool more useful for my colleagues. That's a win every time.

Comments

Alan Levine

Thanks for blogging this Brian although my understanding level is hovering at 16% 😉 But something I did pick up on is what I want to be implementing more on some work projects, being able to create filterable tables of data, where you can provide a place to dynamically pare down tables of stuff to ones of interest.

I like AwesomeTables but you have to pay per app. And I tried the Google Dynamic Tables thing but it looked like it was built for something else- I get a sense HTMX might be a way. And like you, I prefer this HTML oriented approach.

Cheers!

Brian Bennett

Oh boy, you’re in for a treat. HTMX has a partner tool called hyperscript which allows for some lite client scripting. It’s made by the same author and it’s pretty much plug and play with HTMX. I’ve got it filtering tables (alphabetical clicking on table headers) as well as an active search on rows in large tables, all right there in the HTML. I’d be happy to send a demo if you think it’d be helpful.

Previous: Sort a Google Sheet with Vertically Merged Ranges Next: Adventures in Building an Interactive Apps Script Sidebar

Comments

Comments are always open. You can get in touch by sending me an email at brian@ohheybrian.com