I was planning to build an online portfolio as an OS clone, my idea was to build it as a portfolio and present mine different project as apps with capability to add any app in runtime.
Then I dropped the idea and stick with capability to add any app i.e. Micro frontend. The OS clone is mostly gimmick.
- Folder Navigation
- Photo app
- New folder and rename folder (not for desktop route, bug!)
- Start Menu (though nothing is clickable)
- Rearrangeable Quick apps (Tutorial)
- Notification Shell
- Quick Actions
- Calendar micro app
- Upload app have stopped working ( Probably due to space or similar constraints on Heroku)
It's a design approach similar to micro services, instead of creating a big frontend app we can break into a collection loosely coupled frontend apps built on same or different technologies might be working together.
Years back we used to have website/apps with bunch of HTML or PHP files. Around from 2006 people start updating the page with partial HTML into the DOM using browser API's updating the portion or complete page with a never need for a reload, these were the building steps towards the SPA.
Then in 2010 Angular came and took the web by storm as it was introduced by Google almost everyone was into it, it bought all the good and required parts needed for SPA in one place the Angular Framework. Back then it was really amazing it still is and a lot of things have changed. After a while in 2013 React was launched by Facebook and it doesn't took it much time to gain the upper hand from 2015 React had almost double the downloads source: npmtrends, and now it's around 20 times more, there were various reason behind this like virtual DOM which made React more performant (though Angular caught up later), low learning curve, JSX etc.
Then came the the Micro frontend
"An architectural style where independently deliverable frontend applications are composed into a greater whole"
The goal is to make development and delivery easier for different teams ideally there should be no dependency on each other, failure of one app will not effect the others, simplest example can be a nav which loads different app on each route, without reload.
User will never know how the apps are loading the are different or components it will behave like a SPA but behind the scene there can be multiple apps powering it. Instead of route they can also co-exist on same page, like widgets exist on home screen of mobile or desktop.
Those widgets belong to different apps but work on same screen and are totally decoupled but if you will load two widget from same app, like Todo list and Todo Counter, completing a item from list should also decrease the count, here the data in store is updating and other was listening to it, other method can be dispatching events.
- Build any app on Code Sandbox using the CRA template with nothing in public folder. (This has not been handled yet)
- Zip the app.
- Upload with App manager with required meta data.
- App will be installed in OS to use in runtime.
The calendar app there was uploaded in same manner!
This all sounds cool, but whats really happening?
There are numerous ways to do this, we just need the app code/bundle which we build with Code Sandbox and a specific div to mount!
Okay so we need an app bundle and we have a zip, then bundle it!
That's what happens on uploading an app, I unzip it, copies required files to bundle, a Webpack config and few other things. The reason I am not using CRA's react-script because I need a single bundle (
main.js)! (We will cover this later), have to handle assets so I can load them appropriately.
After building the app, I pushed it into a bucket with a specific prefix, a unique ID generated during app upload. Now whenever user clicks on the icon, main React app calls for bundle of that mini app.
Every asset including
main.js is behind an endpoint right now in the node app which in turns streams the files from bucket, so even if the bucket url changes the I will only have to update my endpoint's controller, I can enable CDN here as the all are files for faster delivery.
On the UI side whenever user clicks on an app, along with fetching the
window to facilitate that.
When I was creating this whole scenario I was unable to figure out how to get entry points for particular app, as if an app will have multiple chunks few chunks will be require to start the app this can be done too, then we will need to load those JS files/chunk while instead of just loading single JS file.
This was an POC so auth was not important but there is an option to sign with Google to upload apps. Let say an app Chat requires user to sign in now authenticating same user multiple times for different apps doesn't provides a good experience, this can be solved by off loading the user management to a single app, the main App, if any other apps require authentication they can share the access token of the main app and get back an access token for that particular app. On server side Chat app micro service will be communicating with the main app service to generate an access token specific to this app or they can just share the one token for each app.
I tried to keep a very modular approach while development so I can make everything as Micro apps but haven't done so, this way the can we replace or update any app on runtime and different user can have different apps for same thing, like the folder app. An app just need to follow the schema for CRUD operation how they do that is up to them.
Not every big app is needed to be breakdown as micro apps, there are other ways too, even for easier development like Bit ecosystem, or just a better component model! It all depends on the requirement.
Feel free to share your thoughts/feedback in comments!