Context
I do software for 10 years. At the beginning I did pure web: django, backbone, jquery, gulp, react, you know.
Since then the rest of my career I did mostly Go backends: some data processing from elastic to postgres, from kafka to mongo, kubernetes integrations, terraform providers, javascript sandboxes and just simple RESTful APIs. I have a few friends from web, mobile dev and I tried developing a desktop app, so to me it feels easy to imagine what to expect developing a declarative UI.
What do I want to see in a development flow?
- Declarative UI. I don't mind seeing XML like things in desktop or mobile, so I anticipate having old fashion HTML with a few tricks is ok.
- Strict schema. In a designated API service ideally we have OpenAPI. But we do web, right? I see 2 options:
- we have the schema first and generate code for both a client with options to inject interceptors, for instance to inject an auth token from the cookies (pls don't use local store for auth tokens). Protobuf provides this kind of experience, I can't get why it's not deeply in the culture to have same standard with OpenAPI, or Swagger if you will
- or we have a server that defines client's available methods to call and its data model
- Predictability. We all need debug the apps sooner or later. And if you are for a while in the industry you want to go deeper to the function definition to read its source in order to understand the problem. It makes reading documentation a bit easier and learning process smoother. "No magic" term is fine for me.
- Clear separation of concerns. Back then in django/rails/etc. We had a view layer and we knew it's the only layer might be exposed to the user. I wouldn't say it was easy to understand how to expose sensitive data to the client, but it was simple.
So how was it 10 years ago?
Suboptimal. People were looking for decent approaches to build web.
Since then we have amazing changes in web:
- tailwind: it's not only about dev experience, but a huge jump to reduce client bundle size dramatically. It's even more beneficial for dummies like me, having such a simple tool to produce efficient UIs, it feels amazing.
- Tons of headless UI libraries and shadcn, it gave every small team the ability to establish its design system in 20 minutes, huge step forward.
- Vite is a standard for building apps. It has so many smart moves in there increasing quality for anyone who steps into it, while webpack made manually come up with things to minimize the bundle.
- React and friends. For anyone touching it it's clear - it makes sense. Having HTML right in the view layer shows you the markup of the component and its state. After things like dojo and backbone - ofc it's a way better.
- Astro. Not well adopted yet, but static content also jumped forward. Behind vite config it hides dead simply but efficient idea - islands. Im pretty sure it gotta change SSR and SSG forever.
Well, lots of positive things, let's build an app after a long break.
Picking UI
React. Well, it's changed a lot. I don't want to be an old farter who complains on changes, but there are tons of features people rarely use. Ok, it's a matter of taste. But it made the bundle size jumping ridiculously high, it's not ok. Treeshaking you tell me? Doesn't seem it helps much, it's still the most bloated UI library. We thought progressive internet quality and speed around the globe, but we make software worse to make the progress diminishing.
Vue has a bunch of magic where a "property" is not case sensitive may break the entire app, seems odd to me.
The only 2 real alive alternatives are Svelte and Solid. Svelte is clearly taking a track to become the modern rails and Im not very fond of it.
Giving it API
There are many options today:
- Write a regular api service, generate OpenAPI, generate models, etc.
- Use trpc/orpc like and generate API from that. To me it feels correct, we have a strict schema communication, breaking on one side we have a type error on the other. Then generating a schema from the implementation we document what we implemented instead of promising what we plan to implement. This approach eliminates overpromising and that's a big deal. We can see its evolution in svelte remote functions and similar attempts in next/nuxt/solid ecosystems.
Adding Next JS to React apparently make it even larger in bundle size, so not every meta framework is a good choice. But not having a meta framework makes SSR a way harder.
There are alternatives to solve SSR with traditional backends like inertia.js, but having different languages don't give so much joy of immediate data types sync between server and client apps. After touching trpc/orpc it feels wrong. If I need a niche purpose backends like Go for integration with networking services chances I need SSR close to 0, so I can generate openapi from it and then client models with 0 worries.
Building all together
What do we have left if I want:
- small bundle size
- decent performance
- well defined unified API layer
- no magic solution
- SSR
I have nothing.
Traditional backends + inertial.js may save us, but introduce tons of others complexities, so in the best world we look the answer in the meta frameworks.
React is no go with a raw bundle size of ~100kb today, adding any UI library makes it at 150, adding a bit of code makes it 300+ in the best case.
Vue might be very close, but having case insensitive attributes drive me nuts. things like v-for="item in items" undebuggable. how do I know the items there is what I meant? no way, only to run the app and take a look or pray my team writes the tests. A single typo may destroy a page.
Svelte is promising in quality: small bundle size, great performance. But so much magic frustrates me. Like in rails there is no logic, everything is declarations of the concepts. I have to learn the framework instead of software fundamentals to understand $state, +page is not just a file name and a remote function is the actual API call depending on the execution context (server or client). It doesn't give "simple" solution, but gifts the "simplicity" with the price of an abstraction layer worse than ever before. And all of it with the mixed context where is the server where is the client makes it even worse.
Solid has all the UI benefits of React, all the performance benefits of svelte. But doesn't have any adoption. Its UI libraries are months passed since the last commit. Solid itself and Solid Start have 3 weeks gap since the last commit. Im more than confident it's simply due to lack of financial support and the need of having a commercial job for the maintainers.
Conclusion
Closer to finish I find this 30 minutes writing as a pure nagging about sveltekit having too much magic and solid not enough adoption. Although most of the people don't share same feeling.
It's surprisingly (no, it's not) sad to me people had better learning frameworks than software itself.
People don't like simplicity and it frustrates me as very few people look for it.
Accept the rules, take whatever worse we have I guess and keep going if you need web. I would be happy to see Solid having independent financing and larger community engaging.