Why I Switched From Svelte 5 to Htmx and Django
svelte
is the most popular framework ( or in 2021 that was the case ). There’s no debate over the fact that svelte
does some things right.
Pros of svelte
:
- No virtual DOM
- Less boilerplate
- Truly reactive ( or it was before
svelte
5 )
So if svelte
is a bag of goodies, why move away from it?
Well I am glad you asked.
svelte
5 is a mess
svelte
is not all sunshine and rainbows.
svelte
3-4 had the nicest API possible.
Take for example:
<script lang='ts'>"use strict";
let count = writable(0);
</script>
{$count}
<button on:click={
()=>$count++
}>click</button>
This became something like in svelte
5:
<script lang='ts'>"use strict";
let countRune = $state(0);
const count = {
get value() {
return countRune;
},
set value(v) {
countRune = v;
}
};
</script>
{count.value}
<button on:click={
()=>{
count.value++
}
}>Click</button>
See the problem? This is the route react
took with their context api
This tweet from fireship sums it all up
Coming from react
land, this gives me PTSD.
Some people might say, “But it’s opt out, if you dont like it you dont have to use it”.
To which I reply, ”Rich hinted that runes will be the default way moving forward”
svelte
lost its original vision, instead they are going for a different direction ( to which not sure i agree with )
Jamstack gets expensive
The data transfer between backend and frontend gets expensive relatively quickly.
We were using REST api to move data from backend to frontend. There’s a lot of redundant payload that moves from backend to frontend.
Take for example we send this data from one of our endpoints :
{
"name":"Joe Smith",
"first_name":"Joe",
"middle_name":"",
"last_name":"Smith"
}
But let’s say we use only Joe
from the above example. We still need to send everything from backend.
When the payload gets large ( about 129kb ) from our backend on each request, it gets expensive.
svelte
community is confused and possible diverted
Oh boy, where do we start.
For starters, projects like pelte
popped up right after rich announced svelte
5.
Posts like these popped started appearing on reddit:
- How does Svelte 5 w/ Runes differentiate itself from Vue (i.e. why use Svelte vs Vue going forward)
- [Meta] Svelte vs X
These indicate that a portion ( may be small ) shifted away from svelte
after the announcement.
Authentication between SPA
and decoupled backend is hard
For starters, if you have a django
backend, you dont have a straightforward way to do authentication from backend and frontend.
You can do something like token authentication, but the problem rises with storing the token securely, then validating the token, …
The token can be stored securely ( specially if you use something like sveltekit
) but the process is cumbersome ( server side route, setting https only cookie from server ) and it takes time to set everything up. Minus point is you lose client side routing if you go with this route.
The ecosystem is brittle
The entire svelte
ecosystem didn’t get that much mature even after 2-3 years. For example there’s nothing like mantine
for svelte
. Well skeleton
exists but it’s a relatively young project with countless bugs.
There’s no good text editor ( that’s native ) for svelte
. Posts like this echo this problem.
The move
So, why did I move to django
?
For starters django
does a whole lot of things right ( that’s a post for another day ).
Some benefits:
- With the help of
django-components
we can even recreate the components fromsvelte
- With the help of
django-tailwind
we can usetailwind
in ourdjango
app
Our new stack:
htmx
django
tailwindcss
hyperscript
Authentication
For django
we can do something like:
{% if request.user.is_authenticated %}
<!--Do something-->
{% endif %}
To do this in svelte
I probably would have to show either a skeleton
or a loading spinner
No node.js
server in production
Doing everything in django
means I don’t have to deal with node.js
docker container, saving resources and improving efficiency
No fetching data from backend
We can return the html rendered by django
, no need to fetch data back and forth.
welcome back {{ request.user }}
With hyperscript we can add event driven interactions
Take for example :
on hyperscript:change(url)
if url !== '{{icon.href}}'
put 'btn btn-icon relative w-[4vw] h-[4vw] border-none rounded-[0.75vw] p-0 !bg-transparent' into my.classList
remove .hidden from <span/> in me
else
put 'btn btn-icon relative w-[4vw] h-[4vw] border-none rounded-[0.75vw] p-0 relative !bg-accent before:absolute before:-left-[0.15vw] before:z-10 before:h-[1.25vw] before:w-[0.25vw] before:rounded-full before:bg-primary-500' into my.classList
end
on htmx:afterRequest
add .blur-sm
then wait 100ms
send hyperscript:change(url:event.detail.pathInfo.responsePath) to <icon/> in <glider-container/>
send hyperscript:change(url:event.detail.pathInfo.responsePath) to <button/> in <glider-container/>
This doesn’t look that great compared to svelte
but, we can achieve the same functionality provided by svelte
.
Conclusion
I had really hoped that svelte
would be my last framework. But the way things are moving forward, I am currently unsure if this would be the case.
Having many ways to do the same thing is why perl
died and react
became a mess.
svelte
should get their direction right ( they originally had the motto “Reactivity by Default” ), should that happen i will return to svelte
.
Don’t get me wrong, I still do absolutely love the innovations brought by svelte
( that’s why my blog uses svelte
), it’s just that I am not gonna rely on svelte
for my main project moving forward.