TW Presents: The one right way to do microfrontends - two opinions

TW Presents: The one right way to do microfrontends - two opinions

Show Video

- My name is Matthias Kainer. I'm in software industry for almost 20 years now. I started in the year 2001, back then at Microsoft, where I earned my first few Euros. Back then, was there euros already? Can't remember, it's long, long ago. And during the course of my career, I've worked at multiple companies like AutoScout, like 1&1. I had two startups where I was a co-founder.

And I landed at ThoughtWorks a few years ago and I'm working here as a Lead Developer and Tech Principal on accounts. And with that I want to hand over to Mario. - Hello, I'm Mario, I'm also a consultant at ThoughtWorks. Been here, yeah, I don't know, almost three years already. And a bit less of a shorter career than Matthias but still I've been doing software for over 10 years already. And I'm also a Lead Developer here.

And yeah, we worked well with our clients, building software and trying to get better at this software thing over time, kind of our thing. Enough about us. Let's talk about Microfrontends. In this talk our aim is to ask and answer these three questions. What is a Microfrontend? Why would you use it? And how can you get started? We want to tell you how our experience has been, things we have seen in projects, things we have tried and how that has led us to form a lot of opinions about Microfrontends, just like we have opinions about everything else. The goal for today is that you can walk away with an understanding of pros and cons and maybe, like a direction if you want to get started so that you didn't really have to discover everything from scratch.

If we are talking about Microfrontends, I guess the first thing is, before other microservices, Nowadays everybody is on the microservices train. And maybe even without needing it that much. I mean, and I think it's pretty much, seems to me that it falls when you start an application, it's like, how many microservices are we going to build? And that makes sense, microfrontends are there for a reason.

Like, when you are in a set of when they really work you really understand why everybody so, I would say excited, but maybe it's past the excited part and it's more like a routine. Still, what about the frontend, all right? What, I mean, microfrontends, you read the internet or finance or you're separating this APIs and so on and you arrive at something like this. You went through all the trouble of adopting microservices looking for domain boundaries, applying domain-driven design, doing the whole thing and then maybe this happens. We have seen this and in some accounts and projects, you end up not touching the frontend for various reasons.

And you end up having something like this where the frontend is a monolith. And yeah, monoliths are hard to deploy. And you may be stuck as a duration like this where you are saying, we got this continuous everybody thing and we are deploying these microservices daily. And then we are doing a quarterly release of our frontend. Seems like a bit exaggerated, but it's really not that far away from the truth.

One of the first breaks I was on at the ThoughtWorks, I would name their releases with the Q1, Q2, Q3, and Q4. And you probably can imagine how often they actually would release that software based on the naming. This is something that happens. And I guess the answer to that are microfrontends.

Microfrontends are actually a couple of years old if you look for a first mentions. It's just less appear in our Tech Radar in November, 2019. And the snippet basically says what I've been saying. You are going, like through all the trouble of making microservices. And then, in the end, the frontend remains a monolith which kind of prevents you from getting the benefits from actually splitting things up and dividing it nicely among self-contained teams. That's the point, right? Microfrontend has an architectural pattern, can be used to close that gap to make sure that at the end the user doesn't really care how you divide your software or whether you, where you set the boundaries for fronts and back-end services care about the experience, right.

The very first question we want to ask ourselves is, what are microfrontends? Before we even talk about details and specifics. This is a nice definition. An architectural style where independent delivery frontend applications are composed into a greater whole. And I want to show what I mean from two different perspectives. First, perspective of the developer.

Why, because developers are selfish and they're thinking about their own situation most of the time even though we claim to do the other way around, we do that all the time. How does it look like as for me as a developer? It sort of looks like this. A half instead of a one kind of line or delivery pipeline or artifact. I'm going in different lines and I'm building them differently. So they all have the different pipeline and they all end up generating an artifact which would be a bundle with HTML, CSS and JavaScript, probably.

Of course you have to combine this at the end impression in some form. Because in the end the user is not going to open multiple, 10 different tabs so that they get your app so that the every single component can be visible. That's what's going to happen. But we are going to get that in a few minutes. And from the perspective of the end user, how does that look like? Actually, it shouldn't look like anything different. So a user doesn't necessarily have to notice that that site is built using microfrontends.

Here I have, well, you have this side and maybe, that top bar is one (mumbles) entity that you can separate into its own application. Maybe you have a search, maybe you have all the microfrontends. All in all, it will do things well.

You shouldn't really appreciate the difference that much. Many things that we are mentioning appear in an article by a colleague of us, that was pretty comprehensive and then came in modern politics website. I kind of encourage you to have a look if you want to read a bit more.

And we are heavily inspired by that and we have a similar experience. The what, I hope is more or less clear now. Let's move to the next question.

Why are we going to use this? Why, why, yeah. Why bother? This is an extra effort. Maybe this is departing from what we're used to. What are we getting out of this? Let's list some of the benefits that we expect to get.

Incremental updates. I mean, am I not to have no big bang releases? And I think that's a very good way of putting it. Let's see now you're one of these big corporate websites, that nobody ever wants to touch, that were started 20 years ago when DSPs were still a thing. And imagine you want to introduce their changes. It is probably very hard to change the whole thing.

It's probably out of the question to rewrite it from scratch. But what you might want to do is, why have we inject like just a widget on the bottom part of the page or just rework some small part where you can incrementally add value to that side and change things without having to touch the whole thing and commit to a full rewrite. Which in practice rarely happens because it rarely succeeds, as well. Independent deployments are pretty much the same as microservices. The idea is that if you are working in your team you probably would like to deploy your staff without having to rely on what other teams are doing. I know that's an idea that's not uncommon for a big site.

There might be, I don't know, in one of my last accounts, 10, 15 teams. And imagine if you really depend on what everybody is doing. Just the amount of staff that is appearing there. The amount of complexity.

The amount of possible merge conflicts in fact, all that can really (indistinct) This is the same as microservices. And Autonomous teams so with the idea of slicing things vertically instead of horizontally. That's kind of, a bit buzzwordy. And what I mean by it's just like having teams on either smaller products or at least features not like function.

Not saying, all right, we have the front-end team, then we have the back-end team, then have the operations team, then we have the database team. There's kind of a horizontal separation tends to lead to, well, yeah, I have my thing and I throw it over the wall to the next team. And we don't really, I mean, the user doesn't care how you organize internally. The user cares the experience that you deliver on. We have seen that that tends to work a lot better when you work this way.

A related question to the why is, should you actually use microfrontends? I think this is a very valid question to ask. And it's one that we probably should be doing more often. Just because the technology is out there, just because we put something integrate out doesn't mean that it fits every scenario. Doesn't mean that in your particular situation, it's the thing to do.

I think that's important, right. Keeping the context of what you can do or you should be doing. It's really important because otherwise you might be end up doing something that is technology for the sake of technology. And that is nice to play to get paid, to play with tech. I don't own the right but this is really something that is going to be that useful.

We have to have a critical eye and ask ourselves, why should we use microfrontends? In fact, if you are in (indistinct) community, you might have and you happen to visit Twitter, we're not there. If you are into that kind of unhealthy stuff. You have might have seen that not everybody's a fan of this.

In fact, coming back to the article that I mentioned a couple of slides ago, when that was published there were some nice flame wars going on on Twitter. And somebody pretty prominent in the community, like Dan Abramov, was not really one of the fans of the whole approach. And I think, again, well I kind of again empathize with that. I think when you are talking about microfrontends, we need to talk about the fact that there are trade-offs here.

We are talking about the autonomy, teams want to do their thing but that autonomy doesn't come for free, you are trading there. Maybe you are going to increase the complexity of your app or the speed, the speed at which your end user is receiving the page, is going to suffer. And I think you have to be cautious of the trends we are making.

So that has to be a conscious decision. There are some factors that you can consider whenever you say which microfront and speed or I think to use in my context, in my project. As I mention horizontal and vertical teams, I mean, if you have this horizontal setup where you say you are frontend and developer back-end and this and that, I have a hard time picturing microfronts as working in that setup. I think you will recreate the, I mean, you end up regressing your organization and that doesn't really help the end in the end.

What is your priority? For us fast time to market, if it's that, microfrontends. Maybe not in the sense of you can reward, if you need to reward your whole application, I don't think microfrontends are going to make you any faster. But if you need just to deliver a part, certain part, and you don't want to be dragged down by the necessities of a legacy, monolith that takes a quarter to be released, then that is a good argument.

On the other side, if you have high UX conditions and requirements, like you want really everything to look in a cohesive way, maybe that is not something that microfrontends is going to allow to do very easily. It's still possible, but it might not be easy. And last thing is, if you are already releasing every hour, why, I'm not sure how much faster you can get.

I think you're probably already fast enough. Is I don't know in our point, if you are already Facebook, if you really move really fast, which comes back to the Dan Abramov quote, if you're already really fast maybe you use a (indistinct) to talk about organizational patterns. Because in the end, just like microfrontends is much more than technology, is more how you structure your organization around the technology.

It might be that this is not something you need. And it's good to decide that before you invest a year reworking things and not seeing any benefits. I mentioned that microfrontends need to be composed at some point, right? I was asking questions like what, why? And now we are moving in slightly towards the how. We need to compose things if we want to deliver microfrontends. And that's going to be a big part of the remaining talk. We have made an arbitrary division between server side and client side, mostly because we are two people and we both need things to talk about.

But anyways, I already tried it but it kind of, say it works. We have composition from the side of the server, from side of back-end and composition and the client side. I'm going to talk about the server side approaches mostly and Matthias will take over then and talking about client side. Plus we're also going to mention other relevant concerns, other than all like back-end call and some other things that often come up when you are trying to work this way. Let's start with the first approach, build time integration.

Basically, what I mean by this is, that you are actually going to divide, you can divide your application into separate npm packages and aggregate them again, and deploy them as one entity. I even drew a fancy chart for that. In the end is here, you kind of take your big bundle and you separate it in a bunch of smaller bundles which then are developed independently and combined again. Nothing really very sophisticated. Say it could look like this, it could be a main package or a metal package that aggregates everything else. Now, this way, I have different versions for every package, because we said we want to allow people to evolve at their own speed.

If we do all this and then force everybody to move, one release it stays and everybody gets that release. Then we just build micro monoliths inside the kind of modeling. And how it kind of looked like, it's really not very different from a normal react application. Let's say we are integrating through components. Something as simple as you have your routes there and you're putting each route in each component and then the component comes from the package that is assigned to that team, that is building that particular microfrontend, not really very different.

How do you manage those packages? You can do a lot of things. One approach is Lerna. This is one actually in the team I was on.

We started with one app because we were a smaller team. And at some point we were scaling up the team, we were kind of introducing more people there, and we figured out it made sense to try to allow people to work a bit more liberally. And so we put microfrontends there and we used Lerna for that. In fact, I was working on that team and then when I left, Matthias replaced me. I saw the part where we were building things but I didn't see the day-to-day.

You can ask him if it actually works or if I was just there to get the fancy (mumbles) out of it. Anyhow, I remember the first time I gave this talk somebody was not, I was nearing when I mentioned Lerna. So keep in mind this is just one way. You can still do it the way you see it fit. With Lerna, again, you can have your own packages and the configuration and a bunch of packages. I think in practice, the Lerna approach works well for teams that are collaborating very closely together.

If you have the portfolio I mentioned in the beginning, 15 teams, and they are actually not that close. I mean, they don't really engage that much with each other. This might be a difficult thing. So this is something to consider.

How that's Lerna look like, that's part of (indistinct) independents. You want to release the packages on their own. Let's talk about pros and cons. We promise to tell you what works and what doesn't in the projects that we mentioned. It doesn't really get much simpler than this.

Maybe it does but I don't know if we can do it with less effort and you don't really have any runtime impact because you are composing all these bundle as part of the process whatever process you have to release your frontend before it even hits any production or any environment. The downside is that this, technically speaking, is not really microfrontends because we are, there is a certain degree of separation but just before you are wanting to release it or just before you want to compose this final bundle, you're actually aggregating everybody together and introducing this kind of bottleneck. So depends on if that is fast. Our experience was that if that pipeline is fast and seamless, it's not too bad, but it can really be a sacrifice to the autonomy.

I guess I would say this kind of approach is a starting point. If you have more requirements, you will probably grow out of it at some point. Let's move on to the next one.

Now we are going to talk a bit about server side includes. If you are a Varnish user, you might know them as edge side includes. It's a similar thing. What does an, as I say, SSI, first of all this is not new at all, this predates microphone this by quite a bit. It's not like we are rediscovering here anything and we're not doing any major breakthrough.

Anyhow, server side includes is a certified server side scripting language that allows you to inject files or content into a page using a directive. How does that look like? It looks like this, this is a personal example. I have my index HTML there and then I will have there this comment with include and somehow that would be an injection point, as you say, where content would flow in. Let's say you're using in Unix for that.

I mean, in Unix, in a (indistinct). So I think it's a good example. You will choose here, you have the OSI module on and then we are deciding what to put based on the location. We would have a bunch of different assets accessible by our web server. And we are injecting each of those. When I say set page browse, for example, I could also have something like, the URL of my CDN, maybe HTM is a blank to which CDN, and this is sort of the last point where we integrate that.

That's fairly easy and painless. And naturally, our question is, but where is the microfrontend? I mean, this is actually happening on in Unix. I don't see a lot of microfrontends happening around here. I drew another chart that feels like it's not really useful but I forgot about this since last time.

So I didn't replace it, but still I'll try to explain it again. All in all your page, your whole page has a bunch of boxes and each box is an opportunity for you to put a microfrontend in. The microfrontend that comes kind of self-contained with its own markup, its own styling and its own behavior specified by down street. And so let's expand the example let's say, yeah, we're Micro... Our page is a collection of different elements.

It has a header, has a page, a sidebar, has a folder. Each of those is an opportunity for a separate dedicated team to put their, develop their microfrontend, then definitely and inject it there. And then it looks something like this where the page ultimately gets aggregated and they use their CSR creative experience but still like every app has been developed differently which give us what we actually want. This independence, this ability for teams to work on their own without really having to align with absolutely everybody else that surrounds them. This approach, let's move to the pros and cons again.

It's simple still. All we're introducing just a piece of extra infrastructure in the picture. You need, somebody needs to take care of this nginx or this entry point, but still it says manageable. And we have a big drawback here.

We are, just like I said, we are injecting a microfrontend each time we do one of this. Let's imagine we put 10 of these smaller apps in our index. Well, we are bringing 10 apps. And if we do it like the naive way, we might be forcing the user to download 10 times 10 SBAs with its own react version, its own router, its own... Well, the thousands of packages that you need to in order to change the color of a text and nowadays in modern word programming.

From the developer's perspective it's perfect because you don't see any of this from the user perspective. It might not be ideal. Now that we are all at home, we have fast internet all the time, but maybe once we, if we ever get back again to the streets we will have to use the data plans that are not that fast. And maybe you don't want to download 15 megabytes of repeated actually react versions just to see your next meme. There is, in fact there was a project in Munich for the, I didn't work there but some of our colleagues came in and started developing on page base on microfrontends. And it was actually for a user-facing 3D known (indistinct).

There was actual traffic there and they started there with deciding routes and they ran against their limits and they actually work on that and build a custom framework for it. And in fact it was complex enough to be its own top. If you wanted to get into those details, I recommend having a look at that one.

I think it's interesting to see for your start simple and then you kind of evolve as your needs also evolve. These two were two backend approaches. And now I want to, as I said, make a bit of a detour and talk about some other things.

One is backend interaction. Composition, it's not just like how you actually make the different parts of your website work, when you are aggregating this. If you are devising the frontend in smaller apps, they also need to communicate. In fact, the fact that you are kind of separating things means that there were there will be more rest calls to your backends to fetch the information that you need to display stat. It might be that the end result is actually more, more heavy in the depends. I mean, maybe you are using a range 2B2 and everything is multiplex and you don't see it in practice, but maybe not.

Anyhow, what is interaction in the back? I have here my what to avoid plan. And for me, this is a bit contentious. I think when I showed this to Matthias for the first time, he said, "Yeah, I'm not sure about the saying that you have to avoid it. I think that's a bit of a strong statement."

I guess that there is always context. But I want to say here is if you are really spending a ton of effort in dividing your app into a smaller apps backend and a frontend, you are doing that. And then you put an API gateway in the middle to centralize everything again, it depends on how you do it, but it might be that you lose the benefits that you gained before, right? If this API gateway sort of a blocker or a centralized gatekeeper that makes teams less flexible in the way that delivers software, that's bad. If you have something like an API gateway that is super flexible and more people can kind of take ownership of their own areas, I don't know, something driven by code, I've used Apogee in the past with some amount of success. It can work, but still, I want to talk about backend for frontend.

This is nothing fancy. I think we are experts at taking concepts that are fairly simple and getting fancy acronym or a fancy way of calling them. But it's really nothing that you haven't done before. A backend for frontend in the end is a custom backend for a particular client built very importantly together with the frontend by the same team. I guess when you're building backends there are two different approaches.

One is say, all right, I'm going to build a generic API that can serve models using rest and serve for the whole domain. And everybody's going to be using that or are going to say it's hard to predict what Erica is going to need. Maybe they have slightly different requirements.

So maybe we can try to build them a bespoke backend for the frontend and address those needs and not try to predict what the future is going to hold and how we will need it. I think that that's pretty much the same. Kind of also combining it together with a frontend, which I think is important.

This backend for frontend idea, it only works if you have a team that's basically owning this thing end to end. If you end up saying, we have a team doing this backend for us and then we'd have to wait one week for them to prioritize the storage that we need in order to do this feature. All that adds friction.

And in the end, maybe it will take as long as you took before when everything was a big plump. This is how it can look like, like frontends communicating with their own again from frontend. That doesn't mean that you are duplicating all the data or that you don't really have more interactions. Maybe after that there are downstream services, with which you have to communicate, maybe you own the data you have, maybe you're more of an aggregator. Maybe you are just collecting data that is being put there by different teams that expose our APIs. That's a really minor, that's a you have to figure it out yourself.

And a big learning from this is microfrontends talk to their own BFF. We had a client, Kimberline, ran for a few years where they were really heavy on the microfrontend staff. And it was just, I think it was mostly like a bunch of (mumbles) teams co-located across Germany and India.

And they did a lot of microfrontends. And one of the developers who was working there told me that they really struggled with, because in the beginning they didn't enforce that people should try to communicate only with their own backend or frontend, in this case. Instead this network communications made things hard to change because there weren't a lot of relationships there. So you couldn't really be completely sure that you weren't affecting anybody. Avoiding coupling, that's pretty generic advice but still, I think it's worth mentioning that.

We are introducing a certain amount of complexity here and we don't want to lose the benefits by doing that. It's probably unavoidable to have a lot of communication, at the end you want to display useful stuff. You want to interact.

You want to enable your customer to do things. You need to interact with certain systems but maybe you can minimize it as much as you can. Maybe you can see this kind of a diagram with a lot of arrows going in every direction is a sign that the domain boundaries are not properly divided. Maybe you are missing on a brainstorming session. Matthias can organize this for you here.

He loves that shit. Let me finish with some quick ideas about CI/CD. Additionally, there is a topic that doesn't really fit in three or four slides as you can really do a talk or a book out of it. I guess the main idea is if you aren't dividing things if you are extracting from them in smaller chunks that are working separately together that leads to smaller deployments which smaller deployments are always easier to do than bigger ones.

There is less to take care of. There is less possible sources for errors, less possible things that can go wrong. And this is one, just to put an example. It's a pipeline that I did in a project for which actually wasn't truly a microfrontend then but still illustrates the point.

A very tight pipeline that really does just things that are really needed. Reversing, sling tests, deployed to an environment, runs on tests and deploy to the production environment can easily be completely automated. You can actually say, yeah, if the tests are green I'm going straight to production because my thing is small enough that we can figure out what is wrong and what's not. As I mentioned, pipelines deliver new deliveries, have bigger topics. I took this out of another talk I did in case you want to read a bit more on this and expand and give you this link as well.

And this is the blank slide that signals that I need to stop sharing and give control to Matthias. - Thank you, Mario. Let's see if we can show you the same white slide that you just saw before. I guess you can see it by now. Mario was talking about quite a few different ways to do a kind of microfrontend composition.

And the thing that he was focusing on was pretty much in a backend, and yes, you can say, well, on one hand you're saying an API gateway is not the right solution but you want to put all of that behind a shared nginx. Shouldn't that be an anti-pattern as well. But I think that would be easy. There are good reasons for everything that are in place.

But I still want to take a look at this shared instance of the shared URL can't be avoided. And for that, I actually want you take a slightly different direction and start with a little theory. Now, my theory is that not everything on a website can be put behind a shared nginx or shared load balance, our shared whatever. Basically you don't have any everything on a website running on the same URL, and I'm going to prove this little theory using the following assumption.

There exists a setup where multiple teams create content for the same website. Pretty sure most of you have seen that. The second point is at least two of those teams, at least two teams in the world don't share the same tool infrastructure. If you've ever switched between two companies, you might've seen that actually it is true. There are different tools into different infrastructure.

You might not use the same tech stack actually but very different ones. And if one and two are true, then there should be a number X of websites that are built by teams that are not sharing the same tools or infrastructure. And this number of X should be greater than zero. There should be some scenario where they, where people are working on one website that uses different technologies.

And I can actually prove that with a very simple example. And that example is actually ads. If you don't have an ad blocker, you might have seen those things they turn up in your browser while you're browsing. And they're a very simple example of microfrontend and microfrontend composition that are happening inside the browser. They're really old. Ads have been with us for a really long time.

That's kind of the message that I want to send. We have this name of microfrontends now but we're doing this very thing for a very long point in time. Now, how would I know that ads are actually microfrontends. If we look at one ad on one German website, we can see it's actually pretty old, 668 cases of Corona. That was almost a few weeks ago.

And we have a big ad in the middle about the gluten noodle Aus Tirol. But if we were to open this very same website, and the time machine, in a way back machine that you can use to take a look at a website a few days ago, you would actually notice that this ad is no longer there. Now, why is that happening? The thing is that this frontend composition is really happening at the client. When this page is opened, the one thing is that the URL doesn't match. The microfrontend, in that case the ad engine, decides that it doesn't really want to present you that content. It just, removed it from you and the rest of the page just collapses nicely.

It's as if the ad has never been there. It's basically the same as (indistinct). And if you think about the past, you will notice that microfrontends are actually far older than even that ad inclusion, which is actually highly sophisticated because it requires some JavaScript magic and it possibly will be using something that you might know as frames or (i)Frames. Now, frames are basically a way to include site content into other sites. You would have a website with my domain, but I would just show two different websites and my own navigation on it.

And the browser would just put that together. That was actually something that was there with HTML in the beginning. And eventually it got dropped because there was some issues with that, but (i)Frames are still with us.

And if we look at one possible implementation on how this could look, this would be a website that has, for instance, an (i)Frame in the header that access the shopping cart. You always have something visible that shows you how many items you have in your shopping cart. If something's happening over there and you have a microfrontend container that gets different URLs injected into the (i)Frame based on the route of the page. While you would click around, your window location would pick up a different path and based on the path, it would just select different URLs and put them into the microfrontend container.

That's actually a pretty easy solution to have something that's really separated and it actually comes with a lot of freedom and how you can develop because it's very much separated from each other. You have a very high degree of segregation on your page, and it's really very simple. You're basically just using browser tools. There's no framework that you actually have to use. You just use plain HTML and a little bit of JavaScript. It's very isolated.

For instance, there would be no style leaking from the one (i)Frame to the other because they are all contained. But one thing that can be really hard to use actually to come up with (i)Frames and doing them responsive because you have a container inside a container. Was even harder to do with frames, but even with (i)Frames, it's not completely solved. Routing can be tricky. We saw a very naive implementation of how we could do routing.

But of course, rout on the internet can be far more complicated. For instance, it can include hashes which might be difficult to get at at specific points in time. And SEO can become interesting because you're actually composing different pass URLs.

And while most search engines can deal with it, if you forget things, you might actually screw that up and (mumbles). And it's really very isolated. It's hard to communicate between those (i)Frames. Yes, you can do a service side communication or you can also try to use the window.postMessage API

that the slide is giving you. Wait, what's a window.postMessage? This is actually not that well-known but this is something that your browser will actually offer you. What you can do is basically just as you would for every other event, create an event listener that waits on a message event. And you can take this event and it will already come with a few fields that help you make sure that you trust whoever sends this message to you.

For instance, you can verify that the source is your current window. If you want you to limit yourself to only receive messages from a specific source, then you can specify that here. And you can also add an origin that you would expect. And it's really easy to post those messages, by a window.postMessage.

Now in an (i)Frame setup, what you would probably do is that the (i)Frames what call window.parent.postMessage, and post the messages in there while they would listen to window.parent.addEventListener. And then kind of see if there are any messages that are basically sent while the message bus of the wise application. If you want, it's a very simple implementation of Kafka in your browser, but of course it's not that sophisticated, but it's immune to network lags.

It's really happening in real-time because it's all happening in the same browser. It can be made pretty secure. Side, not all of those things can be easily fiked and extensions will not be able to, for instance post a message in the context of one of the frames or origins. And it's very lightweight and it can help you start thinking in events. As Mario pointed out, initially, I'm kind of looking on most of the domains that I'm working in and trying to understand what are the domains that are actually floating in between them.

If you have multiple items on your page and you think about how can they communicate, I still feel that it might be good to actually communicate in events rather than come up with very complex interfaces and basically have to come up with something on how you shared a contract between them. But of course, this is very simple. I didn't need some extra special love from you to support more relevant things like queuing or delivery guarantees. The microfrontend will only receive messages if it's actually available.

And there is no native way of basically replaying what's there. You would have to create a little queue on top of that, that can actually help you with that. The next thing is that if you can't trust yourself, and I usually can't trust myself, because I'm really good at forgetting most of the things that I want to come up with and then to the tests that I showed you like the source and the origin window.

Then probably just don't do that because you undermine the security concept that comes with it. And if you forget those, it basically means that everybody can start cross-site scripting your frame by simply including you on the page. And that's probably something that you really don't want. The other thing is that if you can't trust your user, then you shouldn't rely only on it. Because even though there is some security to it, you can just open the developer tools and then try to trigger the wide methods, intercept those messages and create your own. For instance, if this is the only way, and let's say order process, and the user has the option to modify the price simply by sending a message, they probably will.

If that's the only thing where you would get the price from then you should probably think twice about putting that into production. The next thing that I want to talk about, and now I'm getting back to micro-finance, is actually module loading. There are different approaches to it and Mario has showed you a few of those already. The easiest one was basically the Lerna approach that we have seen in the very beginning. It does mean, and this was also pointed out in the chat, that you are restricted to a monorepo. All the source code is basically shared in one repository, which also means that if you have a trunk-based development and the CI/CD that you will deploy quite regularly and quite often, that's not necessarily bad but it can lead to a long queues and fun of the developers that have committed something just break the build.

A lot of teams would have to wait for them. Another (mumbles) how you can set it up is actually create and cam modules and deploy them to an artifactory or to rather somewhere where people can actually download as NPM modules. It does allow you to separate your code. You can start having your own separate gateway repositories, for instance.

And you can also have your separate deployments. You can specify where you can pump the versions, upload them to the Artifactory and let everybody know that you have a new version. And that actually means that you have no longer control of your go-live, because simply because you released a new version does not necessarily mean that everybody's going to upgrade automatically. There is another way and that's basically dynamic module loading which is the hardest of this way. It's really difficult to set up. We will take into that in a second, but of course it allows you to have completely separate code.

You can work on completely different companies work completely separated from each other, have a separate deploy, and you will deploy to your own bucket. For instance, in an S3 bucket. And you would basically just put it there and the others would just include you, your URL. And with that, you basically can start controlling your own go-live. Because as soon as you have released the new versions, the other would use it.

This is really important because there's one thing that I've learned over and over again. And that's the fact that pinning the version for a dependency it's always tech debt. You have to care about it. You have to make sure that you update your dependencies. You have to check if people are using old versions of your software and what impact would that have to you? You have to manage all of that. And that means you have some extra effort put on your plate, that's operational, that actually keeps you from developing new things.

It's a tech debt, that has to be managed and there are no really good reasons for it to probably be avoided. One way to actually go in a direction of this, where we strongly coupling a single-spa. That's a Brit acronym, because it actually means a single single page application, but once you got over it, it's actually not that bad. And we are going to do a little code demonstration and we'll see how well that goes because usually coding things always go wrong.

Now what we have there is basically a folder with three little things. And I imagine those are different gateway repositories. The one that I called root, is just a very simple file. A very simple folder, has three files in it. And index.HTML, it's basically a HTML page

for direct developers here that can't even remember something like that existed. It has a docker file. It's basically just an nginx. And an nginx conflict basically says, whatever you do just go to the index HTML. Let's quickly start up that docker container.

Zipped. And it's running, we can open it. And it has a few navigational entries.

Kind of says, this is a react page. Nothing shows, this is a view page, nothing shows. This is both of them, nothing shows. If I'm going to change it.

Like that. Restored and I'm refreshing it. Of course, it's still shows the old content because it's immutable, I've deployed it. This version is now in production.

I can't just simply do something to change it. But what I want to do now is to load the different other applications. I'm starting the react application that runs on a port 3000, and a view application that runs on the port 1337. Why did those things start up? What they are going to do is basically they're going to expose a little script on the URL, either on local house 3000 or on local host 1337.

Give it a second to be available. Let's take a look. If we click here, we can actually see it. That's the view page. If we click here then we can see, Oh, that's who we are page and something was monitored and it can actually show both of them on one page.

Here's the react thing, here's the vue thing. And if I go into one of the two pages and for instance here and change this maybe to something. (keyboard clacking) Corrected text And I opened the vue page. Then we can see corrected text and here's the corrected text.

It's actually loaded in real time, because what happened was that those things have watches attached to it. Whenever we have a change they would be deployed but we didn't have to deploy the root that actually just loaded a new version of the script that was deployed. If we are going to take a quick peek and here our network and just restart them, we can see that we have, let's go to GS, that we have loaded a few scripts and for instance, this is the script for the ones under the port 3000. And it's simply a Webpack script that has all the dependencies in there that you would need. And once it's there, it's basically just executed on a page and put in to the point to the place where you would want to have it. And what single-spa does, is that it basically allows you to register those applications in a page.

And you can, for instance then trigger that for specific locations, a specific application should be shown. Single-spa can actually do a little more as well. You can see ahead that it's actually not so much dealing with URLs. It does not know anything to put a port 3000 or local hosts. It's actually importing our dependency via system import.

So how does that work? Let's take our next little detour. If you have done (indistinct), JavaScript in the backend, you might be well familiar with how JavaScript or how (indistinct) inputs work but actually there's something that it allows you to do something very similar in a browser. Which is basically sketched out by the WICG working group, which is called import maps. It basically allows you to place a special script tag in your browser, specified the names of the package and where you would find them. And by that you can actually start loading them on demand.

Now that's really really something that we would want to have because it not only allows us to get specific snippets off our page, we can actually start taking dependencies and providing those dependencies globally for a specific version. If we look at it, here we have our index.HTML page. And this index.HTML page basically takes single-spa, which it needs as a base, undertakes the react dependency and puts it in there. Here we have the two applications that are running and actually the react application is no longer required to bring the react to dependency by its own. It can actually use the one that was defined globally and that's really convenient because Mario had the point that we want to reduce our pilot.

We don't want for every one of our applications to bring their own version of react that would make our pages really huge. But with this, we can actually say, look we have a global react version. You start one.

And if one of the teams is not using react 16 but rather react 14, then you can tell them, well they need to use the global one, create your alias. And use that one in your application. They can still bring your own version of react in case they are not compatible to the global used. Which means you are no longer required to actually have big bang deployments and your whole company, whenever you update your react version or you angle a version or whatever, you can start creating something that allows the other teams to reduce the pilot and be nice to the customer. Or be evil and take a little more time for moving to a new version.

And there's another thing. There is a Webpack merge request open, and I'm clicking on the link, but it's not opening. Ah there. There's basically a proposal that allows to do this very thing without the complexity of single-spa. It's actually mentioned there.

When this merge request is closed, you can do something like that for a Webpack or for multiple Webpack projects. And actually, and able you to deploy different frontend apps independently and Webpack will take those different dependencies and orchestrate them for you in a browser. It has been open for a few months now, they're still working on it, but I expect that when this merge request is closed and really put into a Webpack, then this will pretty much change the way how we do, well how we develop our websites. No, where did my presentation end up in? Ah, it just opened and the same top. That's brilliant. And there's another thing that actually, there's a lot of that already for you and that's web components.

If we talk about microfrontends, then we can describe our components as browser-supported microfrontend-fragments. Now, web components are basically, again, nothing new. What's new about it is that the HTML tags that already existed, you can create your own now and you can distribute them. An example for a web component would be this clock. It's actually a web component digital clock that contains a few digital clock characters that are basically just changing the digits while things run.

But as you can see, this is HTML. It's not a react component or whatever that you see there. It's your own component that you have inside your browser that comes with a little bit of functionality. And this functionality, you can basically create yourself by creating an element that extends from an HTML element, just like any other. You can create properties that get specific attributes that you have in your element. And at the end you can define those elements and add them to the window.

Now, if you put at this digital clock character to the pipes and the script is not loaded, we'll simply just do nothing. I will just show you to place all the texts that you might have put in there. And only when this window custom element is defined then it will be loaded.

It basically looks like that. I have it here. You're waiting for a script to load, add to code, and at that point in time actually the web component starts to exist. You're not required to have everything ready at the very point in time where the HTML pages entered. It's totally fine to add that later.

And it's really convenient because it's pretty much simple. You don't have to use an external library. the footprint is super small because you actually don't have to load anything else. It's super isolated, or you can make it super isolated.

Or you can make it super open. You can use things like a shadow term to avoid a CSS or scripts basically leaking inside your web component but you can also open it up and making it more extensible. The browser support is getting stronger and stronger. One of the biggest reasons not to do web components is actually IE and IE is really, really getting away. And there are good polyfills for components that actually allow or help you start working with that, also in older browsers. And there are also frameworks.

Then we are, of course, no longer with the library-less approach, like lit-elements that make this much more usable. If we click look at the clock ticket, (mumbles) clock digits from before and use lit-element we can see it does this a much easier approach to actually create this custom element. Can we just compare how much code we need is there and how little code we need there. And then it's actually a little less chatty than before.

Of course it's still class-based and kind of inflexible the way as it is. There are some libraries that help you to create little web components and a more functional approach. But again then you would have to include yet another library. Web components as they are, are class-based and also the way that they handle attributes is based on the instance of a class. And other than, for instance, attributes and languages like react, they not read only for the component itself.

You can close, you can change them from the outside. You can change them from the inside. And not necessarily match the change that you have on the inside retract from the component outside and that makes it really difficult on your website.

You actually get an idea about what's going on and what's happening. You have to make sure that you handle that specific part as a team on your own and come up with a way good architectural decision on how you want to handle them and then stick to it so that you are aware of what your attributes are actually doing. Because otherwise you have a non-predictable, two-way binding that you will never have never ever be able to manage.

And it has a lot of things that you can take a look at. And there are probably fills for that are almost there. That will make your life so much easier but they're not still not widely supported and cannot really be used in all the browsers. You're kind of restricted to not using them even though you know, that they're there.

And some of those things are also pretty heavy and pretty complicated. It opens up a lot of opportunities that you have but a lot of those opportunities actually come at a very high cost. For instance, if you think about a shadow dome and you want to have something like a shared UI library, you have to think about how you can share all those different CSS where are you able to CSS styles to the different elements and how you can't in a bigger company basically make sure that all of those components kind of comply to it and what would happen if they don't, what would happen if something changes, how can you basically work on that? And there's a lot of extra complexity that you will basically get into your project, if you use web components for everything. If all that you want to do is basically have a smart component that can decide if should I use a drop-down list or an input field, then this might be the right thing there. But coming back to the point, why do I want to do microfrontend in a browser in the first place? What is the reason for me to take on this complexity? Well, the idea is actually that it can deploy independently and that the teams can deploy their versions independently and have their updates on the production page when they need it. But for that to really be feasible, what I really need is that those multiple builds, had multiple deployments, in the end, worked together like a monolith.

Mario said it in the beginning, if you're getting into the direction of microfrontends, what you probably will lose is some kind of a UX on your page. There might be breaks on your side that are a little bit off that don't feel completely like they belong together. And also when you're working with it, there's so many things that might make you remember that you just are brought into a lot of complexity. And if you don't really feel the pain, then you probably should really avoid it because at the moment it's really difficult. And you shouldn't do microfrontends simply because you feel that everybody does microfrontends, but the same as for microservices, you should do it if you feel the pain and actually have the need to change something.

And with that, I'm giving back to Mario. - Yeah, all in all, it ended up being a pretty long talk. Let's finish with a recap. I mean, the end, the very beginning, I said there are three questions. Why are there microfrontends, why would you use them and how can you get started? I hope we managed to bring some clarity to that, if you didn't know the concept that well before.

I think what is a summary is while it might be, it's like microservices, but in the frontend. And while I think, it's also related to, don't do it just because, it's fancy, just because some expensive consultants like us are telling you to. Rather do it because there is a pain there because you want to accomplish something. Mostly you're not separating teams and allowing them to develop and work without having to depend on others without being blocked. And then how, for how we spend a chunk of time talking about a bunch of different approaches.

And in fact, there are two points there. One is that nothing we have mentioned is really revolutionary or super new, except maybe this new Webpack thing that will change our lives. But other than that it's based on mostly concepts that are being there that you might have been using already without calling it microfrontends.

And the second one is that there are a ton of different approaches that they mix. I mean, the lines are blurred, when you stop, front and back end, it really doesn't have such good separation. And we didn't mention other alternatives.

We didn't talk at all about Taylor, the library (mumbles). We could have talked about many things, In the end, the message, I guess, would be you have to find a way that works for you. And given that everyone has a different context it's probably going to be slightly different from everybody else. And with that, we are basically done, I think. Yeah, exactly.

We are finishing with this picture. And even though we took quite some time, we still would like to answer whatever questions you might have if you're still up for that. Thanks all for your attention.

It was really interesting to do a talk without any feedback from the audience but I guess you get used to it the more you quarantine. Thanks.

2021-02-09 14:48

Show Video

Other news