WASM standalone runtimes are mostly fine, but WASM in the browser is not great. No direct access to any web APIs (this often really hurts when shuffling data to/from WebGPU). Multithreading via WebWorkers is a complete pain to setup. No zero-copy APIs for streaming data in/out. Little paper cuts, but they all add up...
Probably an unpopular opinion, but IMHO the WASM Component Model is an entirely overengineered boondoggle that has no place in browsers.
It's trivial to create small statically linked WASM programs in the "a few dozen kilobytes" range with the right programming language (like C).
"Code sharing" via dynamic linking also works, but it has the same downsides as dynamic linking on native platforms (basically that DLL interfaces represent an optimization barrier): https://emscripten.org/docs/compiling/Dynamic-Linking.html
Memory management is pain. If you want to optimize, you're forced to 4k pages. Runtimes are fragmented. Wasi is a mess. Async and threading is awkward. Whenever you need to integrate with hardware you need platform specific adapters.
In practice, whenever you need more than a singlethreaded app with http/serial port, the "run everywhere" breaks.
Don't get me wrong I love WASM but we're not there yet
WASM is called WEB assembly but it can't access the Web API's without paying tax to the JS tyrant in between.