So bake those supply chain vulnerabilities right in there, nice and deep.
When you load 50 (or for the tree, 500) independently developed modules the probability of failure (or vulnerability) is typically the sum, not product, of the failure probability of each component. The same reason why not everything is implemented as a fleet of microservices.
Few worry that the TCP implementation in your OS is a monolith, and one that is tightly integrated with the IP code. This will make increasing sense further up the stack, for good or ill.
There are trade offs both ways.
But yeah, agree that the odds of failure are probably lower pulling in a handful of monoliths that are well exercised than hundreds of miscellanea of varying robustness.
That's not even including the fact that processors are actually processor simulators these days.
Thus, "bare metal" is actually "resource division among managed processes on a simulated processor" which sure sounds a lot like a VM to me. Modern OSs are in fact a form of virtual machine, and we found it useful to have yet another.
Arguably docker type of simulation introduces yet another level so a react app in a docker shell in a VM cluster is really a interpreted application on a simulated operating system, on a resource sharing virtual machine, on a virtualized hardware environment, on a multitasking virtual machine, running on a simulated processor that's implemented on a _real processor_.
If you write a program that is launched by an OS you are by definition not manipulating the hardware directly. Those POSIX calls go somewhere.
I write such code from time to time: a boot loader, a small OS, or apps that run with no OS at all.
40 years ago writing code was a lot harder; improving that has allowed a lot more interesting things to be built (both bc people can work faster and at higher levels of abstraction and because development is more democratic, leading to a wider pool of people writing things). The cost has been high though; few people think about the hardware and even the term “bare iron” is used unironically to refer to a machine running a multi-tasking OS!
But I think this will swing back the other way. Not by removing the abstraction but by “melting” some of the abstraction implementation layers. Hard work on improving interpreters and compilers has always been one of the ways, but assembly-optimized hotspots and tighter integration in some of the stack elements will be increasingly worth doing because fixing that speeds up all the developers working at higher levels.
The downside is that you won’t be able to, say, easily customize that version of React you’re deploying. But nowadays you really want to stay away from that anyway, in 99.99% of cases.