Yes and no. I both agree and disagree.

For a lot of it, yes, it is a giant mess.

I'll posit the reason modern front-ends are a giant mess has to do with the fact that everyone tries to hack, slash, and transform the document model into an application model. This means they don't want to reload the page, and they then have the burden of manipulating the DOM in a very crude way.

This creates a predictable empire building game of building a framework to make it easier, and every framework succeed to a certain degree. Now, they succeed in a number of great ways, but then they run in the abstraction leakage which causes them to bend in strange ways. For many applications, that's fine, but as the number of applications grow this creates problems for the common case. So, quality gets harder to achieve.

Now, the philosophy that I believe is that we just don't think simple enough. Most people don't think deeply about this stuff (and good thing because we would never get anywhere without people running forward making messes), so what do we do?

Well, I think the real answer may not be to fix front-end development. Instead, I'm coming to the conclusion that we should fix back-end development. Instead of using the tried and true work-horse of request response (i.e. HTTP), we need streams (i.e. WebSocket). Streams let you pair-bond state, and this is exceptionally important.

Ignore the complications of WebSocket for a moment (I don't deny there are problems, but they are solvable; just no good common solution yet).

What a stream lets you do is pair-bond/entangle objects, and this lets you simplify the development model to a great degree such that the front-end object is a proxy to the back-end model. This entanglement then forces you to contend with two things: (1) how do I change the object, (2) how to respond to object changes.

Once you address those two concerns, you can build applications fairly easily. Using this framework, we can then see work towards understanding why modern web development is so painful.

Since objects don't tell you how they change, you have to reconcile that change. This is why things like react have a shadow-dom, but you still have to read state from server then shred it into components for that to work. It's easy to miss an important data point since there is no direct entanglement. Ultimately, you have to take an entire object and then mangle it into a form that is pretty to the user without disruption because the DOM has hidden state (i.e. scroll bars or text selection). Classic web avoids so many problems because that disruption is built in.

Since failures of the request will happen, you further have to deal with partial failures of state changes which is why you generally need a thing like Redux to be an immutable state container so you can rollback state changes. OR, you need GraphQL such that the client only deals with atomic failures. However, most people fuck up GraphQL, so you have to have both GraphQL and Redux.

Things like svelte are better because it uses language techniques to help you shred your data into DOM, but it still suffers.

My claim is that you can simplify front-end development BUT you must also simplify the back-end, and I'm doing this over at http://www.adama-lang.org/ where I'm solving the problem for board games. I claim that board games are a limit point of technical complexity for transactional interactions between people, and partial failures are catastrophic for the experience.

The way that I'm building a game right now is that I have a client which I can connect a giant JavaScript object to the server. There is no proxy, just an object. The server will then get an update, then update the object and tell you about it via a change callback. These change callbacks allow you to synchronize the DOM to the object without an intermediary. The DOM callbacks can safely read the object.

This lets me use vanillaJS without fear.

When some DOM callback wishes to change the object, then all it does is send a message via the stream to the back-end which will (1) authenticate it, (2) validate the change, (3) incorporate the change, and (4) spit out a data change. Much like a database, the UI is a tailer of the log.

The JavaScript library I have is in its infancy since I'm balancing my time between the language, the devkit, the client library, the distributed system design, the game tools, the canvas renderer, and ultimately the first game to launch.... And I'm only working on this 2 hours every evening until I retire, so... it's going to take time.