Thursday, May 17, 2018

Microservice Approach for Web Development - Micro Frontends

This post is based on my Oracle Code 2018 Warsaw talk. View presentation on slides share:


Wondering what micro frontends term means? Check micro frontends description here. Simply speaking, micro frontend must implement business logic from top to bottom (database, middleware and UI) in isolated environment, it should be reusable and pluggable into main application UI shell. There must be no shared variables between micro frontends. Advantage - distributed teams can work on separate micro frontends, this improves large and modular system development. There is runtime advantage too - if one of the frontends stops working, main application should continue to work.

I have implemented micro frontends architecture with Oracle JET. Source code is available on GitHub repository. There are three applications, two with micro frontends and one is the master UI shell. Both micro frontends are implemented as JET Composite Components. First is hosted on WebLogic, it calls ADF BC REST service in the backend. Second is hosted on Node.JS and returns static data. First micro frontend implements listener, it allows to handle actions from the outside.


When JET application is accessed in your browser, bunch of HTML, JS and CSS files are downloaded from the server. Core idea with micro frontends - instead of loading HTML, JS and CSS for micro frontend from the same host as master app - load it from different host. JET Composite Component rendered inside master application will be downloaded from different host. Not only downloaded, all backend calls should go to that host too, not to the master host. JET Composite Component integration into master application architecture:


This is how it works in practice. Each of these charts is separate JET Composite Component, loaded as micro frontend from different host into master application. We can see that in network monitor. Loader.js scripts for both micro frontends are downloaded from different hosts:


Runtime advantage - if one or multiple micro frontends are down, application continues to run:


JET Composite Component runs on the client, even it is hosted in its own micro frontend. This gives possibility to subscribe to the events happening in the component in the master app and route that event to another micro frontend. In this example, once item is selected in job chart - employees chart (another micro frontend) is filtered:


Technical implementation

Main application must be configured to support remote module loading for JET Composite Component. Read more about it in Duncan Mills blog post - JET Custom Components XII - Revisiting the Loader Script. In short, you should add Xhr config in JET application main.js:


Server where micro frontend is hosted, must set Access-Control-Allow-Origin header.

Main module where both micro frontends are integrated is using JET module component. Each micro frontend in master UI shell is wrapped into JET module. This allows main application to function, even when micro frontend in the module stops:


JET module is initialized from variable, which returns module name:


Jobs module contains Jobs micro frontend - JET Composite Component. It is hosted and WebLogic and calls ADF BC REST in the backend. Component is assigned with listener:


The most important part is in JS script. Here instead of referencing JET Composite Component locally, we load it from remote host. This allows to develop and host micro frontend JET Composite Component on its own:


Listener refers to c2 element and cals the method. Element c2 in the main app relates to second micro frontend:


This component is loaded from another host, from Node.JS:


Important hint - for JET Composite Component to load from remote host, make sure to add .js for JET Composite Component script, as highlighted (refer to source code):

3 comments:

Luc Bors said...

Hi Andrejus,
Great post. I'm currently working on exactly the same stuff, works great.
Even preparing a blogpost, but you beat me to it :-)
My issue is when I have no control on the "remote" microservice.
I have multiple microservices, based on JET, ReactJS and Angular built by several teams, which I can not tell to create specific stuff that I would need for integration in the main Shell.
This could mean remote microservice does not provide a JET Composite Component (or Webcomponent when others UI technology). Any suggestions on how to solve such situations (other then iFrames)?

Andrejus Baranovskis said...

Hey Luc,

When there is no single standard, then its hard. Wild guess from me - may be you could follow 3rd-party library integration approach in JET. Each "library" - will be loaded remotely, instead of locally. For example - Fullcalendar.io library, is not written with JET, but can be integrated into JET and calendar will be displayed. So, what if that would be some micro frontend, loaded as 3rd party library from different host. May be it could work.

Regards,
Andrejus

Luc Bors said...

Thanks for your reply. I'll try some stuff over the next couple of days. Will keep you posted.