Five Module Federation/Micro-Frontend Mistakes

Video Statistics and Information

Video
Captions Word Cloud
Reddit Comments
Captions
let's talk about five common misconceptions and mistakes that people make when it comes to module federation and micro front ends i'm jack harrington and this is blue collar coder brought to you from scenic portland oregon in the fall so the first one we can talk about right here and it's a misconception that people have when it comes to understanding the relationship between microphone ends and module federation and it's probably something that i've added to the confusion on because i've kind of mixed and matched those things in the past but they are two separate things so module federation is a code transport layer that's all that it does it gets code from one application to another as a runtime dependency and microfrontends is an architectural style about sharing code between applications and in particular front-end ui code and there's two core tenants when it comes to what a microfront is and that's one that the microfront end needs to be cross platform or platform agnostic and the second is that it needs to be a runtime dependency that is independently deployable and module federation obviously helps with that second one it makes that code independently deployable between those applications but it doesn't help at all with the first one which is to create that platform agnosticism of the component itself so let me give some basic concrete examples here and we'll create a module federation stream a pipeline between our applications and we'll have in this example two applications we've got home and we've got pdp and now in this case in the simple case both of those are written in react and that home page wants to act as a remote it wants to share the product carousel with any other application and that pdp page wants to consume that product carousel so it's going to act as the host now the nice thing here is that both of those applications are written in react so there's no real work to be done to share this product carousel micro front end between these two applications the home application can simply share the product carousel code and the home page can simply consume it from that module federation code sharing stream and render it just as it would any other component now let's take a slightly more complex example the home page of the product carousel is once again written in react but in this case the product detail page is written in view so how is that going to work well in this case the home page can vend the product carousel onto that stream and it can also vend a shim a diy shim function that uses react to render that product carousel into any element it's actually a pretty simple function to write and so what the view application is going to do is consume that shim that shim is then going to bring in react because it needs to have react in order to render that react component and also bring in that product carousel and then with that you can mount that product carousel on any element on the page and away you go but of course that's a diy solution and you're not going to want to do that for every single component you have and also there are some downsides there's property maintenance and all that sort of stuff that that diy solution doesn't cover so what's a better way to do that well better way to get that platform agnostic behavior that you want when it comes to microphone ends is to use single spa so how's that done well let's talk about that same scenario where you've got again the home pages react and the pdp pages view but in this case instead of doing the diy shim the home page parcelizes the product carousel which makes it a platform agnostic piece of code and then publishes that to the stream the viewlab then consumes that parcelized code and uses a single spot client to render that parcelized component onto the page and single spa does all of the work of making sure that that react component looks and feels just like any other single spot component now that's a little bit of extra stuff if you have react in all of your locations but when it comes to getting your code between application frameworks this is the best way to go and single spa is a fantastic library but of course this understanding also short sells module federation which can do a lot more than just share front end code it can share any type of javascript between applications and that could be configuration flags i18n strings utility functions data access libraries what have you you can put anything onto that module federation stream and get it going between two applications so it's important to understand what module federation is and the scope and breadth of what it can do and also what microfront ends are as a an architectural style and how your code fits into that model all right now to get into the next common mistake or misconception that people have we need to jump back to the office all right the next common misconception that people have when it comes to module federation is that you're implicitly sharing state when you share out this code so in order to demonstrate this i'm going to need to create two applications of course and so i'm going to go and create two different shells all right now over in this first shell i'm going to do pmpx and i'm going to do create mf app and that's going to set up an app for us but first you have to give it a name i'm going to call this one host it's going to be an application on port 3000 and it's going to react and in javascript and i'll use tailwind for that and then we go into that directory and i'm going to yarn and yarn start if the yarn is successful that's what that double ampersand's about and then over on here in the other terminal we're going to do pmpx again and create mf app and over here we are going to create our remote app so we'll call this one remote again it's an application port 3001 react javascript and tailwind and we'll go into the remote directory and then again yarn and yarn start so what are we going to do how are we going to demonstrate this well we're going to go and create a new file so we're going to go create a new file and it's going to be called counter jsx and when you know it we're going to go and create a counter so let me see if i can speed run counters here and bring in react i'm going to bring in use state and that's all i need for a counter and then i'm going to export a default function called counter and then it's going to have account and set count ooh wow okay well github co-pilot is going to help me speed run a little bit here good starts at zero cool all right return and div and we're gonna have a div that says count is the count and then we're gonna have another div that has a button in it that then on click will add one set count to count plus one column plus okay and that's a sesame street joke for y'all add to count i don't know if you get sesame street wherever you are it's a good good show all right so we've got a counter now and we're going to go back into app and we're going to bring that in import counter from counter and we'll put down here the uh you know let's keep remote that's important and then we'll do counter like so and i'll go to port 3001 and now i've got our count at zero and we can just add to count and away we go let's make it a little bit nicer so we can kind of see that it is this thing nice thing we have tailwind around so i'm just gonna make a i'm just gonna get a better border and make that border blue and give it some padding and then give it some rounded yeah kind of make it look like a like a thing oh yeah okay so now it kind of looks like an mfv right like a micro front end so there you go looks good and hey if i hit refresh right what does it do it goes back to zero every time right because a new page load and all we have is that state and that state always starts at zero so let's go and take the same thing and expose it first so i'll go down here to webpack config and go all the way down here to the plugins and module federation plug-in and i'm going to expose the counter from source counter and now i've got to go into my remote shell and then yarn start again and i'm going to go over to my host and then go in with webpack config and go scroll down again here let's see if i have remotes and i'm gonna say remote at remote at now let's give me the url here so i'm just gonna get remote entry that's what it's looking for is this manifest of all of the modules that is exporting you can actually see as you go into here i can i can search for counter and it actually has you know counter in there all right so now let's go and add that on there say at and then give it the url and that's going to connect these two applications so host is now going to be connected to remote as soon as i restart it so let's do yarn start again over here and now when i want to import i can just import the counter from the other application so let's go back over here to our host app go into the app and then i'm going to bring in counter from remote counter get the upper casing right and in this case it's host make it all uppercase and then put that counter in there and away you go so let's take a look so now yep there you go on three thousand i got the counter on host and then on three thousand and one we've got the remote and if i go and add six over here i'm gonna go over to host and i'm still at zero and so this is a misconception that some people have when it comes to module federation and what it's capable of doing in this case all you're doing is just sharing this counter code you're not sharing anything more about it you're not sharing any kind of state and the fact that this code is served from a running app doesn't mean that there's any implicit connection between the code and the server that served it so how would you share a state between these applications well there's all kinds of options for that there's firebase there's graphql subscriptions there's your own rest api with websockets there's all kinds of ways to share a state but none of it is going to happen implicitly because these modules are federated and you're sharing this piece of code all right so this brings me to the third misconception or mistake that people have about module federation and that's the the when the app goes down that code is going to be broken which is not quite a misconception but it's not quite right so let's actually try that out let's go over here to our remote app and we're going to stop it it's dead right and so now if we go over to our host and we hit refresh we're going to die because we go over here to the console we can see that we couldn't load that script and so i get this question a lot well what happens when the server goes down and this one is again partially on me because when i demonstrate module federation i always do it using apps like this and that's because i want that code to regenerate quickly but that's not actually the way that you deploy this so let's go and go back to our terminal and i'm in remote and i'm going to use yarn build and then dev the reason i'm using dev here is because i want to have the nice file names and if you use yarn build you'd get the kind of chunked up file name so all right so let's open up that dist folder and we can see that we have the remote entry we've also got the source for the counter and everything else and this is actually what you deploy to s3 or an asset store basically it's a static application you don't need a server to run this thing so if i wanted to imitate what a static asset store would do all i need to do is use a dumb server application i'm going to use servor so i'd imitate this i'm going to go into that directory and then i'm going to do port equals 3001 mpx server and that's basically going to do essentially what an asset store would do so now over on remote i can hit refresh and localhost 3001 it works great and everything's fine and if i go back over here to our local host 3001 if i hit refresh it works and that's the way that you deploy federated modules you do it to an asset store like s3 and if s3 goes down i think a lot of us are gonna have a snow day when it comes to web development so going on a misconception four there is a related issue when it comes to the stability of these things and that's the misconception that people have that module federation modules are versioned and they're actually not and that's actually kind of the point you want that runtime dependency to get updated immediately so there is no versioning on them and that can add to some risk and potential errors so let's talk about that potential risk and then i'll show you a way to mitigate that at least in react so let's jump over back into vs code and i'm going to stop doing my server and go back in the main directory and then in that remote directory i'm just going to do yarn start again so let's say that i want to add in the app name to my counter so i'm going to go down here to my counter and i'm going to add a property called app to my counter and it's going to have up at the top here a div and then app.name so if i'm over on localhost 3001 i refresh it's lights out game over and why is that well let's go into our console and we can see that it cannot read the properties of the undefined reading name right so we're looking at for app.name and app is undefined so let's go over to app and then we'll add an app app equals name and then remote refresh and now that works awesome okay great but let's just say that we push that to production and then to s3 and now the host team over here they do refresh on their page and boom lights out right why because well in this case again cannot read property name of undefined so they didn't know that they had a contractual change here in what the contract of that react component that counter component was so let's go back over into our host and let's obviously we can just do a quick fix here we can just add on that app name is host and refresh and we're great but that actually doesn't address the underlying issue which is we want these components to be safe and not take down the whole page if that contract changes so let's make this break again and let's try and fix the page at this point from this broken state and the way that we're going to do that in react is we're going to use error boundaries so an error boundary is a component and it basically catches any errors that are found in the running of components that are encased within it essentially now the only bad thing about an air boundary is it has to be a javascript class which you may or may not like but that is the only case that i know of in react where it has to be a class so i'm just going to copy and paste in their example code and i've left a link to that page in the description and so the big things here are that you have a react component constructor creates a state where you store whether you've had an error in your component and the way that you get that error set to true is you get this derived state from error that is percolated up from this component did catch automatically by react and component did catch allows you to go and do something like for example log an error to my service would go and log in error off to splunk or something like that so let's just comment that out and i'm just going to take this error boundary as is it's going to go and if it sees an error it's going to just put out this h1 if something went wrong and i think that's going to work well so let's just drop it in here around counter and then go back to our host page and yeah at least you're not blowing up the whole page and that's the important part and all i did was just paste in the code from the react documentation and just comment out this non-existent log error to my service which you should go and replace with something that would log an error to your error tracking service okay so our fifth and final mistake or misconception when it comes to module federation is around typescript so i need to restart everything with typescript this time and so again i'm going to go and create two terminals and in that first terminal i'm gonna again do pmpx create mf app if you don't have pmpx you can always just use mpx i'm using pmpx because it works on windows and then i'll pick host again application 3000 react and the only difference is i'm going to pick typescript this time and then tailwind and again i'm going to go in there in the host directory and do yarn and yarn start some more kind of thing over here in this other one i'm going to do pmpx create mf app again yes and again i'm going to pick remote and then i'll pick application 3001 this time react and again typescript and tailwind and then i'm going to go into remote and start yarn and yarnstar okay looks like both applications are up and running just fine we got host on 3000 with typescript and remote on 3001 with typescript okay so let's go and start off our example by going into our source directory and i'm going to create a new one called my user mfe dot ts x so we're going to have these microphone ends and they're all going to take user as a required property so let's go over to our app and we'll import that and so it's giving me the red line because it's telling me that there is no user property on here yet so in order to satisfy that i'm just going to put in my user and looks good let's go to try and there you go so now i've got my mfe going in there and that's great i can take out this stuff it's a little bit distracting looks good awesome so now we want to get this over to the host app so again i need to go over here to our web config and scroll down go to exposes ab dot slash and then my user my fee and then give it the source file which is going to be that tsx file and then i need to re-launch our remote okay that's looking good so now let's go and get the location of that remote entry and i'm going to import that into our host so let's close down these and then go over to our host and go into webpack config scroll down to remotes and then add in remote and then give it the name of the fair module which is remote at and then the remote entry.js location looking good and now let's go over to our import and app and we're going to basically do the exact same thing that we did in the other one we're going to import my user mfe from in this case remote and my user myvi and i'll scroll down here and say user equals bob and now i've rebooted the server and it works just fine so this red squiggly is telling us the typescript doesn't know the types of that module remote module use my username fee can't find those types right so why is that well the misconception or the mistake in thinking here is that the federated modules contain any type information from typescript they don't they're just javascript they're just compiled javascript so let me prove that to you i'm going to go over here into our remote and i'm going to close that out and then go into remote and i'm going to do yarn build again in dev mode so i'm going to bring up the my user mfe tsx.js in code but the code is kind of obscured but a little bit by this eval stuff and the reason for that is that dev tool is turned on in our webpack config so i'm going to go over here to our webpack config and then scroll down and just add in dev tool is false and go back into here and yarn build again and now let's take a look at that file and yeah at this time it looks like it should but this is basic javascript right we got var my user mfv and we got the import of the of the create element from react and then you can see it was actually creating that react element this is just basic javascript there's no type annotation on this at all so that's why you're not seeing any typing over on app.tsx none of that is exported when it comes to federated modules so how do we go and fix this well let's go back over into our host and we're going to basically go and add types for remote my user my fee so the way i'm going to do that is create a new folder in here called at types and i'm going to give it the first level name of remote and then i'm going to give it another directory within that called myusermfe and then within that i'm going to create a new file called index.d index.d.t.s and in there i'm basically going to bring in react and then define what my user fe is it's a react function component that takes a user as a string and there you go and it exports it as the default but we're still not working so why is that well we've got to go and create a ts config in our directory which we don't have so let's go over to host and then within host i'm going to do tsc init now it's going to create a ts config file and then i'm going to go and change jsx because this by default doesn't allow for jsx i'm going to change that to react and then i'm going to go find the location for paths and then i'm going to go change this configuration for paths to say that we want to look also at the source for types which is what that directory that we just created so let's go back over here and we can see that now we have proper typing and as we take this out we can actually get like real typing here so it knows that there's a jsx attribute and we can say hello and there you go but that's not quite a complete solution right what you really want is you want to be able to define the contract of an mfe and share it between these two systems such that when that contract changes the remote will fail on compilation or the host will fail in compilation and the way that we do that is well one way to do that is to create a shared library between those two so let's go and create a third terminal and this time i'm going to do pnpx create mf app and instead of creating application i'm going to create a library and we'll call this one mfe shared and we'll create it as a library and then we'll go into mfe shared and then into that i'm going to add react and react dom as well as the types for react and react dom so i'm going to add types for react and types for react dom both of those in development mode and now let's go take a look at what our library actually has so let's go here to mfe shared and in the source directory there's simply just an index.ts file and all it has in it is this in simple function and i'm going to replace that with a definition for our user mfe so again the user mfe is going to have a is going to be a function component that has a user name as a property okay cool so let's build that and then in that directory we can see that we now have a disk directory and within that we have this index.dwts file so let's take a look at that and that actually declares that type of user mfe all right so this looks good now we've got this definition for what a user mafia is so let's go and do a yarn link in here and that's going to allow us to then link that into both the host and the remote so let's go and first off go to the remote and then do from here yarn link mfe shared and then go into the host and also yarn link mfe shared and so down now in the remote we can go into source go into my user ife and say that we are a my user my fee so we get that definition from mfv shared which so we can now replace this with that definition and that works just fine so let's go and yarn start on that looks like it's up and running just fine and now we're going to go and do the same thing over in our host app and then we go into the types remote my user on a fee and go in here and we can just bring it in and say that we are a user mfe and there we go now let's put it in host and it looks like everything's running just fine but of course that's not really the point it was always running fine it was just the types and so this allows you to share those contracts between the host and the remote and when the host and the road are compiling the tse compile phase or babel compiling typescript then you can make sure that the remote components all have the right properties and that the host pages are looking for the right properties and send the right properties to those components to avoid those runtime issues like we saw before when we added properties to a component but didn't tell anybody that we had done that okay well i hope this video helps you understand a little bit more about how module federation and microphone ends relate of course i'm sure you have some questions so be sure to put those in the comments section down below and of course in the meantime you can hit that like button if you like the video and of course hit that subscribe button if you really like the video and get notified the next time a new blue collar coder comes out
Info
Channel: Jack Herrington
Views: 4,634
Rating: undefined out of 5
Keywords: module federation, federated modules, micro-frontend, micro-fe, react architecture, micro frontend, micro frontend react, micro frontend architecture, webpack 5, federated modules in webpack 5, micro frontends, module federation webpack 5, webpack 5 federated modules, webpack 5 module federation, module federation crash course, Module Federation Mistakes, Micro Frontend Mistakes, Five Module Federation/Micro-Frontend Mistakes, Module Federation/Micro-Frontend Mistakes
Id: 0WIFW3s2fDM
Channel Id: undefined
Length: 28min 9sec (1689 seconds)
Published: Thu Nov 04 2021
Related Videos
Note
Please note that this website is currently a work in progress! Lots of interesting data and statistics to come.