119 comments

[ 3.6 ms ] story [ 187 ms ] thread
(comment deleted)
> Say no to the heavy frontend solutions such as React, Vue, Svelte, Angular

I get the author is looking for some integration with Django and server-rendered HTML but Svelte is definitely not heavy and v5 is going to produce even less JS code.

Svelte had it's own language and compiler.
It has a compiler, yes, but if you know HTML and JS you already know like 99% of the language.
I wanna know more about what's "heavy" and what's not, and why choose lighter solutions over heavier.

Are we talking purely bytes? Popularity? Typical codebase size? Browser performance?

And whichever it is, why are we prioritising it?

Heavy as in "conceptually heavy" -- complex, steep learning curve, extra build steps, bringing in non-Django paradigms.

I.e. looking for solutions that "render HTML in Django, and use Javascript to enhance the server-rendred [sic] HTML."

HTMX is the most popular solution.

"conceptually heavy" -- complex, steep learning curve, extra build steps, bringing in non-Django paradigms

which i think is, for the most part an exaggeration.

if someone feels that learning a new framework is heavy and has a steep learning curve, then either they are juniors that need more practice and experience, or they have never tried learning a second framework, or they have become lazy. (but here i'd also like to blame employers that don't give their developers time to learn new stuff)

(comment deleted)
I imagine it's not so much about learning curve, but about the number of concepts to keep in mind while working on your code.

If an application has lots of client-side state (and the framework to support that), for example, that means you have a whole additional lifecycle of your code to reason about. Whereas if it at most sets a disabled attribute on a button, that's conceptually a whole lot lighter.

If an application has lots of client-side state, for example, that means you have a whole additional lifecycle of your code to reason about.

not really, because you no longer need to track that state in the backend. the backend can be reduced to data storage and business logic calculations. the cases where you need track some state in both frontend and backend should be rare. from my experience all the UI code is moved from the backend to the frontend. it's not being duplicated.

duplication of code can happen during a transition, but it should be temporary

It's not so much that a single case affects state in both the frontend and the backend; it's that in some cases, you're going to have to reason about the lifecycle of your backend, whereas in others, it's the frontend lifecycle that's relevant. Both come with their own set of concerns, and it's more context switching and lifecycles to keep in mind.
well, yes, sure, but that's not much different than any two projects. sure, if all your projects are using the same framework then maybe that's easier, but if you are working on multiple projects, chances are you also work with multiple frameworks. at least i do.

and if i specialize, i'd do it with one frontend framework and one backend framework. ok, so that's two instead of one. anyone beyond a junior developer should have no problem with this.

Exactly - "heavy" frontend frameworks are like adding another project. It's not that there aren't plenty of situations where that is perfectly fine, but if all you need to do is adding a few client-side effects, I'd suggest using something more light-weight.
that's part of what i am disputing. the frontend logic is moved to the frontend framework, and the backend is dramatically simplified. the overall complexity is not much greater than having everything in the backend framework. so i am only adding another project in terms of dealing with two frameworks instead of one, but at least on the backend i am only using 50% of that framework now.

what's more, this simplifies the backend so much that in most cases it is reduced to CRUD in such a way that i can reuse it more easily. since using frontend frameworks i haven't in face needed to do any backend coding anymore because i could just reuse the backend i already had unchanged. so in my case, i only ever had to deal with one project, except for the first time where i wrote the REST API into the backend. every other website after that was a frontend project only.

for dozens of projects i can now maintain a single backend implementation (with multiple instances as needed, that all share 100% of the code). that alone makes using a frontend framework worth it even just for a few simple client-side effects.

I think this is just a case of you arguing from a different set of assumptions. The thread starter started out with a Django app and wanted to distinguish between frontend libraries' conceptual "heaviness" for adding bits of interactivity to their website. Obviously in that case (i.e. being comfortable in Django and wanting to keep that) a framework that assumes that you'll move all logic into it is then conceptually pretty heavy, given that they're not going to do that.

If you are, then sure, those frameworks are conceptually lighter.

you are right. i am arguing based on the assumption that this:

being comfortable in Django and wanting to keep that

is a bad idea. because whoever is doing that is missing out on a lot of potential.

sure, there are many cases where sticking with django for everything is the right choice, but that's not always true, and i am trying to argue that there is a benefit to exploring the alternative.

i was a backend developer too, django, laravel, others,, and i shunned javascript as much as i could, but when i discovered angularjs (the first version, before it was popular) it just won me over as the better way to build frontends.

in particular, not having to track state in the server, i feel, makes the whole development process so much easier.

i could summarize it thusly: i would use a lightweight option only if the site is mostly stateless (which many content sites tend to be) but as soon as it is necessary to track state, i find a frontend framework talking to an API is the better choice, because tracking state in the browser is so much easier.

Heh I mean, I'm a frontend engineer too and agree with you that there's so much to be had in the frontend :) But I also understand that people have preferences and habits, and that there's a cost to investigating potential other paths one could take without knowing in advance whether they're right for them.
well, you never know in advance, and while i don't fault people for feeling overwhelmed by the many ever changing frontend frameworks, everyone should at least build one true SPA with any frontend framework to learn what the fuss is all about. because you can't make an informed choice about the suitability of building an SPA if you are not familiar with the choices. there is also the aspect of using frontend frameworks for mobile development, where an SPA is more likely to be suitable to enable disconnected operation.
> the number of concepts to keep in mind while working on your code.

And most importantly, the amount of fragile ad-hoc, potentially abandonned "concepts". I have a very different feeling when I grind hard to learn about physics or maths compared to IT solutions. The latter almost always feel empty and very temporary, which causes fatigue to rise way faster.

Or simply what integrates well with an existing framework. The "lightweight" examples given allow for non-JS templating on the backend (in this case Python, but the article looks at other non-JS languages), whereas other frameworks require build steps/"SSR" and effectively require a REST or other API framework.
see my comment here for a response: https://news.ycombinator.com/item?id=39157910

btw, i use frontend frameworks without bundlers/build steps, but load then statically straight into the browser. that may seem a bit wasteful, but it dramatically simplifies the maintenance needs for a site, guaranteeing that the site will keep running and be maintainable for the forseeable future.

I assumed size which is probably what most people would associate with "heavy".
> I wanna know more

I want to know more.

Let's try to maintain a high level of writing and communication here.

> Let's

Let us.

Contractions are proper English. Your "correction" is not one. Nice try though.
I thought Vue was in that lighter space where you can easily add it to a server side app too. Last I hacked on Livebook they were using it for the more complex front end widgets for example, and that’s primarily a Phoenix Liveview app.
Yeah, Vue is my go-to lightweight option and while using Vue with pre-build steps adds a bit of complexity you can also use Vue without any build steps(95% of my Vue usage). And then putting something like Phoenix liveview,etc into the lightweight category, really feels like putting things in categories via rumors or smth.
For an article about "lightweight javascript", it mentions the bundle sizes of its examples exactly zero times. Probably because the livewire bundle alone is like 40kb, comparable to react+react-dom's 45kb.
A big difference though is that the Livewire lib is downloaded only once and includes Alpine for client side stuff.

With React you still need a ton of JS with components and other libs.

Vue 3 is 16kb, or 27kb if you use everything. It feels like "heavy" refers primarily to cognitive load (a legit factor, of course).
45kb (zipped!) for document.createElement() with a babel transpiler build process.
Excuse me, I forgot that react-dom also ships with an implementation of document.appendChild()
I've been using Django Unicorn and been reasonably happy with it. I have run into some bugs and weird behavior but it's extremely pleasing to build even fairly sophisticated interfaces without any JS or the need for web-sockets.
I had a nice experience at first but have moved away. Decent codebase with dozens of components, throwing it out. It's too fragile and breaks too often. Users will send screenshots of broken UIs and I feel helpless - not a good situation.
The Django community goes out of its way not to learn JavaScript.

I’ve been a Django developer since 2008; I was allergic to JavaScript (for good reasons) too. After almost five years of front-end development I can tell you that most of those reasons stopped being valid sometime between 2017 and 2020. JavaScript is a great experience now.

I didn’t do it willingly. Front-end developers are expensive and hard to size up if you don’t know what Flexbox or a Promise is.

If you’re going to be doing anything web related you might as well get comfortable with the fact that learning JavaScript, TypeScript, CSS, Sass, HTML, and something like RxJS is going to make you a better developer and your life easier.

Not just Django, the .NET and some other traditional server side communities have done their best to avoid JavaScript.

Despite the churn, there are some great core technologies for the front end. Native browser functionality is much better than it used to be.

Oh yeah, .NET [0] too. Layers upon layers of abstractions in C# just to be able to accomplish a fraction of what you could easily do in JavaScript.

[0]: I was a C# developer for five years, but, with Mono, because I wanted to make sure I wouldn’t be employable.

I don't feel that's really true.

Try using the native date control or the number control.

You also still can't easily style the select component. In React MUI, for example, they completely give up on it and use styled divs instead.

But what would I know, I'm one of those incompetent .Net developers.

but that's a browser problem, not a frontend framework issue. you'd have the same limitation without a frontend framework, wouldn't you?
> But what would I know, I'm one of those incompetent .Net developers.

C# and the .NET Framework were some of my favorite tools. I thought LINQ was neat.

> You also still can't easily style the select component.

Forgoing JavaScript and CSS for a .NET abstraction wouldn't make the situation any better. You'd just get whatever the select component's library gave you until the browsers standardize a way to do it.

Those are great examples, there's still work to be done.
It's very true for Ruby on Rails. Rails' (not so) benevolent dictator for life, DHH, has been inventing and pulling in abstractions on abstractions so that Rails Devs don't need to touch JavaScript.
The trouble is, you learn javascript and discover it’s a better back end for website building.

I say this as a python dev with experience of bottle flask falcon Django Starlette abs FastAPI.

Ehhh yes and no.

I still run into a lack of "it just works" and stays that way in JS land. It is likely I have not found the right combination of tools or the right framework but nothing has been as reliable as django and the builtin contribs (auth, admin, sessions).

What would you recommend I look at in JS land knowing I love django and dislike flask?

>> What would you recommend I look at in JS land knowing I love django and dislike flask?

I just use typescript and nodejs and the database.

No framework except the express web server.

It's incredibly raw and close to the metal, which I like.

Here's a throwaway example of register and login from ChatGPT to illustrate how easy it is. Totally unchecked but it's just to show approximately what's involved - and it's not much at all.

    import express, { Request, Response } from 'express';
    import bcrypt from 'bcrypt';
    import db from './db';
    
    const router = express.Router();
    
    router.post('/register', async (req: Request, res: Response) => {
      const { username, password } = req.body;
    
      // Hash the password
      const saltRounds = 10;
      const hashedPassword = await bcrypt.hash(password, saltRounds);
    
      // Insert user into the database
      db.run('INSERT INTO users (username, password) VALUES (?, ?)', [username, hashedPassword], (err) => {
        if (err) {
          console.error(err.message);
          return res.status(500).json({ error: 'Internal Server Error' });
        }
        return res.status(201).json({ message: 'User registered successfully' });
      });
    });
    
    router.post('/login', async (req: Request, res: Response) => {
      const { username, password } = req.body;
    
      // Check if user exists
      db.get('SELECT * FROM users WHERE username = ?', [username], async (err, row) => {
        if (err) {
          console.error(err.message);
          return res.status(500).json({ error: 'Internal Server Error' });
        }
    
        if (!row) {
          return res.status(401).json({ error: 'Invalid username or password' });
        }
    
        const isPasswordValid = await bcrypt.compare(password, row.password);
    
        if (!isPasswordValid) {
          return res.status(401).json({ error: 'Invalid username or password' });
        }
    
        return res.status(200).json({ message: 'Login successful' });
      });
    });
    
    export { router as routes };

For database I use the postgres.js library which is super nice https://github.com/porsager/postgres

examples from postgres.js front page:

    import sql from './db.js'
    
    async function getUsersOver(age) {
      const users = await sql`
        select
          name,
          age
        from users
        where age > ${ age }
      `
      // users = Result [{ name: "Walter", age: 80 }, { name: 'Murray', age: 68 }, ...]
      return users
    }
    
    
    async function insertUser({ name, age }) {
      const users = await sql`
        insert into users
          (name, age)
        values
          (${ name }, ${ age })
        returning name, age
      `
      // users = Result [{ name: "Murray", age: 68 }]
      return users
    }
Well, for me this is less way readable than python. And I know JS for a long time, yet IMHO its syntax and structure seems clunky.
Readability and unfamiliarity are two different things.
It doesn't seem that close to the metal, and not enough to justify the lack of convenience and readability.

It's like using C++ instead of C#. Still pretty removed.

Respectfully, and thank you for taking the time to reply, this is why I clarified I like Django and dislike Flask.

I'm not interested in writing all my sql for every operation. I will gladly take the overhead of an ORM for the convenience in centralizing query building, table definition, object mapping and (in the case of django) migration tooling. Knowing it's battle tested saves me from my own silly mistakes.

I do love sql alchemy so I can imagine enjoying something like Prisma but I suspect express is going to leave me wanting more.

I think my next project will use Go to force myself to avoid Django and pick up a nice perf boost with much better type safety than Python + MyPy.

I'm not sure you can call one or the other "better".

Python is more type safe due to run time type checks (less lolwut). Also, less typing. But, you also get the Django ORM which is great for productivity (good for complex but low volume apps).

JS has some great features: async/await, deconstructing objects, nice JIT, same language as in browser. However, it's also very lisp-y, which is a pro and a con :)

>> I'm not sure you can call one or the other "better".

I should have said "better for ME".

>> you also get the Django ORM

I decided the best way (for me) to write back end application is:

* typescript

* nodejs

* postgres

* plain old SQL

I realised I hate using ORMs and much prefer the raw power and directness of SQL. Postgres is an incredibly powerful database - I find it's a problem to have any sort of abstraction between me and the DB.

And honestly typescript is a real pleasure to write.

I still use Python extensively for other stuff, but for web servers, typescript/node/postgres is my preference.

I found the best way for me to write backend applications is with an ORM.

Because SQL is super slow to write.

The exception is sqlx in Rust when I want something super correct.

>> Because SQL is super slow to write.

ChatGPT writes SQL incredibly well - presumably because there is so much training material out there.

Seriously, ChatGPT is the single best reason to change your architecture away from ORM to plain SQL.

That's interesting. But no. I can write queries so fast with the Django ORM it's silly. Especially dealing when dealing with relationships...

Pycharm will auto complete like 4 levels of joins in two seconds. That's faster than you tabbing to chatGPT let alone writing the prompt.

Writing the code is only part of the equation though - especially if you are not very fluent in SQL. I imagine it gets annoying quite quickly if you need to ask ChatGPT what different fragments of SQL do 6 months after you have generated them.
Ah. So you're not writing the SQL, ChatGPT is.

Yeah, no thanks. I'll stick with Django.

Sounds like you still see ChatGPT as a bad thing in some way.

I can almost hear the subtext "AHA GOTCHA! you don't understand the code being written!"

ChatGPT is a programming assistant - it is an advantage that assists in your programming.

You still have to understand the code, and more often than not you need to debug it and refactor it to make it work or make it work nicely.

If you are not using ChatGPT as a programming assistant then you're wasting time and doing yourself a disservice.

> Sounds like you still see ChatGPT as a bad thing in some way.

Not really, it can be a useful tool, I'm not ready to just delegate all my code writing to it and no professional developer should either.

You're talking about using raw SQL because it's "closer to the metal" (it isn't really), but then really you're just using ChatGPT to write your code so in a way, you're much further removed from the metal than framework developers.

If I had to choose between an OS written in C++ by skilled humans vs an OS written in ASM (because it's 'closer to the metal') by someone who had ChatGPT write most of the code and "checked" it, I know which I'd choose.

Do you ever find yourself building utility functions etc which start looking like a lightweight ORM?
Nope.

Always raw SQL. I move the SQL statements into minimal functions that live in their own files to separate them out from the code as much as possible.

I'd be curious how your apps stand up to a WAPT.
> Python is more type safe due to run time type checks

How could Python's runtime type checks be more safe than Typescript's completive type checks? Nobody sane uses typeless Javascript for serious business logic now anyway.

FastComments main backend is around 200k lines of plain JS. I do extensively use JSDoc however.
Also, TS type checking is not at run time (with NodeJS). So some library could allow unsanitized data as a wrong type etc. at least with Python it'd fail fast.
Libraries like io-ts make it trivial to write type definitions once and use them both for both static and runtime checking.
> Libraries like

But this is already solved by so many other runtimes... Without a library..

That's why I love js ecosystem. If something is implemented in language itself, runtime or standard library, it will never meaningfully develop.
It doesn't need to be developed... An int isn't going to store a String in Java because of a bug, that doesn't require further development.
Here here. The same app built in Django was worse frontend, worse package management, and worse deployment than a Next app.
I’ve written reams of JS over the years–web frontends with a dozen frameworks, Node backends, mobile apps, you name it. It’d probably make sense for me to use it more often on the backend, but the trouble I run into when committing to it for a new project is that… I just don’t like it.

I know how to avoid all of the “wat” stuff that people typically trot out to criticize the language. I can write a quality piece of production software with it. At the end of the day, though, I still just have this feeling like I’m cooking in someone else’s odd and disorganized kitchen with not quite all of the right tools and ingredients.

I'm a JS guy but I'm not sure I would agree.

Backend frameworks in JS are not as mature as Django, Rails, or Laravel.

Or you get hung up on how bad JavaScript is compared to Python.
Is there anything like django admin?

I'm open to JS or Java tbh, but django is just so productive because of admin, forms, user management and DB migrations.

Give me those in a more performant language and I'll be interested, but I just can't find them. Add to that that django has all those under one roof so you can hire a django dev who doesn't need to spend 2 weeks learning your libraries, and I'm just wondering why the faster languages ignore such a value proposition.

not sure what you are asking here. if you use a frontend framework with django as a backend to build your site, you still use django admin as before. there is no need to replace that. you are only replacing the end-user facing frontend.
The GP was suggesting chucking out django entirely as I read it.
oh, right, sorry, then that's a fair question.
Out of curiosity, what do you perceive as the main advantages of JS on the server vs Python?
It's personal preference that's all.

To be honest it's more that I prefer TypeScript to Python. Python and JS have been my main programming languages for 14 years or so.

Either are good - I'm not totally off python. I still write async web servers in Python for various reasons. I'm not much of a fan of Python's type system probably because I haven't yet spent enough time to really learn it.

I definitely use Python for Linux systems programming or non-web server stuff - Python is really great for more systems oriented stuff.

I really liked Django at first but after a while some things really started to bother me about it.

The ORM I found complex and clunky - any time I wanted to do something I kept thinking "Ugh this would be dead simple in SQL".

Needing to add plugins to Django - I often felt like it took me the same amount of time to work out how to install and configure a plugin, as it would to write the same functionality from scratch, with the disadvantage that at the end of the process I'd often still feel like the plugin was a black box that I'd managed to make work but was never sure I had done it right.

And the thing that really annoyed me most about Django is it's meant to be "batteries included", but the very first thing you need to do is work out how to implement users and signin and forgot password and signout - all stuff that should be the very definition of "batteries included". Instead, at the start of every Django project you're left to try to work out what is the right plug and how to install it and did you do it right. If I have to do all that stuff yet again for every project then why bother with Django at all? Why not just use a minimal web server and implement it myself because I'm going to have to anyway.

And then, after forming these hesitations about Django, I started doing async web programming with Starlette and FastAPI and found I really liked async web server programming and Django isn't async.

So at this point I'd pretty much lost interest in Django.

Yep, the future is JS full-stack. Especially with stuff like Trpc, Next, Server Components. These frameworks just have much more options to integrate the frontend and backend nicely.
I still like using Python on the back-end. But, I've also been waiting for what, 10 years, for Django to get async support.
So it’s a kind of survivor bias: those who learned JS stopped using Python for web backend.
I still like Django on the backend.
This isn't quite fair. The problem is that JavaScript expertise is still volatile. It is a use it or lose it skill. It quickly becomes alien unless you stay on the threadmill and keep up with the developments, patterns and tooling. I admit syntax is not actually difficult to relearn but patterns take time to acquire.

I've been programming for over 20 years and the languages and frameworks I favour have a sticky quality. These are the ones I can put away for years, return, get back into it and pick up new features in a few hours at most. The cognitive load of getting back into them are low.

I picked up django around 2011 and moved on to other things including JavaScript at the time. When I needed to build a Django project in 2016, there were some improvements and new features but the syntax, tooling and patterns were the same. It was possible to just jump right back in after a quick skim of the docs. It is possible to develop mastery of this stack, set it down for a few years and return to it with familiarity and continue on that journey.

The JavaScript ecosystem in that period however has pulled off a massive amount of transformation. I learned the basics of jQuery, yui, knockout, emberjs, backbone, coffeescript, ecmascript X, knockout, baconjs, rxjs, react with classes, react with hooks, redux, typescript, nextjs, react server components, react native, graphql, assemblyscript and on and on. It has been impossible for me to develop any deep mastery of anything in the JavaScript space. This does not even include the insane tooling with vague overlapping responsibilities. The closest I have found to reasonable stability in this area has been clojurescript with reagent.

I am constantly stuck in tutorial mode when I need to dive back into the frontend. I recently upgraded a 4 year old Django codebase in 2 hours. I am ripping out all of the react code because it is just not worth the effort any more. The tooling, dependencies and patterns are now outdated. HTMX has that simplicity and elegance that will keep the cognitive load manageable while I focus on the real problems.

> This isn't quite fair. The problem is that JavaScript expertise is still volatile. It is a use it or lose it skill.

This is true of most of almost all living technologies.

> When I needed to build a Django project in 2016, there were some improvements and new features but the syntax, tooling and patterns were the same.

Python and Django both underwent major transformations between 2011 and 2016. That was the 2->3 transition, class based views, channels, packaging was heating up, async came, and there were several syntax and libraries improvements. Were you more comfortable with Python at the time, is that why it was easier to get back into it?

Most Angular 2+ apps written in 2014 have essentially the same architecture as an Angular app written in 2024 (Directives, Components, Services, Pipes, etc, etc).

What you're describing reads like putting down any living technology and picking it back up again a few years later.

> This is true of most of almost all living technogies.

It's not really true for any other programming language. If I'm an expert in Java 8, I can build and ship a product using it. I don't need to be up-to-date in my knowledge of Java 17. Same holds for almost every language.

Javascript is an exception because you don't get to decide which version to deploy, so you have to constantly be keeping up with it.

It’s the opposite problem with JavaScript. JavaScript almost always going to be backwards compatible. But, you’re right, because you can’t control the environment you’re going to be perpetually using “new” features that are 2-5 years old.

For example, I can still run my projects from 2004 but I'll have to wait until 2028 to widely deploy my bleeding edge projects from 2024.

Hmm. I'm not primarily a web developer but when I do do web stuff that needs a database, Django is my go to.

I also try to avoid JS as much as possible. I honestly feel like it's a good design approach/directive - use HTML and CSS as much as possible, and JS only when needed and sparingly.

I'm not against it at all, I use it to expand menus, or to change a hidden field to visible based on which option in a dropdown is selected, maybe even some AJAX stuff.

But mostly if I can avoid it I do. My sites still look modern, but they are fast, and often the entire front page can load in 0.3 seconds or similar (according to various online speed tests).

I haven't ever needed TypeScript, Sass or whatever RxJS is.

(comment deleted)
Disagree on RXJS. Oh how I loathe it.
Anyone else actually having a great experience with full-stack typescript?
It can be nice, but TS the language lets you get really fancy and dealing with excited library developers gets old fast.

Also the TS compiler tends to be buggy and break in weird ways with minor version changes.

I just try to not use too many libraries given the npm ecosystem.

Sometimes you do need excited devs. When the domain is complicated I’d rather have fancy types than static analysis black holes.

I don't think the choice is hard to understand types vs no types with most runtimes.
It’s great, except that the compiler’s really slow and that trickles down to editor slowdowns, slow CI, etc. Also need to understand it well enough both to understand complex types, but also to know not to go overboard with types. Built a couple businesses already on it.
+1 I've found ts to be a good all-round project language. If I need something with performance, then golang if it's quick/dirty, rust if I need some more complex data modelling.
Unicorn is nowhere near production ready. The main author makes major changes in untyped Python and JS without any unit tests and every minor version change has had major regressions that can be hard to catch.
HTMX is gaining a lot of traction but is barely mentionned.

Seem to be a good pattern of adding what is needed and otherwise keep things as they are.

Do not have a lot of experience with it but I would gladly ditch our vue.js build process and docker image for the little web we actualy need to do.

After trying out htmx (for perhaps the wrong project), my feeling is kinda the opposite, it really didn't add much (if you want to just add css-animations to your otherwise static backend it's probably fine) but didn't help squat with actual work tasks (data and events updating the view), I ended up adding Vue to parts of it (and wrote another task with Vue from the start).

One difference for me is that I only pick Vue for projects that are large enough to need fully front-end logic but small enough not to need a build-step (And one could equally well go for React once a project is large enough to need a build step), this is where Vue really shines since you get the auto updating goodess but don't need to burden yourself with any build script complications.

We've build (and open-sourced) our own livecomponents[1] for Django and based it on htmx. That way we got a ton of client side functionality for free and didn't have to reinvent the wheel. Just this week we've retired our old react based webapp and replaced it with our Django livecomponents. htmx is awesome!

[1] https://github.com/om-proptech/livecomponents

That looks fun, thanks. Gonna try it out when I get a chance.
I'm wondering why these frameworks keep using HTML as a "communication language" between server and client ? I meant server sends a HTML fragment to client for it to parse and update the current DOM.

It makes sense for traditional web frameworks like Django to respond to client request with HTML, because it relies on browser's understanding of HTML text. But if these frameworks ship with JS anyway, why don't they use something else, like a data structure that is native in the programming language that they are written in, to describe the UI. Their JS component can parse that and render the UI. The JS component is basically just a templating engine on client side without all the routing, state management, etc complexities of a SPA framework.

I feel like not using HTML for server and JS component could simplify a lot of things. I guess my assumption here is that both server side programming languages and JS could use a better data structure to communicate than HTML text.

I'm not familiar with these new frameworks or have ever implemented a frontend framework, so I apologize for this probably silly question.

The approach you're describing is pretty much how frameworks like React work. I think there are two main reasons why the more lightweight options don't go for this:

1. In the React space, you have to write two conversion steps: first you have to convert your app's data to some wire format (JSON objects or something) on the server, then you have to convert the wire format into HTML on the client ("render" the UI). This is more complex than a single step where you just convert the app's data to HTML on the server.

2. For best performance, the server needs to be able to generate HTML and send it to the client on the initial page load. (React calls this "server-side rendering"; its approach to it doesn't really work for lightweight frameworks because it requires you run JavaScript on the server.) Once you have that capability, you might as well use it as much as possible, rather than implementing a separate code path just for JavaScript.

I see. I forgot about server side rendering scenario. Thanks!
you have to write two conversion steps: first you have to convert your app's data to some wire format (JSON objects or something) on the server, then you have to convert the wire format into HTML on the client ("render" the UI).

disagree. the first conversion step also happens in the backend where you convert your data from the various sources into native (eg python) datastructures. converting that then to json is almost trivial. it just forces you to design an API and consolidate some structures to reduce the number of round-trips.

I've heard great things about HTMX+Django.
I've yet to come across a use case where I would need or improve things by using HTMX
Theoretically, you could have a single-file SPA using HTMX, Alpine JS, and Tailwind.
That sounds gross. Why would anyone want that.
For fun? I did something similar to build a small site for a non-profit. Looks nice, easy to maintain, fun to build.
I would be wary of mixing two frameworks in one project, since that would require the intersection of relevant skills from future developers or maintainers. One must be sufficiently familiar with both ends (and any idiosyncrasies of how they are used in this instance) in order to jump in and push changes that don’t mess everything up.

If coming from Django side (which I did), consider whether you really need a separate framework for the front-end. Nowadays, JavaScript isn’t that hairy, and browser runtime comes with tons of batteries and syntax sugar that make it easy to write complex things. Maybe you want to use a small library like React (which is, of course, not a framework) for certain widgets, or even introduce an extra build step and write TypeScript, but sticking to vanilla overall can be key to managing cognitive load for others or your future self. Yes, maybe you’d need to write a tiny bit of boilerplate (much less than in IE6 days!), but on bright side—basic language reference (e.g., MDN) would be enough for anyone to grasp how it is generally put together.

If you are considering using a framework and your front-end part is sufficiently complex for that then consider if you should rather architect it as a separate project. Putting strong boundaries in place can help keep it manageable, problems are isolated to one side, and it’d be more easy to find someone who is best at Django or best at (insert your front-end framework of choice) in future.

i strongly agree with the separation into two projects. that's the real advantage of frontend frameworks. for me backends are now only providing a REST or GraphQL API and no more HTML templating at all. the HTML stuff is done only in the frontend.

that also takes care of the problem of overlapping skills. sure, you need to learn a new framework, but really, it is not that big of a deal. if you have been creating complete websites from CSS/HTML to the backend, it really doesn't change that much. your CSS/HTML skills apply unchanged, and the only thing that is new is javascript itself and a new templating system.

the problem (as other commenters noted) stems from backend frameworks trying hard to avoid javascript. so they will try to do as much as they can in the backend, and i can imagine that throwing a full frontend framework into that is going to be challenging. i never tried it. as soon as i started using frontend frameworks 10 years ago, i was done with server side HTML generation.

That works great for apps, not so great with content sites.
why is that? if you are thinking that content sites should work without javascript, then that's an entirely different issue. but aside from that, frontend frameworks work just fine for content sites, and there is absolutely no duplication of any logic in frontend and backend. i have built sites like that myself.
In contrast to sibling comment, I think you have a “content site” then you don't really need a framework. Vanilla can be enough.

However, there is no clear line between a content site and a web app. That’s why I suggest that, as a rule, if you see front-end becoming so complex that a full-blown framework is a must, then it might save you in future if you architect it as a separate project. (As sibling comment points out, it doesn’t need to compromise the ability to render static HTML and degrade in UAs without JavaScript.)

i don't want to get into the argument about what is better for a content site. that's not the point. i am only focusing on the cognitive load argument. to reiterate, for me the cognitive load is no different whether i use a frontend framework or not. i need similar structure and logic for the frontend, regardless whether the frontent is built with a frontend framework in the browser or in a backend framework on the server.

ironically, the main reason i would use a frontend framework for a simple content site is that it would allow me to build all my sites using the same specific frontend and backend code, which actually reduces the cognitive load because i can build my new site just like the last one.

obviously, if you want your site to work without javascript at least as a fallback then that's not a good idea, which just goes to show that maybe using cognitive load as a metric itself is not a good idea.

> for me the cognitive load is no different whether i use a frontend framework or not

A framework, as opposed to a library, requires you to understand its way of thinking, so there is a big difference in whether you must understand one framework or two frameworks in order to make any change. If you have a single project that intermingles two frameworks then your cognitive load is necessarily higher than if you are dealing with only one framework and in future you (or your client) have to hire someone who knows both, and knows them well.

The cognitive load is lower if you know both frameworks now in their current state, but we all know frameworks evolve and go in/out of fashion.

In addition to the above, depending on a framework is a big thing. Due to inversion of control, it’s much more difficult to refactor something that’s written in a framework, rather than just using some library. Going with two frameworks multiplies that problem by two. It’s like constructing a building on shoulders of two giants that can go their own separate ways. If something happens to either one of them (changes license, changes core team & direction, gets abandoned & no longer receives security fixes, etc.) you’d have to redo a lot of things.

Going with vanilla means you don’t need to grasp another framework, even if you need to write a bit more code today. Going with cleanly separated projects means your cognitive load is limited to one framework at a time (plus the connecting layer). It’s more easy hire someone who’s great at back-end & Django and someone else who’s great at front-end & Alpine, instead of finding one person who happens to be great at both.

> it would allow me to build all my sites using the same specific frontend and backend code, which actually reduces the cognitive load because i can build my new site just like the last one

Sure, adopting a framework whenever you want to save on boilerplate code and cognitive load today would work (thanks to the same inversion of control), but I find is likely to cause maintainability issues and more cognitive load tomorrow.

> obviously, if you want your site to work without javascript at least as a fallback then that's not a good idea, which just goes to show that maybe using cognitive load as a metric itself is not a good idea.

I think making the site work without JavaScript is a different problem, you can do it regardless of whether you use a front-end framework (unless the particular framework you use makes it difficult).

Solid article, although part of the conclusion is a pitch to purchase the author's book on Django + Hotwire, so perhaps take with a grain of salt.