Browser native, zero-config, micro frontends
The topic of micro frontends (MF from now on). Is one I have dealt with before, in my module federation article. It's something that really interests me since it allows you to frankenstein websites from little parts of other websites. Now module federation is awesome, but it requires a bundler, plugins and setup, albeit a pretty easy one.
There are however other options out there:
- SingleSPA, which is a JS router for micro services.
- iframes. Yes you read that correctly. iframes are micro frontends, they allow you to import other sites inside another one, and display content hosted somewhere else.
Today’s challenger is none of the above. It actually requires no setup at all. Is supported in all of the browsers and it is dead simple. Yes I am aware as of the time that I am writing this one, Safari is not supported per the MDN docs, but it will be on version 16.4, per their release notes. So based on the above they are also browser native!
The feature is importmap. What is an importmap precious? you might ask. Well an importmap is a type for the script tag. It allows you to alias name, to some url that contains a script, in a json format. Allowing you to use:
import X from aliasName
Inside your JS. So how do you actually use that to make MFs? Well since you can treat your imports as a named module, that allows you to do, just the above. And thanks to web-components and lit, You can import some pretty cool and amazing stuff, including components with independent routing. Imagine this, you have a root application, inside it you put and importmap tag, pointing to external urls. Were each url, server some web-components, and those web-components behave independently and each one of the has its own routing rules. Allowing for maximum flexibility. Sounds good?
Well, here it is: repository you will find guidelines on how to run and built it.
We have 3 projects.
Each lit project has 2 routes,
- ‘/’ - has a simple message saying this is mfe-X
- ‘/special’ -has a webcomponent that fetches some data from the public pokemon api.
‘one’ fetches the first 10 items, ‘two’ fetches items 11-20.
Each project has its own init() func that mounts the web-components to a div tag with id of “app”.
Both projects are very similar. I just make sure we export the bundles with a stable name when they are built. So we can predict them. The only setup that was needed was making sure when serving the preview build, it was on a particular port of my local machine. Otherwise if you run this on a server, there is no need for something like that.
In this case I will be serving those components under ports 8080 and 8081 under their names.
Now on my root project, all that is needed is to define the importmap as below. Import the init methods from my named imports and run them.
As you can see on the network, we get our web-components code over the network. And we can navigate to different routes and each will behave independently.
The '/' route:
The '/special' route:
Cheers! Thanks for reading!