DEV Community

A progressive micro frontends framework - Fronts

Michael Lin on July 03, 2021

Micro Frontends An architectural style where independently deliverable frontend applications are composed into a greater whole. As fr...
Collapse
 
kokaneka profile image
kapeel kokane • Edited

Hey Michael! Nice work. I am experimenting with a hobby project and have a few queries around that.

  • For importing, we are using a syntax like
import('app2/src/bootstrap')
Enter fullscreen mode Exit fullscreen mode

so does it mean that all the smaller parts of the micro-frontend need to reside in the same folder structure?

  • What is the deployment process like, if I want to deploy the two projects separately?
  • Also, I am pretty new to micro-frontends so can you please explain what is the core difference between this approach and another one where two teams build a React application by maintaining boundaries defined by folder structure? For instance, team 1 works on src/cart and team 2 works on src/products.
Collapse
 
unadlib profile image
Michael Lin

We need more complete example, for example, we have a shopping application, then it depends on cart and also depends on products, so we can have two teams to develop cart and products respectively. these two teams develop and deploy completely independently.

For the more complete application shell of shopping, we do something like import('cart/src/bootstrap') and import('products/src/bootstrap') to render them both in the shopping application.

We can choose the rendering containers in the shopping app for these two sub-applications, useApp(), useWebComponents() or useIframe().

And the most important, it also supports components of the same UI framework. So the three teams, which can choose to use React , and we can merge two sub-applications in the shopping using import Cart from 'cart/src/App'; and import Products from 'Products/src/App';.

fronts are highly recommended for reuse as components when using the same UI framework.

Collapse
 
kokaneka profile image
kapeel kokane

Hey Michael, thanks a lot for the reply!

These questions are regarding an article that I'm writing comparing singleSPA, webpack module federation and fronts.

I also checked out the example that is linked on the official fronts github. Planning to convert it into an ecom example with a better UX.

I have a few follow up questions:
In the above example that you provided, does the shopping app, cart and products code need to be in the same code base? If yes, then what is the advantage over a conventional codebase that depends on folder structure boundaries? Is the ability to build them separately the only major advantage?
Also, these component apps be deployed separately and what would that deployment process look like?

And lastly, does fronts optimize the shared common dependencies among these code bases? If yes, where do we define the shared libraries?

We can even connect for some time if you're free.

Thread Thread
 
unadlib profile image
Michael Lin

In the above example, shopping app, cart and products does not need to be in a codebase at all (If necessary in fact monorepo is a good practice to manage large frontend project).

Its biggest advantage is that it is completely independent, lazy loading, and it is fully dynamic. Compared to traditional codebases, it doesn't need to be rebuilt in its entirety every time. For example, we add a new feature to cart. We simply rebuild cart and deploy it so that the shopping application loads the latest cart code. For large and complex front-end projects, this is a huge advantage. It means it's a very efficient delivery. Imagine how flexible it will become when many teams are working together to deliver large projects, with each team just being responsible for its own part independently. (It has very many other benefits, and if you want to learn more about it, you can read this article. martinfowler.com/articles/micro-fr...)

The deployment process of fronts is like this. For example, cart has been made by A and B feature, when the new feature C has been completed, then we can directly build and upload the same directory location files to overwrite the old file on host, then once the user refresh the page or open the new shopping page, the user will get A, B and C these three features. (Also fronts supports version control, which will mean that the administrator can control the loaded version of the application, and any Canary release, A/B testing, etc. delivery becomes very convenient.)

Regarding dependency sharing, fronts follow exactly the settings of the module federation, for example.

We set up the cart/site.json file.

{
  "name": "cart",
  "exports": ["./src/App"],
  "dependencies": {},
  "shared": {
    "react": { "singleton": true },
    "react-dom": { "singleton": true }
  }
}
Enter fullscreen mode Exit fullscreen mode

We also set the products/site.json file.

{
  "name": "products",
  "exports": ["./src/App"],
  "dependencies": {},
  "shared": {
    "react": { "singleton": true },
    "react-dom": { "singleton": true }
  }
}
Enter fullscreen mode Exit fullscreen mode

This would mean that they share react and react-dom.

Finally, thank you for the invitation. I'm not a native English speaker. If you don't mind my broken English speaking. We can schedule a meeting via Zoom. I live in China and there should be some time to discuss this topic from 7:00-9:00 PM Beijing time.

Thread Thread
 
kokaneka profile image
kapeel kokane

Hey Michael. Thanks a lot for taking out so much time and replying in such detail. That previous comment cleared out a lot of doubts.

I just have 1 last question:
How would the following code present in app1 look like in case of a non-monolith app:

import React from 'react';
import { useApp } from 'fronts-react';

export const App = () => {
  const App2 = useApp({
    name: 'app2',
    loader: () => import('app2/src/bootstrap'),
  });
  return <App2 />;
};
Enter fullscreen mode Exit fullscreen mode

Let's say that app1 and app2 are separate Github repositories with example URLs like these:
github.com/kokanek/app1
github.com/kokanek/app2

In that case, how can I use a button exposed from app2 inside of app1 with the help of Fronts.js?

Thread Thread
 
unadlib profile image
Michael Lin

You need to set these config in app1/site.json

{
  "name": "app1",
  "dependencies": {
    "app2": "http://localhost:3002/remoteEntry.js".
  },
  "shared": {
    "react": { "singleton": true },
    "react-dom": { "singleton": true }
  }
}
Enter fullscreen mode Exit fullscreen mode

And set these config in app2/site.json.

{
  "name": "app2",
  "exports": ["./src/bootstrap"],
  "shared": {
    "react": { "singleton": true },
    "react-dom": { "singleton": true }
  }
}
Enter fullscreen mode Exit fullscreen mode

Then you need to start both app1 and app2.

This way you can use app2 on app1 and app2 is also running independently.

Thread Thread
 
kokaneka profile image
kapeel kokane • Edited

Awesome! That clears almost all the doubts that I had about this. I forked the fronts-example repo and created a more visually appealing example of the same by creating a dummy ecom site powered by fronts.

Here's the repo if you'd like to check it out. Would love to know your feedback. :)

Collapse
 
mvoloskov profile image
Miloslav 🏳️‍🌈 🦋 Voloskov

Nice work!

I never understood why the entry point is always JS no matter where I look. Conceptually, the webpage lifecycle always starts with your browser receiving HTML. Also, HTML modules could include CSS and JS, and we should be able to parse it into an AST just like we parse JS. Then we tree-shake it and it'll be done!

Too bad I only managed to found some pre-alpha or straight up abandoned solutions which achieve this.

Collapse
 
unadlib profile image
Michael Lin

Right.

But we should look at things differently. Most modern front-end projects are packaged into a JS bundle or or several JS chunks, while HTML and CSS are injected by JS.

If we really need HTML as an entry point, then that means that we have to fetch the HTML file asynchronously and parse the HTML file so that the CSS/JS/HTML are parsed out, we have to parse it completely, and for the parsed elements to be strictly enforced by the Web's rendering standards, which is not easy, it has a high cost, and otherwise there can easily be some problems otherwise there could easily be some problems.

So what we need to think about is do we really need HTML files as entry points in most cases?

Collapse
 
kleveland profile image
Kacey Cleveland

How does communication work between micro-frontends using fronts? If I have a parent frontend that has state management and I want all of my child frontends to pull in some of the parent's state, is there a way to handle this with fronts? First thing that comes to mind is user authentication and storing a user's state in the parent state with the child frontends pulling the user's session in from the parent state.

Collapse
 
unadlib profile image
Michael Lin

Yes, you can use fronts-transport. For example, globalTransport.listen('increase', (count) => count + 1) and const result = await globalTransport.emit('increase', 1), and the result should be 2.

fronts-transport can be used in any iframe or non-iframe micro frontend, they can communicate as long as they have a dependency, either indirect or direct.

So sorry, the documentation for fronts is still in progress.

Collapse
 
kleveland profile image
Kacey Cleveland

No worries; it is a very cool project and I am looking forward to seeing your progress going forward!