Lesson Description

The "Runtime Composition" Lesson is part of the full, Enterprise UI Development: Microfrontends, Testing, & Code Quality course featured in this preview video. Here's what you'd learn in this lesson:

Steve explores the module federation pattern with runtime composition for building enterprise applications. In this example, a host application or shell loads various remote modules lazily. Challenges of sharing common dependencies, such as React or design systems, and the trade-offs between autonomy and complexity in managing independent deployments are also discussed.

Preview

Transcript from the "Runtime Composition" Lesson

[00:00:00]
>> Steve Kinney: First one we're going to dig into, as I said in that chart we saw earlier, where we'll kind of whip up a simple version because could I, especially these days, could I have whipped up a full enterprise-size application for this workshop? I could have, and we would have spent the entire day studying it and trying to figure out just how to even get it to compile. So we've got some exemplars in here that we'll play around with, but the first one we're going to look at is that module federation pattern with runtime composition.

[00:00:29]
I said before, we'll start with the most autonomy and complexity, and then we'll start pulling back the complexity and figure out how to figure out for each and every one of y'all and the teams that you work on and the legacy code that you have to deal with and the various factors of what trade-offs between autonomy and simplicity you like or will work for you. But the idea, as we've kind of alluded to before, is we've got a host application, right, which again, some of these things are organizational issues, which is who owns the host application.

[00:01:15]
Maybe you have a team, maybe you have a senior VP of engineering who wants to keep lecturing you about inner source. That's where nobody owns something and everyone on the individual teams in the company, in the good of their heart, maintain the commons. It's a very cute idea that people outside of—everyone in the room is shaking their head. Everyone has experienced this where somebody who hasn't touched an editor in a decade tells you, what if—and they're not familiar with the term tragedy of the commons—what if everyone just maintained everything outside of their normal expectations and everything worked out great.

[00:01:57]
So either you have a team who owns a host application, which is a healthy thing, or you have a new problem. But the idea is that there is a host application that doesn't really ideally do much other than load the other pieces. Now, you and I both know that's not true. Sometimes there is the shell that does a lot of things, and then it also has these little children that kind of hang off as well, and there's different flavors of this too.

[00:02:27]
But you know, this is the—I would argue, and you know, I don't have any real statistics, but this is a feels-based statistical argument, which is I would say the most dominant or popular version of runtime composition, which is the shell loads and then it lazily loads all of the pieces that it needs from the various different models the teams have deployed. And so, you know, each remote says, here's where to find me, and then something either ties it all up together.

[00:02:56]
You could theoretically do this at build time too, but in this case, we'll start out with it at runtime. And the fun part is, what do you do about the stuff that needs to get shared, right? Namely, you know, React, Angular, so the framework, arguably, but like the design system, the CSS stuff along those lines. But you know, like CSS is a tricky one too, because if you bump the CSS and somebody's not ready with those classes, so on and so forth.

[00:03:30]
But the usually it's the big libraries, like your framework du jour, so on and so forth. You know, just to be clear, for the purposes of this, my goal is to keep this framework-agnostic as possible. When, but like that, you know, having some kind of framework just makes stuff a little bit simpler, so I'm assuming—I mean, React is kind of lingua franca, but in a lot of cases, I'm like, oh, and then also I've got to write up for what that looks like in Svelte or Vue or Angular or what have you as well.

[00:04:02]
And my goal is to not lean too hard. The React server components will be the closest, but I also then still tried to keep that—because I, you know, I both write a lot of React and a lot of Svelte. I don't write a lot of Vue or Angular, but Svelte and Vue are kind of the same. Somebody from the Vue team is going to be like, no, but you know what I mean? I'm trying to keep it as agnostic as possible, but at a certain point, assuming that everyone, whether they like it or not, knows a little bit of React.

[00:04:33]
But whatever that library is, okay, we want to bump from React 18 to 19, Svelte 4 to 5, what have you, and okay, but now in a distributed thing, does everyone have to be ready? Because the other answer is that everyone ships their own version of React, which is just like saying I hate our users, right? Because you don't want to have a situation where it's like, you know, Austin's app is shipping React 19.2 and Rodrigo's app is shipping React 18.3, and those are totally separate bundles or they're the same code just hosted in two different places, right?

[00:05:08]
So now we're making them download and compile that code over and over and over again, right? So you get some problems that you wouldn't have otherwise, but we'll have this idea of the host or the shell, the big thing that's over all the other pieces, the remotes which are all going to be the tiny federation of modules in this case, and then the shared stuff, which again is stuff like React or the design system or stuff along those lines, which is everyone's problem and nobody's responsibility a lot of times as well.

[00:05:44]
And then the other term that we'll see, and this is mostly terms from the module federation spec, these are not terms I decided to invent, is what do we expose? So, okay, for my thing, what do I want to make available to the shell, or for the design system, what do we want to expose as the components and what do we want to keep kind of hidden, right? If you've ever used, if you've ever made an npm package and thought about that exports and you can define a bunch of different exports, it's the same basic concept, you know.

[00:06:13]
And to be clear, as we said before, there are trade-offs. This is our requisite Thanos meme for the day. I had to get that out of the way, right? We'll see that there's a complexity, and like I said, we're starting at the most complex with the most autonomy, and we're winding it back, right? And so you can decide—you're like, no, this is good, I like this, then great. If you like the most complicated thing with the most autonomy, welcome.

[00:06:38]
Great. That's awesome. And you're like, oh God, I can see where this might hurt, then we'll begin to pull it back from there. So what do you get? You get those independent deployments, the autonomous release cycles, incremental upgrades, the team-scoped blast radius—which, tell me when that actually happens—the technology flexibility, like, well, my thing can be in Angular and there's going to be an Ember.

[00:07:07]
I still question why. What it costs: yeah, now you have to juggle all of that basically, right? What do you do if one thing needs to go out before the other, right? So on and so forth, right? How do you keep that all consistent, particularly if you've decided to take on the mantle and—if you are refactoring a legacy codebase, and that's why you have Backbone and Vue, I'm not talking about you, right?

[00:07:33]
I'm talking about the people who decided from the get-go that this is going to be in Elm, this is going to be in Vue, and this is going to be React for reasons. Yeah, how do you maintain the consistency? You're going to live in CI/CD land, I'll tell you that much. You're going to have to come up with some system, you know. How do you do a rollback during—think about it, always for when we think about the complexity, just imagine there's an incident.

[00:08:02]
Right? Just think about that for a second, right, and think about tracing. Where are those logs, right? Do they all have one shared Sentry thing going on, so on and so forth? You know, and some of that just simply because we won't have to live in this example for one year, two years, three years, we won't feel, but put on your imagination hats and imagine what it's going to be like to endure that.

[00:08:28]
Cool. And so yeah, like I said before, who owns a given URL? How do you transition between remote, full page load? These are now problems that you will have to solve. Now, granted, you are not solving these alone, right? There is tooling. There are other people solving these, right? We'll see that Webpack and Rspack—how do you say RS, I don't know, the Rust one, the Rust version of Webpack. If anyone has ever said that word out loud before, I haven't until just now in front of you all.

[00:08:50]
Those are all things we'll have to navigate. What happens if one of them crashes, so on and so forth.

Learn Straight from the Experts Who Shape the Modern Web

  • 250+
    In-depth Courses
  • Industry Leading Experts
  • 24
    Learning Paths
  • Live Interactive Workshops
Get Unlimited Access Now