As someone whose walked through a lot of code-bases, I rather hate the "unmagic" just-write-whatever-nest-of-route.js-files-you-want path.
It's easy to write routes in express, yes. But every company & usually every project in the company usually does it differently. Oh this person used a glob tool to find all the route.js files. Oh this person has nested route.js files littered about. Oh this project is just a massive ultra-complicated routes.js.
A huge part of the win of DI & places like Java JAX-RS is that code one place looks fairly alike code another place. Dependency Injection frees us from having to know a project well, from having to be familiar with structure; we simply ask or tell, & there's a system there. I find it elegant that Express routing concerns, React concerns, and all the various configuration/providing systems you might need can be managed via IoC. Recent TypeScript example I found of these concerns, in Injex:
https://www.injex.dev/docs/plugins/express#get-post-patch-pu... https://www.injex.dev/docs/plugins/react#the-renderinjexprov...
There's a lot of push back against "magic", but really I think it's something that served Java extremely fantastically well, particularly the Dependency Injection/IoC systems. I think developers of those systems got a ton of value, and it was really understated just how noble & simple those worlds were, how clean & easy it was to walk up to any random controller & be able to discern more or less what data was going to get used, in what scopes. By not having all that stuff written in the ad-hoc, existentially open world of declarative code, and instead encoded as normative, regularized, low-overhead annotations, there was a kind of predictability & visualizability & simplicity that I think a lot of these practitioners probably sorely miss, now that they're probably mostly writing Node.js like nearly everyone else. ;)