You can either use shared dependencies from the app shell or share dependencies independently from your microfrontends using import maps. The former involves additional responsibility on the app shell side (dangerous) the latter potential overhead in case of unaligned dependency versions (then these are loaded multiple times).
It’s not a silver bullet and requires A bit of overhead. I’m interested too to hear how other people manage the problem.
Most our projects where microfrontends have been actively demanded (and we did now quite a lot of them) did not come up due to use of multiple frameworks. Yes, it is possible to use multiple technologies, but quite often there is key technology in place anyway. E.g., one of our clients had a huge pattern library written in React and demanded all microfrontends to be written in React.
So why then microfrontends at all? Well, all parts are still independent from each other, i.e., independently developed and deployed. Our client has multiple teams and like that these teams can just work in their own pace using a few guiding principles that have been given by the solution architecture.
Agreed, the only mention of using different technology has come up in the current project is in discussions of Typescript vs plain JavaScript. That’s been the only bring-your-own-technology for the most part, since we’ve standardized on React and some shared libraries like Lodash.
We’ve primarily benefitted from the forced feature and team isolation (aka domain boundaries if you would), plus it gives teams more granular control over their deployments. So, pretty much just what you described.
Another benefit has been our ability to build once and share features across different applications, since we have a few of those for reasons. Teams can build out different “views” (roughly) for different use cases on different apps which share the core functionality.