An Express web app

As promised, I'd like to write about my personal Express.js experience. A brief disclaimer: I know it's considered outdated, and I know everyone is writing with bun + Hono + TypeScript, but I have to say something. I compared Express.JS + JavaScript for single-man small projects with the following options, which I call web frameworks for non-programmers:

And my criteria are a bit special:

Fixing Express

The widely known drawback of the JS ecosystem is that it's very fragmented, and it's hard to figure out what to pick for your needs. And it turns out that reading the express.js manual helps, at least it helped me. To get a nice app structure, you could use something like:

npm init -y
npm install express
npx express-generator -v pug --git
npm install

The idea here is to get something similar to Django in terms of the structure. There was MVT (model-view-template), and we got to an MVC (model-view-controller). Express generator doesn't create separate files for controllers, but it's not complicated to do. After that, I got to a structure I liked, and I almost have my urls.py now! That's fine because this structure allows you to concentrate on writing the code and not think much about the structure anymore.

Regarding Pug

I fully understand why the mainstream is now with JSX and other HTML-based templating engines. Again, my tastes and requirements are very specific:

The syntax with meaningful indents resembles Python, and that's not bad at all if you ask me. Returning to the old templates and modifying them is as painful as it can be, just because I don't mess up with the angle brackets. And I didn't see any alternative to Pug in this regard. And I didn't migrate to another framework just because Express.js has basic routing and Pug support. That's all you get, and that's all I need. In my current app under development, I spend a lot of time writing templates, so it paid off.

CSS

Regarding the CSS, I fully understand why everyone is using Tailwind.css, but I just don't need all that, and the functionality is primary to me. I tried some styles and am completely satisfied with Pico.css. The forms are great there, and I use forms heavily. I work mostly with the placement of the elements on the page, not with their appearance. And I'm quite happy with that for now. By the way, Pico.css has some CSS-only nice interactive elements like accordions.

HTMX

HTMX allows you not to reload a full page, and that's what AJAX is about. And HTMX is a user-friendly interface for AJAX. You have to invest some time to learn how to use HTMX and what level of interactivity you can get. It's opposite to the React approach, for example: there you have an interactive app, you need JSON from the back-end, and you don't think about it at all. Here you need to think: about what's on the back end, what's in HTMX, and how to change the back end because of that. After that, you get some real-world use cases for HTMX. I first developed a page without HTMX and then added HTMX to improve user experience. If it doesn't work out, I just return to a static page. Sometimes I had several iterations, for example with tables.

It's easy to delete a row from the table, but when you add a row, you need to know: should I add a table header as well? I thought for some time about that, and I didn't like this idea: I needed a lot more code on the back end, so I stayed away from HTMX. But then I thought: it's useful to redraw a table alone in this case, there's no 'if' for the table header.

Sequelize

The reasoning behind choosing Sequelize was its pure-JS nature. I just compared the code I needed in Prisma and Sequelize for the same task. Sequelize is also not a full-auto migrations generator like Django, but you can generate a database structure and a migration with one command. It makes you think about the structure beforehand, but the structure is important. In terms of learning, it's useful and not so hard.

Typical tasks

Regarding logging the users in, I know that JWS-tokens are the best, but I failed to implement it and backed to express-session.

For file uploads, I used multer.

I like using Markdown, so I ended up using marked for that.

The workflow

Experience with Django helped a lot to figure out the most important thing – my development workflow. I mean something like this:

  1. Adding tables to the database and migrations with the Sequelize CLI
  2. Adding routes
  3. Adding templates
  4. Adding controllers
  5. Modifying routes, templates, and controllers to add HTMX

The trick is that this workflow is described in lots of tutorials and courses for Django, but it's impossible to find a similar tutorial for Express. Just because Express is so non-opinionated and lots of components exist. The components combination and the workflow can be different in each case, so Django was a template that worked for me. When you are looking for an Express tutorial, in many cases you find tutorials for MongoDB, but it's so different, that it changes the application logic. And that was the major difficulty for me.

Conclusions

Compared to Django, I think I progressed in many ways with the web app:

I've heard one thought from Primagen: the best framework is the framework you enjoy working with the most. Thus you can progress better and faster. Now I feel not constrained to implement my ideas, I have some more ideas to implement, and I don't find it complicated. I wish you could feel it, it's a very pleasant feeling.

If you made it this far, you may be interested in checking my git repo for my ugly web app.

That's all for today, see you! More ugly web apps are to come! :)