Page Building using Micro-Frontends and Server-Side Include
Sharing information, knowledge, and ideas around the world has been the internet’s main goal since the beginning.
The beginning is the most important part of the work — Plato
We’ve faced the need for easily creating personal pages. This is why Rasmus Lerdorf created PHP and named it Personal Home Page when the first version came up and some years later it wasn’t enough. Therefore we created CMS platforms for easily creating and distributing content.
Nowadays micro-frontends extend the design principles of micro-services to the frontend world providing the ability to distribute views and compose them inside a page. However, in order to achieve that premise, we need to go back and start again thinking on those views as services instead of reusable components in code.
The page layouts on printed media and websites define the elements inside a page and how they're arranged together. Composing views from different micro-frontends inside a page is one of the challenges we’ve faced implementing micro-frontend architecture but we can make it easier following the next implementation approach.
Nova came up as a base architecture to easily develop micro-frontends using hypernova.
If you’d like to know more about how Nova was created you can read my previous articles.
Nova directive: It’s a custom implementation which renders a placeholder with the necessary data for enabling Nova middleware to request and include the views inside the page.
Nova proxy and middleware: It’s a proxy server for Server-Side Include(SSI) micro-frontends using transclusion. Nova middleware parses the HTML generated from the origin server for getting the necessary information in order to request the views to Nova cluster and include them inside the page.
Nova cluster: It’s a micro-frontend aggregator for enabling consumers ask only for the views they want without know which micro-frontend can render them.
How does it work?
1.- A user requests a page to Nova proxy.
2.- Nova proxy passes the request to the website server.
3.- The website renders the page based in a layout. The website needs a Nova directive implementation for defining where the micro-frontends views will be rendered inside the page. (The diagram shows a PHP website but you can choose whatever programming language and web framework you want).
4.- The website sends back the HTML generated to Nova proxy.
5.- Nova proxy parses the HTML to gather all the information necessary to request the micro-frontend views.
6.- Nova proxy makes a batch request to the Nova cluster to get all the micro-frontend views.
7.- Nova cluster creates a batch request for each involved micro-frontend.
8.- Nova cluster makes a batch request to each micro-frontend in parallel.
9.- The micro-frontends can gather all the necessary data to render the views from an external data source like a Rest API or GraphQL.
10.- The micro-frontends server-side render the views using the gathered data or using the one provided by the Nova Cluster.
11.- The micro-frontends send back the rendered views to Nova cluster.
12.- Nova cluster aggregates the micro-frontends responses and sends them back to Nova proxy.
13.- Nova proxy replaces the placeholders with the HTML of the successful results and keeps the placeholders for the error results to enable the client-side scripts renderer the views in the browser as a fallback.
14.- Nova proxy sends back the modified response to the user.
16.- The user can interact with the views in order to display more information gathered from the same data source for server-side rendering.
What are we going to build?
We’re going to create three micro-frontends scoped by their own domain using Vue.js.
- Common (micro-1): Navigation bar.
- Github (micro-2): A grid view for listing repositories based in a search term.
- Page Builder (page-builder): customize the website pages.
Also, we’re going to create a website using AdonisJS which will consume the micro-frontends to compose the page.
The website is responsible for three things:
- Renders the page using a template view + the Nova directive based on the layouts stored in Algolia.
- Displays the page builder to modify the page layouts.
- Provides an endpoint to enable the page builder to save the page layouts.
Renders page using layout
The route handler uses the Algolia client to search the page layout based on the page path and passes it to the template engine if it exists, otherwise, the route handler returns a 404 error page.
The template view uses the Nova directive in order to render the placeholders for the micro-frontends based in the components declared in the page layout.
Micro-fronted #1 (Common)
The scope of this micro-frontend is distributing common views like a navigation bar on several websites. I created this simple micro-frontend to demonstrate how Nova cluster enables us to request views without know where they coming from.
Micro-frontend #2 (Github)
The scope of this micro-frontend is providing views with information from GitHub, in this case, we have a grid view listing repositories based in a term.
This micro-frontend is only client-side render and it is mounted in the
page-builder page of the website
- Uses the information provided in the Nova directive to initialize the page builder.
- Once the page builder is initialized it requests the views to Nova cluster using the page layout provided for the website when the page builder was initialized.
- Once Nova cluster responds it takes the HTML of each result to client-side render the views.
- Every time the view data inside the page layout is changed by the user it requests the view again using new data in order to preview the changes.
Using the Nova Architecture + page builder enables media publishing platforms to have different teams being owners of their own micro-frontend views which can gather content from different data sources.