Micro-Frontends Course - Beginner to Expert

Video Statistics and Information

Video
Captions Word Cloud
Reddit Comments
Captions
Jack Harrington is an excellent teacher. And he's  about to teach you how to develop web apps with   micro front ends. I'm Jack Harrington, I was a  principal engineer at Nike and also at Walmart   Labs. And I'm here to talk to you about what micro  front ends are and get you up to speed on that. So   why do you want to do that? Well, lots of fortune  500 companies are very interested in a topic of   microfinance. And there's a good reason for that.  So in this video, I'm going to walk you through my   girlfriend's all the way from tip to tail. But as  anybody who has watched my channel before, which   is linked to in the description, they'll know that  I like to entertain as much as I like to educate.   So I'm going to do a good action movie trope and  jump you right into the heart of the action before   backtracking and laying the foundation. So let  me get you excited about my girlfriend's first   and then I'll talk to you about what comes next.  So don't worry in this first section, if you get   confused, it'll all be clear by the end. So let's  jump right in to VS code. Right now. I'm over in   VS code, and I'm going to bring up the terminal  actually, I'm gonna bring up two terminals.   And we're going to go build two apps. So in  this first terminal, I'm gonna run P MPX.   And then create MF app. So P MPX is like  MPX. If you have MPX, just use that.   And create MF app is for create model Federation  app. So in this case, I'm going to pick the name   of my host, I'm going to call this one home  because this is going to be the home page app,   my chooses an application on port 3000. I'm  gonna use React and JavaScript and also tailwind.   Now this other terminal to do exactly the same  thing, but to do PMP x again and create MF app.   And in this case, I'm going to call the  application PDP or an E commerce world product   detail page, an application and this one's going  to go on 3001 Because it can't have it on the same   port. Again, it's gonna be react JavaScript and  tailwind. And again, I'm going to go into that   directory and do exactly the same thing. I'm gonna  yarn. And if that's successful, then yarn start.   Okay, my homepage is running, let's go  back over to my browser. And it shows   me that I now have an app, it's called home,  the framework is react language, JavaScript,   and it's tailwind for the CSS. And there's exactly  the same thing on Port 3001, except that it's PDP.   So let's say that we are the homepage team.  These are managed by two different teams.   And we are going to take on the task  of building the header. So I'm going   to create a file here called header dot  JSX. I'm going to import react from react.   And I'm going to export a  default function called header.   And it's going to return some HTML on there. And  it's going to have a div that's got some tailwind   on it, let's see has got some padding, it's got  a background that's blue, some text that's white   and large, and it's in bold font. And I'm  going to call this fidget spinner world.   Because our app is going to be selling fidget  spinners. Alright, so let's go back over here   and create a new file called footer dot JSX.  And do pretty much exactly the same thing.   And we're gonna put into here, only the  best spinners, because that's our motto,   we only sell the best spinners. And we'll say that  that's the footer. And now let's go into an app.   And let's bring these components in just as you  would any normal React components. So header,   we're gonna bring in from that header file. And  footer, we're gonna bring in from the footer file.   And I'm just going to drop these down  here, header, and then footer. And in here,   I'm just going to say that we have the homepage  content. So we'll start off with a class name,   or you get a little margin vertically.  We'll say that this is the homepage content.   And wrap that div up mostly good luck. Yeah,  okay, looks good. I'm gonna remove the little top   margin there. And wow, beautiful page.  Okay, so now the PDP team is like, Okay,   we're going to start implementing, but we really  don't want to actually redo the header, we want to   use your header. So can we do that quickly? Well,  absolutely, we can, because we can turn our header   on this homepage and the footer into micro front  ends, and we can share them with the PDP page   really simply. So let's give that a try. So I'm  going to go into a file here Webpack config.   So this is the web pack configuration. I'm gonna  scroll down here to the module Federation plugin.   And I'm going to say that this  application, which is named home   exposes the header in the footer, so  we're going to give it the name header,   and this is a object where you give it the key  which is the expose name, and then the location   of the module or the file in this case that you  want to expose. So then so we're doing the header,   and then we're doing the footer, that's a  good idea to keep the names obviously the   same between those two. Don't confuse anybody.  Great. So the only thing we need to do now   is just restart home. So now I'm on the home  terminal, and I'm going to restart that. So   I'm gonna say yarn start again, because we need  to reload that Webpack configuration. But once   we run it, we can see that it works just fine.  But there is something new that's been added.   And that is a remote entry file. So in localhost  3000, there's also a remote entry dot j s. And   that is a manifest of all of the modules that are  exposed by the homepage application. So I'm going   to copy that link. And then I'm going to go over  to our PDP application into the web pack config,   and scroll down here. And I'm going to say that  we have a remote and that remote is home. And its   URL is well home at and then I  give it that remote entry URL.   Now, why home? Well, that's the same home as  defined in this web pack config as the name   right here. And the only requirements on this  is it has to be a valid JavaScript variable   name. So you can't use things like dashes can't  be homepage, it could be home underscore page,   that's fine, because it's a valid JavaScript  variable. So we're going to use home.   And now this is going to allow us to access  any of the exposed components from home.   But of course, we have to restart the  server again. So let's go over here to PvP.   And then we'll restart the server just to  get that web pack configuration loaded.   And now if I go over here to our  homepage and Grab app like that,   and copy out this because I'm kind of lazy  and I don't want to retype all that stuff.   I'm going to go over here to our PDP and go to  the app, which looks almost identical because   it came out of this the same template and paste  that in there. And let's say PDP page content,   and I'm gonna hit save and well that work, huh,  let's try it out. Okay. Okay, so can't resolve   the header and the footer, obviously. Okay, so  there's no local header and footer. But if I do   home here, and I save, and I go back in here,  we can see in our serving the PDP page content,   and we have our header and our footer, the  exact same header and footer that came out of   the homepage. Awesome. And even better, check  this out. So you go to header here and I say,   fidget spinner world to  the fidget spinner warning.   And I do refresh here. Awesome, I get that as  I would expect, and I go to PDP and without any   restart, or refresh or code change or anything  other than hitting refresh in the browser,   I get the updated content. So that's a runtime  connection between these two applications. Okay,   so let's have a look at our completed application  that you will have by the end of this video. And   of course, all of the code is available to you on  GitHub. And let's talk about why micro fees are   so important and why companies are really invested  in them. So first off, this is our application,   you can see that this is the completed homepage.  This is on Port 3000, as we started before,   and it's got our all of our fidget spinners and  it's got our header, it's now a cart link on it,   it's got a way to log in. There's a product  detail page that shows the detail around one of   our spinners. And there's a cart page that shows  you all of the products that are in your cart. So   the reason that big companies are interested in  microphones is the same reason that big companies   are interested in micro services when it comes  to the back end. So on the back end used to have   monolithic API servers. And that meant that a  bunch of teams were working on a single code base   that had a single deploy cycle. And the micro  service revolution allowed that to change.   So now, every team could manage his own server  and update independently, micro front ends,   bring that same methodology to the front end,  meaning that every one of these applications   homepage PDP and cart are managed by separate  teams. And now they can go and deploy   independently. And then if they Venn down any  micro front ends that are consumed by other teams,   those are automatically updated when they deploy.  So for example, in this case, the cart team   manages this little cart drop down over here.  And whenever the cart application deploys,   that cart gets updated, updated along with  it. And all of the other applications, we use   that cart and so it's done dynamically. So not  only can the teams manage their own applications,   but they can actually manage smaller pieces of  the UI. So Now the question becomes, when do you   decide what is a microfi? And what is not? Well,  let's jump back over here to the atomic design   methodology. So the atomic design methodology,  pioneered by Brad Frost basically defines how   you eyes are structured. So you start with atoms,  which in this case would be things like a button,   or a label, or something very small like an  image. And then there's molecules, which are   slightly larger components that use a bunch  of those atoms, for example, a label input,   which may use a label as a text, and then an input  as well. And it manages the relationship between   those usually just stateless Li, and then there's  organisms. And in this case, an organism would be   something like this cart drop down over here. So  it's a self contained piece of UI that manages its   own state and understands how to bring together  all of the molecules and atoms to get something   done. So in this case, that would be these text  fields are here, that clear cart and the checkout.   And it's this unit of UI, the organism that  I think is most appropriate for sharing as   a microphone. And I don't think that you should  run time share atoms and molecules, that's just   my personal opinion. But that's where I kind  of draw the line. Now, there's also templates   and pages. Those don't really categorize for me  as microfiche, but they are things that you can   share. In fact, when we talk about my girlfriend's  more in this video, and as we go along,   we'll be talking about the underlying technology  here, which is module Federation. And module   Federation actually allows you to share a lot more  than just micro friends. In fact, we'll actually   start off by sharing some functions, and then  we'll get into components and then we'll get into   sharing full page contents, and routings. It's  really exciting stuff. Okay, I've introduced you   to the world of micro front ends and why they're  important to companies. Let's now talk about   module Federation, and what it is and why it's  different from other techniques of sharing code.   So model Federation is a feature that's built into  Webpack. Five, it's absolutely free. And it is   part of the standard Webpack five deployment now.  So anything that's built on top of Webpack, five,   can use module Federation, and he saw from that  PNP X, I've actually got it set up so that you can   use Wow, 10 different view templates right now.  And there's also Angular and other frameworks,   they can also use model Federation. So model  Federation can be applied to pretty much every   popular view framework, it's great stuff. So  let's talk a little bit about why it's different   from other methodologies of sharing. And to  do that, I'm going to close out these and I'm   gonna get us into the kind of architectural  box layer, we're gonna do that together.   So we're gonna do file here, and it's gonna be  called architecture. Do, I have a Visual Studio   extension draw.io extension, allows me to kind of  draw diagrams and go all full architecture mode,   right inside my VS code. Let me just drop in  here what we started with, right, so we got   the homepage app that currently is at one Dotto  and we got the PDP app over here. And inside the   home app, we had the header and the footer. Now,  let me go and build out the NPM version of this,   I'm going to create a new page, I'm going to call  this NPM. And I'll paste these two in. And then I   bring in a box for the NPM library, right. So this  is going to be our NPM library, and it's kind of   kind of sits somewhere between these two. And then  we're going to take the header and the footer,   and we're going to put it into our NPM library.  And we're going to arrange it to bring it to the   front. So it all makes sense. Looking good. Okay,  great. So now we have extracted our header and our   footer into our NPM library. Now we got to reuse  those. So I'm going to go and draw a link between   the homepage app and the NPM library. And I'm  gonna do the same thing with the PDP app. Alright,   so drop that in there. Those are looking good. I  want to move this around a little bit to get these   arrows nicely lining up. Okay, cool. So  let's say now that we are a developer   on the homepage app. And as part of the homepage  team, our job is also to maintain the header and   the footer in this shared NPM library. And so I  get a JIRA ticket saying, hey, we need to go and   change this text or whatever. Now I've got to go  and jump from where I'm normally working, which   is the homepage app working on features in that  app. And I got to jump over to this NPM library,   which may have not been worked on in a long time  because the header doesn't update all that often.   And I've got to go and do that change.  And then I'm going to bump that version   to 1.0 point one and publish that out to our  local archive repository. And on the homepage,   I'm then going to bump that to 1.0 point one which  is going to then grab the NPM library and release   to production kind of a hassle, same sort of thing  over here. And that then have to go and talk to   the PDP team and say, Hey, there's a new version,  the header, please use it, and then they would go   and bump it. And there you go. But now from the  customer perspective, right, I'm on the homepage,   and I click into a product, I'm actually now going  to get an older version of the header on the PDP   page app, which may actually not be great at all,  in a black friday situation at a major e commerce   company, they're going to be making changes all  over the place all the time. And so when they make   a change the header, they're going to want to see  that happen immediately between these two pages.   So how are we going to solve that requirement?  Well, let's go back over here and see what we   can do and talk about some solutions that I've  seen in the industry. And one of the most popular   is to use something along the lines of an asset  store. So we'll call this the Asset Store option.   And again, we'll start off with our  one point lm 1.0, as we had before,   kind of bring these down a little bit and  widen out the space because I need some space.   And so now we're going to bring  in this header footer project.   And the idea of the header, the footer  project, is to contain that header and   that footer. And we'll bring those to the front  so we can see them. Again, oh my gosh, got to   make some more space here. All right over here,  boy drawing diagrams, the bane of architecture.   And what this one's gonna do this header footer  project is it's going to build some s3 artifacts,   it's probably going to build a static version  of the HTML, and it's going to build the J S,   and then those are basically going to be injected  onto the page. So we've now even removed react   from the equation here, right? This is just  maybe react that is rendered as static HTML,   and then some helper JavaScript and  actually add some dynamic behavior.   And that is then put up on s3. So we'll draw an  arrow between those two things, this, this thing   is going to create that s3 artifact. In order  to consume that to make it easy on ourselves,   we're going to go make a shim library and drop  that in here. And its job is to go and fetch   that content from s3. And its job is to return to  the homepage app and the PDP page app, some HTML   or some references that are grabs from s3, the  homepage and PDP app, then inject into their page   templates to drop the header onto the page. So  these guys need a connection to that shim library.   And then the advantage with this one is that this  header and footer can update those s3 artifacts   at any time that shim library is designed to make  sure that you always are getting the most recent   copy. And that gives you your dynamic behavior. So  this header footer project, what when those late   requests come in from product to update the header  immediately, the Header Footer project and then   deploy to s3. And all of those changes will show  up on the homepage and PDP page automatically,   as long as they're not caching those results. You  can see there's a lot going on here. And there's a   lot of custom work. There's a lot of custom CICD.  These are very custom pieces of work, very DIY,   that are company specific. And of course,  having any developers move from the homepage   and start making changes on the Header Footer  project because it's so alien and maybe   entirely written in a different view framework.  That's a big change. So there's a lot of context   switching, see, and having a team is dedicated  to that probably a Header Footer project. It's   really just a large company object. Okay.  So what does module Federation bring the   party. So module Federation, let's go  for the module Federation approach here.   And we'll start again with our homepage and PDP  page app. And in this case, we have the Home app,   and we have got the header in the footer, and  all the PDP beige app needs to do is just connect   directly to the header and the footer, just  like that. And so you get the dynamic behavior,   whenever the homepage application pushes. So it  goes up to 1.01, the PDP page automatically gets   the new code, you're not changing development  environments, those Header and Footer components   are still written in React. And as long  as the PDP page is also written in React,   then they work right away. So there's no issue  there with changing frameworks or different   packaging or whatever. And also, the work is  done in context, meaning that as a homepage,   app developer, I just work on the header directly.  And I just work on the footer directly. And   there is some risk there and we'll talk about that  in just a minute. But it's much lower in terms of   context shift cost when it comes to development.  So you can see why have these three method ologies   module Federation is the most attractive when  it comes to sharing component code. Alright,   let's put away our architecture  tools for a bit. And let's talk about   some of the questions that I get most often when  it comes to Module Federation. And the first one   is around asynchronous stuff. So how do I  actually include the header, for example,   asynchronously? So let's do that. Let me just show  as opposed to tell. I'm gonna bring in suspense   from react. And here, I'm gonna say const.  header equals and then do react lazy.   And I'm going to give it a function that's  going to import the header. It's gonna do a   dynamic import. This is absolutely standards  and asynchronous, dynamic important. It's   works in React, but it also works on any other  technology you have any type of library you have   the special Saucier, isn't this react lazy. And  then we're going to wrap the header in a suspense.   And we're going to get a fallback  saying that, while we're waiting,   we should put in a div, which says, for example,  loading, that's a classic fallback div. And so   now let's restart our servers. So we're gonna go  back over here to our home, and then start that   and then go to the PDP page and start that,   as we go through this, by the way, keep a keen  eye on this tab over here, it's really nice that   that actually has the names of the directory  in there, we're gonna actually have five   running applications by the end of this. So we're  gonna be doing a lot of jumping around here.   Alright, so here is our PDP page. And as we can  see, fidgets better world is running just fine.   So that is a synchronously loaded, but if  we kind of want to prove it to ourselves,   let's go and make that stateful. So  I'm going to go and return this here.   And then do use state. And we're going to  say, okay, so we have some mistakes in here   for showing the header. And we'll use state  for that. And we will only show the header   if we are true. And then I'm gonna go  make a button that says, show the header.   I'm gonna make it large. And give it  some padding, just so we can see it.   Okay, cool. Alright, so the first thing we  need to do is start that off as false. Right,   we don't want to show the header by default. And  then if we get a click here, we're gonna turn that   to true. So unclick, Set Show header to just true,  really, I can toggle that. There we go. Alright,   so we haven't shown the header so far. So let's  go over here to our inspector and take a look   at our network and see what we got going on. So  I'm gonna refresh this. And we're gonna see that   if I scroll down here, we have loaded the footer.  But we have not yet loaded the header. And when I   click on show the header over here, we get the  header. And actually, let's go take a look at   the size on that it came in at 1.1 kilobytes. So  that's another really important point to Module   Federation. So if I look back over here, at the  Webpack, config, we can see that there's another   key down here that I haven't talked at all about,  which is the shared key. And this is all of the   libraries that are shared out of this homepage.  So what I'm doing here is it's grabbing all the   dependencies by just looking at the package  json, and then getting the dependencies.   So it's gonna share them all out. And then it's  also going to share as part of that react and   react DOM. But it's going to override those to say  that they're shared in singleton mode, which means   that there can only be one react on the page at  a time. And that's actually really important for   react because react does have some data that's  managed at the library level. And it is singleton   in nature. And so if you have multiple instances  of react on the same page, it kind of freaks   out a little bit and breaks. So you don't want  that. So Webpack shares and manages that sharing   for you, which is really awesome. And that's  why that header only comes in at 1.1 kilobytes.   All it's doing is just bringing in just the  component code for the header. Now if there   were any other dependencies that header needed,  like moment or whatever, you would bring those   in as well but only in the case where you  imported header, so that's really handy.   Okay, so now I'm not going to do this this  way. So I'm going to go and unroll all this   and we'll just go back to plain old header   And we'll talk about the next question that I  get when it comes to Module Federation, which is,   what happens when the app goes down? And  the reason that I get this question a lot   is because this is the way that I demonstrate  model Federation, I run it in apps. But that's   not the way that you deploy model Federation. So  let's go into that. Let's actually take down home.   And we'll go over here to PDP and we'll see Yeah,  it blows up. Absolutely. 100%. No question. Yeah,   blows up. Let's see. script loading error,  couldn't load Header Footer on upset. Absolutely.   So true. If my demo app goes down, right, that's  not going. So true. If my demo app goes down, then   the sharing system goes down. That's true.  But that is not actually the way that you're   going to Deploy Module Federation. And that's why  this is not really an issue. But there is another   related issue that we'll get into in a second.  So the way that you deploy model Federation   is you build and deploy it to a static asset  store like s3, because you want to get that   aka my our CDN, the style caching and all that  kind of goodness. So let's first build it.   And let's create a local directory called Dist. So  let's go in there and take a look at what that is.   And it's got a bunch of J. S  files. So there's really nothing   unique to this, you don't  actually have a server in here,   some of these MPX, and a module called server to  run this application on Port 3000, which imitates   a static asset store, right? server  doesn't know anything other than just   serve these static files. So it's just like s3 in  that case. So now we got 3000, back and running.   And I'm going to do refresh and you're good to  go. So as long as s3 in your static asset store   don't go down, then you're not going to have an  issue when it comes to the code not being there.   So that's not the risk that you should be worried  about. The risk that you should be worried about   is that a developer on the homepage team may  change the API contract of header and make it   work in home, but not actually tell the PDP  page team that the API contract is changing,   that is the risk that you've got to worry about.  So let's try that out. And see how this actually   can blow up. So first, I need to get out  of my sharing of the compiled dist there,   and then go back and do yarn start. And  then our sharing the live code again.   So now we'll go into header. And I'm going to  do app in here, because the feature request was   to put the app name into the header. So this is  gonna say, app dot name. And my save, and I'm   gonna refer refresh the homepage and boom,  what's the issue? Well, the issue is that   we cannot read name because the app is  undefined, right? There's no property,   we didn't put a property called App on there. So  as the developer on this Jira, I'm going to go and   then say, Okay, well, I need to fix that. Right.  So I'm gonna say app. Name is. Done, okay? JIRA,   close, PR reviewed, done. redeployed. Wave is  excellent. Next year, please. Right. So okay,   but over on the PDP team, we're just swimming  along doing our stuff and we refresh the page and   blowing up, right. So why is that? Well, we didn't  make the corresponding change on our side. So   yes, of course, I can make the change on the PDP  page side and do all that choreography. But how   do we actually protect ourselves from that, so  that this might potentially never happen? Well,   the trick there is to use error boundaries,  or some equivalent in whatever view framework   you're doing. But in React World, we're gonna use  an error boundary, I'm gonna create a new file   called Safe component. And we're gonna bring in  React. And unfortunately, an error boundary has   to be a class. So we are going to extend save  component from a React component, that error   boundaries are actually the one case I know of  where you absolutely have to use a class in React.   Now we're gonna have a constructor, and it's  going to set the state so that there's a state   value on this. And it's basically going  to tell us whether an error has occurred.   And then we're going to add the two methods  that are specific to a an error boundary.   The first is component did catch which gets  thrown when the component cashed, and then   given the error, we return that our new state  is has error. True, right? We can do a lot more   here. We can specify what the type of error is. We  can console log it, we can send it to, you know,   Splunk or whatever. You can do all that stuff. I'm  not gonna do that right here. I'm just gonna go   and render out something safe. So let's go make  that render method. And basically say, Well, if   we've had an error, then we're gonna do something  when otherwise, we're gonna, it's gonna return   the children. Okay, so now let's go back over  to our PDP page and import our safe component   from that save component file, and then we're  going to wrap our header in that save component.   And go over to here and we refresh. And yes,  something went wrong. Great. So now our page still   runs. But it doesn't render the header. Now there  is a fallback methodology that I've talked about   in a video on my channel, where you can use both  module Federation and NPM. So that in the case,   when something blows up, you actually fall back  on an older version, that you got an NPM. That's   a great strategy to hear really depends on how  far you want to go with this protection. So   let's go back over into our homepage and actually  fix the bug and see that it works. So we're going   to remove the app here. And then go and remove  the necessity for the app over and header   takedown or two, and you go, everything looks  great. Alright, so I've introduced you to the   world of micro front ends, we've gone and  built two different applications. Already,   we've talked about why micro front ends are  important, what module Federation is how to handle   asynchronous loading, and how to handle error  states. Let's now actually start building out our   application and learn more about model Federation  as we do. So now to do that, we need to actually   go and build our API server that's going to have  our products and it's going to have our cart. Now,   yes, I'm going to go and create a monolithic  single server for this, I didn't want to have   six tabs running. But yes, in the real world, you  probably have multiple servers with multiple data,   you know, you'd have a product server, and you'd  have a cart server and user server and all of that   stuff. But in this case, we're just going to have  one server. Alright, so let's go back over into   our terminal and create yet another terminal.  Yep, we're gonna have five by the end of this.   And again, I'm going to do pm px. Now, why pm  dx, by the way, it's a Windows thing. Turns out,   I'm on Mac. But it turns out that P MPX  is the way to go on Windows. Who knew.   And if you're on Windows, you know, like,  no MPX works just fine, let me know.   But I'm doing this for my, my friends and  Windows world. So let's do create MF app.   And in this case, I'm going to make it server.  And instead of application, we're going to go   down here to API server, I'm going to put it  on Port 8080, you know, as I guess, as usual,   when it comes to API servers, and what we're going  to use as a template is nest J S with off. So this   one is going to use nest J S as our API server,  it's going to be a REST server. And we're going   to use j DVT, or jaunt based authorization. And  that's the template for that one. So now I'm going   to go into server. And I'm going to yarn it get  that all going. So let's take a look at what's   in the server, we've got a public directory that  has all the assets that we want to put in there.   And you're gonna be able to find those on  GitHub, but I'm just going to add them locally.   So this is going to have a fidget one dot jpg,  nice, cool. Wagon Wheel looking fidget spinner,   friend of mines all in a fidget spinner.  So I figured this would be a fun,   fun demo data piece. And we'll delete  that. And then if we go, yarn start here.   We can bring up localhost 8080. And then go to  fidget one dot jpg, and awesome. So now we know   that we are getting this set of static assets.  That's good. So now the next thing we need to   do is ensure that we can get the list of products.  So over here, we've got our auth stuff, we're not   going to touch that that is the JDT Mandrin. We're  not going to touch users. But I will show you that   there's two users that are kind of baked into  this. There is Sally, there's a password of 123.   Maria, who has a password of 123. You  can add as many users as you like,   obviously, this is just demo stuff. You can hook  this up to a real back end if you ever want to.   So in modules, we've got two modules. We've  got authorized and unauthorized. So let's take   a look at our unauthorized controller. And what  it's telling us is that we've got a controller   that's camping on unauthorized and if I get it  I'm going to return true just a single return   true value. So I'm going to do localhost 8080  And then do unauthorized and it's going to turn   true, fabulous. Okay, so what we want to do is  to Change this code so that instead of being   unauthorized, it's products. So first we're  gonna change anything, it says unauthorized   to products. And I'm gonna make that  lowercase. And this is gonna break up   all kinds of stuff. So I'm gonna go over here  to unauthorized, change all that products.   I'm gonna change this directory name to products,  and change these file names to products.   And finally, I'm going to go into app  module and change this to products.   Do the lower casing. Alright, let's  take a look. I'm gonna do yarn start   Dev, I think. Yeah. So this is gonna  continuously watch the server for updates.   I didn't start in that the first time.  All right, let's do this. localhost 8080.   Products. Okay, cool. returning true. That's  great. Awesome. Okay, so now I've got my routing   set up properly, I've got the products,  unauthorized route, because we want to be able   to get products without actually being logged in.  In this system, we are going to have to be logged   in to add items to our cart, we're not gonna allow  for anonymous carts, you can do that if you want.   But beyond the scope of this. So the next  thing we need to do is hit our product list.   So that root level over here under source, I'm  going to create a new file called products.ts. I'm   going to paste in our product definitions. Again,  all of this is available to you on GitHub. But   let's talk about a little bit about what a product  is. So it's got an ID, it's got a name, a price,   a description and image, which is the URL to the  localhost, and then the long description. By the   way, I had some fun with GPT, three to build  out these long descriptions. So if there's some   insane stuff in there, you can blame GPT three  for that. Alright, so let's go back over here to   our products module, and controller, and then over  in here, we're going to import those products.   As well as the definition of a product.  And it's not going to be from product data,   it's going to be from products. Cool. And  this is going to return an array of products,   which is going to be from products. So let's  save that out. And refresh and awesome. So fast.   I love it. Next, Jas is actually really  cool. If you get into server work,   I strongly recommend checking out nest Yes, of  course, Graph QL. Alright, so let's go back over   here to Visual Studio code and then add another  method. So this is going to be able to get by a   particular ID. So in SGS world, you give it this  decorator for the route that you want. So in this   case, it's cold ID basically gonna map that  Id onto the parameter, it's gonna be a string,   we're then going to go in through  the list of products and find   that product ID. And we're going to  parse out that string to a number. Okay.   So let's go back over here and do instead of  products, we're going to do products, one,   and that just pairs down to the one product and  see product ID is 10. There you go golden silver   gears at $9.99. Awesome. Excellent. So that's  pretty much all we need to do for the server at   this point. Let's jump back over into the client  and get that going. Alright, so let's close down   that window, close on server, go over to home.  And then here, we're gonna create a new file   called products, dot j s, and we're gonna specify  our API server is going to be localhost 8000.   And then we're just going to use Fetch to go and  get the list of products. So it's going to fetch   off of add slash products. And then it's just a  return a promise, which has the JSON out of it.   So that's going to give us back our  list of products. But while we're here,   let's go and add another one for getting a  particular product by ID. So get product by ID,   and that's going to be used by the PP page. So  when they want to get data on their product,   they just have a particular product in mind,  right? They've got slash products slash one,   they're gonna go and give us the ID and then we're  going to get back the data that's specific to them   by calling that by ID endpoint that we created.  And then because I'm a big fan of reusing code,   I'm also gonna bring in a currency converter,  which is uses intell. And we're going to use   the US US Dollars currency so that when we format  the prices nicely, you know, make it look right.   Alright, so let's go over to our app page. And  we're gonna do this a little bit differently. So   I'm going to create a homepage content component,  and I'm gonna bring it in to this homepage content   area, and there's good reason for that. It's  always good to not have mega components anyway.   So I'm going to do a new file here and say home  content, dot JSX. And I'm going to bring in the   usual react and use state and use effect. And then  I'm also going to bring in products. By the way,   if you're wondering how I'm getting that  awesome hinting that's actually GitHub co pilot,   and then I'm going to start our home  content component, it's going to have   our product list and use date. And then to  go get that I'm going to use a use effect.   Use effect takes a function, which is  the effect that you want to effect,   and then takes a dependency array. So in  this case, the dependency rate is empty,   because we want to have this run only once.  And then I'm going to get products. And once   I get that value back, because then it's  a promise, I'm going to set that products.   Alright, so let's start off on our JSX. So  I'm going to put some JSX in there that's got   it's got some white padding on it. And it's like  grid layout, so it's going to have four across.   So that's my grid calls for with a little gap in  between each one. I love tailwind, so expressive.   And then with each of the products, I'm going  to run a map and put the key on there for the   product ID. And then let's try it out.  So we're gonna go in over into our app,   and we're going to bring in our home content   from that home content file. And then I'm  gonna put it in there for the homepage content.   And I don't need that extra wide padding. They've  already got that. So let's have a look. Let's hit   refresh. Hey, cool. Let's making the connection  to our API server. And putting up our beautiful   fidget spinners. I really should be getting into  these like, more than I look at them. I spent   multiple days with this example. And I'm like, Oh,  wow, maybe reward myself with a fidget spinner.   Alright, let's continue on. So let's go back over  nor home content. And I'm going to paste in here   that we want to Flexbox and that  Flexbox is going to have a name on it.   Let's take a look. Nice,  adding in our name looks good.   And let's go add the price in there and make  that the next element in our flex box. And it's   going to use our currency formatter to  format our product price into US dollars.   So let's take a look. Pretty nice. Okay, cool.  And I think the last thing we need to do is   just add a description, so the customer knows  what they're buying. Let's drop that in there.   Yeah, looks pretty good. Text is  a little large, but that's okay.   Alright, so our teams are in the mode of sharing.  And our PDP page wants to reuse our Git product   by ID function to get the product by ID. And  that's one of the great things about module   Federation is that not only can you use it to  share components, but you can use it to share   any type of JavaScript could be constants, it  could be encoded JSON, it could be functions,   it can be components, it can be whatever  kind of JavaScript you want. So in this case,   we're also going to share out our  products library, I guess file module   from our Home app. So let's go back over here to  Webpack config, and scroll down again to exposes,   and all we need to do is just add in products,  and then say that its products dot j s.   Alright, let's say that out, and again, I have  to reboot home because the Webpack configuration   has changed. And now over on the PDP side,  we can start doing the same thing. So I'm   going to go and close out these files. And  I'm gonna go over here into the PDP content.   And I'm going to create a new file, and  we're going to call this PDP content   dot JSX. And into that, I'm going to also bring  you state and use effect because they're gonna   do pretty much exactly the same thing. We're  going to hard code right now that our product is   one. And let's go over here to our  app and bring in that PDP content   from that PDP content file, and let's go  and pop that down in there for its content.   Let's take a look. There we go product one, as  you'd expect. Okay, so let's start bringing in the   code to get that product. We'll go back over here  to our PDB content. We'll bring in our get product   by ID and also our currency for matter from home  but instead of header or footer, in this case,   we're just going to use products like we did  before. So let's save and if this doesn't work,   it's going to blow up right now. So let's know  it looks like it's going to be good. Okay, great.   Alright, so let's change this to ID and then I'm  gonna drop in here some state so we're gonna say   that this is going to be the the product  we actually gotten and put in here ID at   the moment So we're just gonna say if we don't  have a product, then we're going to return no.   And so right now it's going to turn  nothing. And so we're empty in there.   And so now we need to bring in a use effect.  So we're going to bring in a use effect,   we're gonna say, okay, so if we have an ID,  which is specified as ones, we're gonna have one,   then we're going to go and get that product by  that ID. And with that product, we're going to   set that product. So in fact, let's simplify this  code even a bit more, we'll just say set product.   Alright, take a look. That looks like you're  good. Okay, so I think we probably got the   data. In fact, I probably just do at this  point product name. Yeah, we'll spend are   good to go. So let's start laying out our nifty  UI in here, we'll just replace all of this.   And we'll have a two column layout,  this time with a little gap in between.   And then we'll have our product image in the  left hand side. So let's hit Save. And there   you go. Looking pretty good, so far, cool. So  let's get to get in on that right hand side,   and we're going to bring in a div, this got a  flex box, and it's going to have our product   name that's expandable unless the flex grow  and it's gonna be nice and big. And then at   the end of whatever that is, we're gonna have  the currency formatted for the currency price.   That looks good 599 Are you out of your  mind. And let's bring in the description.   Pretty good. And then let's bring in the long  description generated by GPT three. All right,   here we go. I just you know, I'm not a good  copywriter like that. Our wheel spinner is fun,   functional, actually looks really good. It's  amazing how much DBT three was able to deduce   just from like a wheel. fidget spinner that spins  was a baby, I gave it that. And it gave me this,   which is crazy. Okay, so next thing we want  to do is allow for us to do like product   one like that. Now, the Webpack configs are  actually set up to go take a look at them.   With History API fallback to true which basically  means that any route that isn't served from some   sort of static asset is going to just render  the same application in the dev server remote.   So that's why you can basically give this any  URL you want, you know, any URL, and it's just   going to go and give you the same page over and  over and over again. So that's why we can use   something like React Router DOM to actually select  out different products. So what we want is, we   want to be able to save, you know, 10, for example  here and get 10 as opposed to our hard coded one,   which is we have now. So let's go and stop our  PDP server. And now we're going to go add React   Router DOM. And I'm going to do a yarn start  again. And then over in our app, I'm going to   go and bring in our React Router DOM stuff, let's  get rid of suspense there, we no longer need that.   We're no longer suspenseful. And we're  gonna wrap this whole thing in router.   And I'm not gonna do the Save component  stuff, that's fine, it's safe as is   not planning on blowing anything up. And now  inside here, you're gonna put the switch.   So this is where we're going to change out  the content. And in React Router DOM world,   use a switch for that. And then inside of that  you've got a route. And we're going to say that   the path is going to be something along the lines  of slash product, and then an ID and then the   component that is going to be rendered if we have  that is the PDP content component. So let's hit   save there, and see if this works. Let's go I'm  gonna close out that you don't need that anymore.   And yeah, it works fine. But if we go to like,  for example, just slash right, that doesn't match   this path pattern here. So you're not going  to get anything. So let's go back to product   10. And that works fine, because that matches  slash products slash ID. So how do we go and   get that ID, let's go back over here to our PDP  content. And I'm going to go bring in US params   from React Router, Dom. Alright. And that's  actually pretty easy. So I'm just going to put   in their ID and then use use params. That because  use pram you can have multiple parameters. So this   is gonna return you an object which we want to  D structure and get out the ID. So there you go.   Save that out. Oh, that is pretty. That may  be the one I get. So I've got our homepage.   We've got our product detail page we're showing  the customer has a bunch of these fidgets spinners   but now we want to be able to sell the customers  and fidget spinners. We've got an E commerce   app after all, so we want to do some commerce. So  that means that they need to have a way to log in   and have a way to add and remove and view  their cart. So why am I doing all this on   E commerce stuff. And using this example? Well,  this is going to allow us to explore how to share   state between the host and the remote. So let's  talk a little bit about the nomenclature there.   So when it comes to our header, for example,  the homepage is the remote. And then the PDP   page is the host. So the PDP page is hosting the  header that is remote to it. And it's remoted in   essentially, from the homepage, so I want  to talk about host and remote. That's that   relationship. And in this case, we want to talk  about exploring how to share state between the   host page and the remote that's coming in. So  we're gonna have a way to log in to our server to   get a job back the JBT or JSON web token, not sure  why it's pronounced jot as opposed to whatever.   But that's going to be our authentication. And  we're going to want to share that between the host   page, which is going to want to know if it should  add like for example, the add to cart buttons,   and the cart MFP, which is going to show you your  cart. So The MFE is going to want to know that you   have a jaunt. And the homepage is going to want to  know that you want to have a job. And you're also   going to be able to share the cart items between  the different parts of the system. So we're going   to explore using this shared state. Okay, so let's  jump in and start working on building out our   cart. And that means going back to our server,  and working on that. So over on our server, we   have modules, and we got this authorized module.  And if we go down and we look at the the readme,   we can see some documentation on how to use  the authorization part of this. So for example,   I'm going to create yet another terminal. And  I'm going to follow this example here, this   example is to do curl, and hit up this localhost  8080 authorized route, which means that I need   to have some authentication details to hit that  route. I don't yet. So that's going to give me   401 message on authorized. So what I can do is I  can post to login with the username and password,   and I'm going to get back a jot. So I'm gonna copy  and paste this again, this is just in the readme   and paste that in there. And that gives us back  an access token. And that is our job. How's that   work? Well, this J S has a whole section in its  documentation on how to do authorization. And he   pretty much just follow that. And it'll give you  this auth login. And then you can specify some   users, of course, you can go get them anywhere,  but again, I've gone put in there, Maria,   and 123. And that's what we're passing in here  and marine 123. And that gives you back this job.   Alright, so then let's go back into our readme  again, and see what I can do with that job. Well,   I can scroll down. And I'm going to copy this  line, which is starts off with the same thing   we did before with authorized but now we're going  to give an additional header. And the header is   going to say authorization, and it's going to give  a bearer. And then I'm going to just paste that.   And I'm going to copy the job that we got  back all the way up to but not including the   quote and paste that in there and paste in  putting the quote there. And we're going to   get back that we're our user ID is two. And so  why are we getting that back? Well, let's go   take a look at our authorized route here. So we'll  go into the controller. And we'll see that when we   get we use a guard. And that's basically saying,  okay, guard this method by applying that John J T,   and that particular off guard. And that's going to  give us a request when we get run and we pass that   jaunt. And from that job, we're going to get  the user and the user ID. So that's pretty easy,   right? Okay, so the first thing we need to do is  kind of we did with products, but now we need to   do with authorized so we're gonna need to change  all that stuff that says authorized to cart cart,   here cart, their cart here and everywhere.  And we'll change the name to cart   directory and we'll change the file names  to cart. And we'll change this to cart.   Okay, looks pretty good.   Couple more carts in here. Seems to be Okay, at  this level. Let's go back up to our app module.   That's the last place that actually see I'm  going to change authorized to cart and then   lowercase that cart and hit Save. And let's see  I can actually test this out my going up here   and doing exactly the same thing as before,  except instead of authorized I'm going to do   cart If I've made all the changes correctly,  yes, that's good. Okay, so now we're working   on the cart route. That's great. So we changed  the route successfully. And now we just need   to kind of upgrade this cart controller with  our cart functionality, because obviously,   returning a user ID is is not what we want, right,  we have the John functionality, we can now log in,   we need to actually maintain a cart. So I'm going  to start by bringing in the list of products,   as well as the interface for a cart. So a cart is  going to have multiple cart items, it's gonna have   array of CART items. And those cart items are  going to extend the product, they're going to   be an exact replica of the product data. But with  an additional quantity, how many of the fidgets   spinners Do you want. And so the cart is basically  going to have everything that you need to know,   to render out the contents of the cart, it's gonna  have all the product information plus the quantity   that you want. And then I'm going to bring in a  little helper function here called initial cart.   And this is going to take a  list of indices. So this is the   references into the products that we want to kind  of preload the carts for our particular users. So   we're going to give Maria some stuff in her cart  already in Sally some stuff in her cart already,   just so this a little bit easier to test.  And we're going to store that down here in   our cart controller as a private member  variable, it's gonna be called carts.   And Sally has ID number one, and she's going to  have an initial cart that has items 02, and four,   and and, and Marie is going to have items one  and three. Okay, so the first thing we need to   do is return what's in a cart. So we're going to  use this Get method, and we're just gonna return   whatever's in the cart of that particular user  ID. So again, Sally's number one, so that's going   to map to there. And reason number two is going to  have to there, we're not going to return a number,   we're going to return a cart, or in turn a  promise to return a cart. So let's try this again.   And there you go. Cool. Okay, so now I've tried  it again, with the job that we got back before,   which has a long expiration, it's got a 24  hour expiration on it, so it's not going to   go anywhere, and it's returning to us the contents  of that person's cart. That's a pretty good start,   we're doing great. So now the next thing we  need to do is have a method where you can post   to the endpoint and add an item to the  cart, and then also a delete and delete   an item from the cart results go back in here.  And so we're going to create a post method.   And we need to bring in post from our next js.  And that's great, you're learning full stack at   the same time that you're learning about all this  microfi stuff. So there's so many good things to   learn here about Jonathan occation, and all the  rest of it. Okay, so we have a now post method,   same idea. So you just post to that same endpoint,  again, it's going to be off guarded with the Jot,   I'm going to get that request that's coming  in before but this time, we're gonna say that   our body contains an ID, and that's the ID  of the product that we're wanting to add.   And then it's going to return the new cart, the  updated cart. So first, we need to get your cart.   And we use the same thing we did here with this  carts and give it the user ID. And then we need   to see if you already have an item in your cart,  because we're just going to update the quantity.   If you have that item. Otherwise, we're  gonna add a new item to your cart.   So we have a cart item, we're just  going to add update the quantity.   Otherwise, we are going to add on to  your cart items by pushing the product   and then a quantity one. Right, cool. And  then we're just gonna return that cart.   Easy peasy lemon squeezy. And the  next thing we need to allow is the   removal of the cart. And for this, I have  personally decided to use the delete method   on that, you know, is that the right thing  to do? I don't know. I mean, that's really   up to you. But I'm going to just use delete for  that. And again, it's going to be off guarded.   Because we need one to know these already. And  of course, we want everybody's car to remain   their own and secure. And all we're going to do is  just basically if you get a delete on an endpoint,   we're going to look to get the user ID, and we're  going to set the card to an empty card and return   it just like that. Okay, we're pretty good. So  I think our cart functionality is going great.   So now the next thing we need to do is actually  have a cart app, the third app here to connect   this to. So I'm gonna go back over into our  terminal. And I'm just going to reuse this   terminal even playing around with to do another  one of these PNP axes, would that create MF app.   And I'm going to call this one  cart. And it's also going to be   a React app. So I'm gonna call this one cart. It's  going to be an application that sits on port 3002.   And it's my react JavaScript and tailwind.  And we can talk a little bit about why I'm not   using create react app or next year. As for this  obvious, I'm using React. So why am I not using   one of those? Well create react app, and next have  very complex setups, everything's in there with   a really complex Webpack configuration, and es  lint and testing, and prettier and all the rest   of it. And that's great. It's a great starting  point. But it's a lot of extra clutter and bloat,   that distracts from what I want to do with create  MFM, which is give you a way to make proof of   concept and test applications. So you can test out  how model Federation and my graphes are going to   work in your environment without actually going  and making all the adjustments to those things   yourself. So each one of the apps that it creates  is the smallest possible thing that I can think   of, it's basically just Webpack, and X Webpack,  and react Webpack and view Webpack, and lid,   Webpack. And all of the different, there's 10  different templates that you can use. So, you   know, it's very, very simple and lightweight, and  it's all there for you to try and play with. Okay,   so it looks like we've installed properly. So  the next thing I'm going to add to our client,   is I'm gonna add RX js, what is RJs? And why  am I adding it. So RSDs is a set of reactive   objects and functions, it's a very elaborate  system for creating observable streams. So   in our case, we're just gonna use it really  simply, we're going to create a behavior subject,   which is a type of observable, that's going  to hold our jot, our JDBC, or JSON web token,   and another one that's going to hold our cart. And  the nice thing about it is you can always get the   current value, and you can subscribe to it so that  when it changes, you get to see it. And the other   nice thing about RX js is it's not bound to any  view framework. So we are going to use a different   view framework here pretty soon coming up. And  if I'd chosen something that was bound to react,   then that would be a problem. Whereas  in this case, anything that can run a   subscribe method on an object is going to be  able to listen to the job and be able to listen   to the cart. And that means it could be anything  could be vanilla JS could be solid, it could be   Inferno, it could be all kinds  of different things. So okay,   so looks like we're good. We've added our  RX js. So now I'm going to start up our app.   Okay, great. So just like we had before, very  simple vanilla startup with the tailwind stuff,   and makes it easy to put some nice styling  on it. Okay, so we're gonna go over here   to our cart into a source and migrate a new  file, and it's gonna be called cart.js. And   this is going to manage in much the same way that  products manage our connection to the products   portion of the server, this is going to manage our  connection to the cart and authentication side of   the server. So we're going to bring in RX J. S,  we're going to give ourselves that constant API   servers can point to the API server, and  we're going to create that behavior subject   for the data t. So that's going to have, if I do  j dt dot value, it's going to tell me what the   current value of that jot is, which in this case,  you can be null. And if I do subscribe, on this,   and I put in their token or something like that,  and I say, you know, console dot log token,   it's going to get called every time that a new  value goes into John. And the way that a new value   goes in there is you say Do do T dot next, and you  give it the new value, like that. So it's a pretty   simple API service here, you do next, to give it  to publish a value to give it a new value, you do   subscribe to listen to changes, and then you can  do value at any time to get the current value. So   very, very simple way of sharing state now, on my  channel, in my module Federation playlist, there's   coverage of Redux and a whole bunch of different  state managers when it comes to doing this with   model Federation. But I want to keep it really  simple. And this one, so it's RX js. So what's   the first thing we need to do? Well, we need to  go and login. So let's go and bring in our login.   And our login is going to take a username  and a password, it's going to do a fetch   a little bit more elaborate this time, because  it's gonna post as opposed to get it's got some   headers, and it's going to need to send along the  username and the password. And then it's going   to get back the response, we're gonna assume that  it's okay, I'm not gonna do any, any error routes   on this, but of course, you wouldn't need to. And  then that JDT that next is what I'm going to call   when I get back the access token from the payload  because we saw when the curls ourselves that the   access token is the key that we get back from the  server that has that jot in it. Okay, so let's   start building out our UI. We're going to actually  go and login at this point. So let's go and close   this out. And I'm going to go over to our web  pack config. And of course, we need the header   and the footer. And for this one, I'm just  going to add all of these apps together.   So I'm going to have a route for home, I'm going  to have a route for PDP, and I'm going to have a   route for myself. So I can be self referential  on cart. So if I internally use cart slash,   it's just going to loop back onto myself.  And module Federation happily supports that.   So the next thing we need to do is  create a new file called cart content,   dot JSX. And into that, I'm going to create  a cart content, it's gonna be a similar thing   to what we had before. So it's going to have  some state that's gonna have that token on it.   And we're going to do that login. But before you  get there, let's go make sure that that actually   works. So I'm gonna bring in the header and the  footer from home, I'm gonna bring in our content.   And then I'm just going to place our body content  with pretty much the same thing as we've had in   all the other apps, which is the wrapper, and  then the header and the footer, and then our cart   content. Alright, so let's take a look at what it  looks like. And it looks like we're blown up. And   that's because we can't resolve home header. So  what's the solution? Give me there, a solution is   going to be that we need to restart our web  pack, right, so we didn't repack, we didn't   restart web pack. And that's why I can't resolve  that. So let's go and do yarn, start again.   And I'll refresh. And we're good.  And jadibooti is currently empty,   because we haven't actually tried to login yet.  So let's go and login and see we get. So let's   go and bring in the login and the JDI T from cart.  And then down here in the US effect I'm going to   try to log in. But I'm also going to subscribe to  that job. And that, again, that's going to take   that value. And it's going to set that token  to that value or if the value is undefined to   nothing. And the cool thing here about subscribe  in RCS is that it returns an unsubscribe. How cool   is that? And it just so happens, the use effect  is expecting that we return a cleanup function,   and it just happily maps to the unsubscribe that  we get back from the job like that. Cool. Okay,   so let's try it out and see what we get. Hey,  there you go. Okay, so we're successfully   doing the login. Let's go and actually test that  and see if it works over in our network panel.   And we can look at our fetch, and we can see that  we have a login. And we are sending the Sally 123   payload. And we are getting back the response of  the access token looks pretty good. And of course,   we're seeing it over in the code over there. So  thumbs up, good to go. So now we're going to do   is we're going to build out the UI that's going  to go into the header over here, it's not gonna   go there yet, we're gonna go and build those  kind of locally within cart. And we're gonna   share those out with the header, the homepage team  that's manages that header, and then they're going   to consume those and put those in the header.  And it's all going to turn into one nice,   complete system. So to make it nice, I'm going to  go and add some icons. So we need going to add in   remix icons, that's what I'm going to use for  these applications. And I'm actually adding   to all of them. So I'm going to stop this guy,  and I'm gonna yarn add remix icon to that one.   I'm gonna grab that. And then I'm going to go  over to homepage, and I'm gonna do the same thing   there, I'm going to go to a PDP, I'm going to do  the same thing there. And the reason I'm doing   it on this side is that CSS is not something you  can share across module Federation, it has to be   either CSS and JS or J S. So that's not the  case in either of these cases, I don't think.   So. This is, so I need to add that dependency to   all of these applications. So next  thing to do is restart everything.   Alright, look, I'm pretty good. We  got a homepage, you got a cart page.   That's good enough for now. And the  next thing we need to do is make sure   that you have the icons in every place,  I'm going to go to the app dot JSX file   in all of our applications and add the CSS for  the remix icons. So back over here in again.   And again, okay, cool. Now we have nice  icons we can use in any application.   So let's start building out our login UI. And  one thing we're gonna do is we're going to   share a custom hook around us logged in so we can  build that now. So we got our cart file in cart,   dot j s, and I'm going to bring in React. And  then down here, I'm going to define that we have a   user logged in, and it's going  to return that login state.   And then it's going to set up a  subscription using us effect to that job.   So first is going to set the value of login  to whatever the current value is of that job.   And this little nice double exclamation point,  basically coerces it into a Boolean. And then   I'll do the exact same thing I did with a  subscribe over here. And there you go. Okay,   so let's go back over to our cart content. And  I'm actually going to remove this auto login,   because we don't want it to automatically  login, because the first thing we're gonna build   is our login screen. So when I remove that,  and then I'm going to go over here and create   a new file, we're gonna call this login  dot JSX. And we're going to bring in you   state and that login and the US login from our  cart. And then we're gonna create our login.   And we're gonna start off by getting the  login state, and already managed some state   around whether we want to show or hide this  little pop up there, we're going to create   the need some state manager username and  login. So we create some state for that. So   got username and set username, password, and set  password as you generally do in these situations,   I'm going to say if we're not logged  in, then we're going to return no,   don't show anything. But if we are logged in,  we are going to show a fragment. So we're going   to start off with a little fingerprint icon,  that's where you click on it to go and fire up   your login. And that's going to be a span that has  within it a icon to assume reasoning I the italic   tag to make become an icon as we always do. And  I'm going to add a ID here, because we're gonna   do some test automation, at the end of this show  you how to test this really cool stuff. And then   if we click on that, we're going to get on the set  that show login, so we can hide and show something   we're gonna have like a drop down. And so the  drop down is going to switch based on show login.   And it's, this is gonna be basically  kind of relative positioned. So you know,   eventually we'll move it into the right spot. But  this is for testing, we don't want off the side of   the screen some comment this out currently. And  then we need an input for our username. So I'm   gonna pop that in there, that input is going to  have a type of text and a placeholder username,   it's gonna have a value of username, and then  when it changes, it's gonna set the username is   absolutely regular react type stuff,  and it's gonna have some nice looking   tailwind on it to make it look pretty. We do  the same thing for password, then this case,   we're gonna give it a type a password, the  value, password and also set password. And again,   make it nice and pretty tailwind style. And  then finally, we're going to have a button,   that's going to be our login button, and also an  ID on that so that we can automate it later. And   that's just going to call login with the username  password, the same login that we have here from   cart. So let's take a look and give this a try.  So the next thing we need to do is important login   into our cart content. And  let's try that out log in from   login. And let's put it in there. So  I'm going to put a div around the John   for them and drop that login in  there since I got in the pace buffer.   Cool. Let's take a look. Oh, okay. Okay. All  right. So I need to say if I'm logged in,   then return null. Here we go. Okay, cool. So  looking good. Because I don't know that is there,   because I should remove that use effect from  before. So let's go and figure that out. So   I'm going to go and rebuild that use effect  that we have before to go and set the token.   But I'm not going to auto login. So now let's  login. And yeah, cool. So we know we're good.   We got the govt and that's great.  Okay, so next thing we need to do   is build out that little mini cart. So when  I'm not showing the login, that means I am   logged in. And I want to show a little cart icon  that shows me the number of items in the cart,   and brings up a little pop up that gives you some  details about what's in the cart and allows you to   check out and clear the cart and all that kind of  good stuff. But to build that we need to add more   stuff to our cart, we need to manage the cart much  the same way actually do the job. So I'm going   to go and create a new behavior subject for the  cart. And then we're going to add some functions   to get the cart and add an item to a cart  and clear the cart. So let's start off with   getting that cart. So we have a function  here, get cart, and it does a fetch just   super straight get from the cart, just the way  we did before. And again, application JSON,   but this time we're adding in that bearer, so  that'd be the bearer token with a dot value. And   that's going to first offset the value of the card  by using cart dot next. So it's again a behavior   subject like we had with Jaat and then it's going  to turn the contents of the cart as well. So if   you want to get it that way, that's fine too.  Kind of nice, nice dual purpose. function there.   Of course, now we want to go and enable this  get cart down here. So once we've logged in,   we want to automatically go and get your cart and  make sure that that's up to date. But of course,   we want to make some money. So let's figure  out how to add an item to a cart. And   that just takes an ID. And in this case, xoma is  exactly the same thing, we're going to do a post   in this case, because that was the route that  we created on the server side was a post. And   then into that we give it the ID, but it also  takes the same bearer token as we had before.   That gives it its shot. And that gives your your  identity. So then we take the return value, which   is just a response, we get the JSON out of it, and  we're successful. So we want to go back and get   a new cart, you know, we could take the value  that we got returned, now it'd be the card, but   it's fine, we can just make two requests. And  then finally, we need to do exactly the same thing   one more time for clear cart. So again, same  idea, but in this case, we're going to use a   delete method, as opposed to the POST method. And  again, we're just going to go and get the cart.   So now we got a basic set of functions that  allow us to manage a cart, let's go put a UI   on it by creating something called the mini cart.   So we'll bring in our usual react use effect,  and you state all that good hook stuff. And we're   going to bring in our cart stuff. So in this case,  that cart is going to be our subscribable value,   as well as the clear cart function they're going  to need to use when they click on that, clear the   cart button or really check out to yeah, whatever.  And then we're going to get currency, which is   going to format currency, but we're going to get  that from home. So we're going to use that module   Federation stuff to pull in currency dynamically  from home. Okay, so let's start building out   our minicard. So, we'll start off by having our  list of items. And we'll get that from our cart.   And we'll have a flag for showing and hiding  that cart because it's going to have that little   icon there and you click on the icon, see,  then the carton, click on the icon again,   goodbye, cart. And so we need to subscribe to  that cart. So I'm going to use use effect in   here. Of course, you could go and wrap that in  a custom hook if you wanted to. But this one is   just gonna do the same thing as we have before. So  it's going to go and get the cart items, and then   subscribe. This little nice optional chaining here  allows us to say, Well, if the cart value is no,   then don't dereference that to cart items. So  it protects us from the value of CART being No,   in the beginning, really nice. Of course,  we don't have any cards that we want to say   nothing. So let's start returning out our JSX. And  again, we're gonna do a fragment, because we're   gonna have that icon and then we're going to have  the content. So we'll start off with our icon.   And we'll have that unclick, they're just  going to show and hide that cart state,   it's going to have an ID on it. Because again,  we're going to do the automation stuff, it's going   to have a shopping cart icon as opposed to the  fingerprint. And it's going to have next to it the   length of items in the cart. So that's just gonna  tell you how many items you've got in that cart.   You know, this actually sounds like a good spot  to try it out. So I'm going to go over here to   cart content. So I'm going to go and import mini  cart from the mini cart file, and then I'm going   to go and use that down here mini cart. And let's  see how we do. Okay, cool. So we're not logged in,   it's not persisted like that. So I  need to log in. And there we go. So   Sally has three items in the cart. Awesome. And if  we try again, and we use Maria, in here, Maria has   two items in the cart, though. Thank you Chrome.  I'm good. Okay, so it looks like our cart icon   is doing well. And we got the cart count going. So  thumbs up to that. So let's continue on, and allow   us to show and hide the detail of what's actually  in the cart. So I'll go and create a show card.   Again, here, we're gonna have a kind of pop  up thing, this is gonna be in a fragment.   And we're gonna have a four column  layout. Because we want the quantity,   the image, the name and the price, that's gonna be  the four columns. And then we're going to iterate   through all those. So use a map for that. So for  the items, I'm going to take each item, create   yet another fragment. And the reason for that  is because of grid layout, you want these to be   at the same level, all with each other. So that's  why the rack rack fragment in there, but we need   the ID. So that's why it's react fragment and  not the React fragment placeholder. And then the   quantity, the image, the name and the currency.  That's unformatted. So let's go take a look.   Alright, again, we'll log in Sally  cool. And there you go. Nice. Okay,   so Sally has a dragon wheel spinner wheel spinner.  Gentlemen, spinner. Very cool. Alright, so of   course he wants to know what the grand total is,  how much money am I spending? So we're gonna add   some more we're gonna go and add Three placeholder  divs, and then essentially the grand total. And   to get the grand total, we're going to give it  a reduced function, which is going to take the   current reduce value, which is gonna start  at zero, and then add on every round the   quantity times the price. So let's try that  out and see how we do for the grand total.   Yeah, looking good, okay, which apparently she  owes us. 20 bucks for Three Spinners. Okay,   cool. So now we need a clear button and a checkout  button. So to wrap those, create a flex box.   And then within that, our first side of the  Flexbox is going to have our Grow div on it. And   in there, we're gonna have our clear cart. So and  again, we're gonna have that on an ID. So we can   automate that. And this is gonna it's gonna  have some nice tailwind formatting here,   I think we're just going to put a border on that  one, let's go take a look. Yeah, that's kind of   nice. I like that. And we can actually clear the  cart at that point. And now if I log in, again,   we can see Sally has nothing in the cart. That's  cool. That means that our server is persisting   the state of the cart properly. Awesome. If we  wanted to go and reset this car, we just need to   reboot that server because it's all in memory.  Okay, so now we need to put at the end of this,   we need to put our checkout button which is  basically gonna do the same thing. You know,   if you want to make a full ecommerce system out  of this, then I guess you'd go to Shopify or   whatever. Okay. So it save there. And then let's  try one more time. And it looks like we're good.   You know, obviously, don't have the cart there,  because I cleared it the first time, but I think I   think we're okay. Alright, so now the next thing  we want to do is integrate this back into the   header, so that we get a coherent experience for  the customer. And we get that shared experience   on every single page. So really cool. So the next  thing we need to do is go back over into our web   pack config. So let me close out a few of these  files. And we'll zoom in on that web pack config.   That's part of the cart, right. And so now the  cart needs to expose a couple things, it needs   to expose the cart functions that it had before  so that I can subscribe to the Jaunt and the cart.   And these two, expose the UI components that are  the login and the mini cart. So cool, or exposing   kind of both functions and microfi components  here. So now we will reboot our cart server.   And I'm going to copy these because I need really  all of the applications now to be pointing each   other. So go over to home and change the Webpack  config there so that now home can look at itself.   It can look at PDP and it can look at cart. And  PDP is also going to have the same things. I might   as well just replace it all in one, one fell  swoop. And let's see, so I'm going to reboot   home. And I'm going to reboot PDP I made changes  to both of those as well. Okay, cool. Yeah,   the only hassle about all this is really the fact  that the browser just keeps popping up every time.   But otherwise, it's a really nice workflow. Okay,  so let's go back up to home, because now we want   to bring in those microfiche from the cart, and  embed that in the header. So let's bring in mini   cart and login from cart. And let's make sure  that it works by going over here to home. And   as long as things don't blow up, you're generally  speaking Okay. And now I'm going to wrap this one   in a Flexbox. So I'm gonna wrap the content here  in a flex box. And the first item in that flex box   is going to be our our home title or title of our  app. And then I'm going to have a flex end item   which is going to have our  mini cart and our login in it.   I don't think it matters, the ordering.  They're pretty sure it doesn't matter.   So let's try it out. Hey, okay, cool. And now  we'll log in. And looks great. Oh, cool back.   And it's so awesome. I love it. Okay, great. So  let's change the CSS a little bit so that we can   make it look pretty. So I'm going to go back over  here to our cart and our login let's see mini   cart. And there was a little bit of justification  that I got rid of there the left and the cart.   Login. Yeah, that looks good. Bring in the  left. You know, I don't like like to make   things look nice. So here we go. So ups. I think  it's no problem. Okay, so it's over there. Now.   Let's go and go back over to our  header and make sure this is relative.   Oh, look at that. So nice. Okay, awesome. So now  we need to be able to add items to the cart, right   of course. So we're going to use that add to cart  function Over here in our homepage content to give   us some a way to add items to the cart. And that  John function and that use login to let us know   if we want to show those add cart ones because we  are logged in at this point, we should be able to   add items to the cart. So let's go over back into  our content for home content. We're gonna bring   in some stuff from the cart, we're gonna bring  in add to cart and also that use login hook.   And I'll use us login. And we're going to use  that to toggle whether we're going to show   our Add to Cart buttons. Okay, so down here below  description, we're going to check to see if we're   logged in. And if we are, then we are going to  align on the right hand side, a little padding   on the top, a nice little button, we're going  to add some automation ID to that so that we   can automate it later, where you can add to the  cart. Alright, let's refresh the page. And we're   not logged in. So let's login. And oh my gosh,  okay, cool. I'm gonna add the cards. Haha. Oh,   yes. All right, here we go. And look at that.  And so now check it out. We are sharing state,   we're sharing the John state. So the host page  in this case, which has that home content,   is looking at the job and seeing whether it's  logged in or not, and showing these buttons. And   then when it needs add item to the cart then calls  the add to cart function, which then fires off to   the server, and then updates again, that RSDs,  which then updates that view. So in fact, check   this out, this is even cooler, I can go over here  to Rainbow flames. And it automatically updates.   So the whole thing is reactive, because you have  that RX JS subscribe mechanism. So whatever state   manager you choose, I strongly recommend that you  make sure that it's reactive somehow. And that,   you know, all of them are really at some level,  but things like mob X, and Val Shio, Jo time,   these are all very reactive mechanisms. Of  course, redox reacts a bit more elaborate,   I would recommend using Redux toolkit if you're  gonna do that. But they all work, which is really   important part, because context also works. I'm  not going to do that here. But context does work   in these systems. Okay, so of course, our car page  is ugly. So we want to make sure that we have a   complete cart page. So let's go back over into  our cart and update our cart content. Alright,   so starting from the top here, I don't need any  of that anymore, I'm going to bring in cart and   clear cart from the car, we're basically going to  redo the mini cart, but just kind of writ large,   I mean, create some state around the items  and have a use effect where we subscribe   to that value. And of course, I'm going to use  that nice optional chaining on there to make   sure that we have card items. And if we don't,  then we have an empty array, which allows us   to safely render an array map. All right, then  down in here, I'm going to start with a fragment.   And into that, I'm going to use the top of the  page to be a grid of all of the cart items,   and it's gonna be a four column grid layout. I'm  not gonna adjust the sizes like I did before.   And then I'm gonna go over to my mini cart.  And I'm just gonna grab pretty much all of   this centrally, exactly the same thing. And drop  it in there. Cool. Let's take a look at our cart.   So we haven't logged in, let's go log in. And  ooh, and check it out. It's the same data.   I added that rainbow flames before  and there. How cool is that?   Okay, so looks like we need a little  bit of getting all my sun aligned.   Yeah, okay, good. And then we need to add the  buttons down here for clear cart and checkout.   So let's go back over here and make sure that if  we have some items that we can show that UI, we're   gonna start off again, with a Flexbox to allow  us to put one button on one side and one button   on the other side. And then you know, I'm just  going to go and grab clear cart stuff, because   that's basically exactly the same code. So let's  go over here. And let's see, is that the balance?   That's the balance. Yep. Okay, cool. And pop that  in there. And let's take a look. Okay, refresh.   Cool. Awesome. All right, and I can clear current.  Yep, I can. Hey, cool. All right. So let's go have   a look at product. I'm gonna go over here  to localhost 3001. And then do product ID,   you know, to sure whatever, solid rainbow I like  that one. It's it's solid, and rainbow. So what I   want to do is I want to show you how to do micro  RFPs, across different view platforms. So the way   I'm going to do that is I'm going to create an  Add to Cart button. It's going to go in here,   because one mule, the add to cart from the product  detail page, but for some reason or another,   the folks on the Add to Cart button team who  decided to use solid J S, which is a framework   I love by the way, so it's a cool choice to do the  Add to Cart button and not react. So the question   is can we get these two view frameworks react and  solid as to talk together. And I'm guessing the   fact that I'm talking to you right now is, the  answer is yes. So let's try this out. And this   is going to give us our fifth application  and our last tab. So let's go and create yet   the last terminal. And here, cart. And I'm going  to do again, P MPX. Create MF app. And this time,   I'm going to call it add to cart. And I'm  gonna pick application and we'll see 3003.   And we're gonna pick solid JS in this time.  And JavaScript and tailwind, don't worry,   if you don't know, solid J S, it's  fine. So we'll go into Add to Cart.   Very easy. If you're familiar with React,  actually, solid J S is very close to react. And   I think there's a lot of cool reasons to look into  it on its own. So something you might want to look   into on your own. Okay, so here we go. So we're  gonna yarn, start that up. And there we go. So   it's kind of similar layout, as we had with the  React stuff, except that the only difference here   is that the framework in this case is solid  J S, and not react. And that's actually the   way every single create MF app runs exactly the  same way and gives you the exact same output,   so that it's pretty easy to compare these  different frameworks. So now, of course,   this Add to Cart needs to be able to get access  to that shared jot and the add to cart function.   So we're going to go down here to the remotes,  and we're going to give it the remote of cart.   And I'm going to restart that server. And into  this directory, I'm going to create a new file   called Add to Cart dot JSX. And you define a  component in solid much the same way you do in   React. So in this case, it's just a function,  and it takes properties and returns some JSX.   Now, there are no classes in this case, that's  not something that solid yet supports. So it   has to be a function. So in solid J S, there's  a signal, which is the equivalent of a US state,   although it can be global, it can be  anywhere, it's actually really cool.   And then there's a an effect, same kind of  idea, but it's like use effect. And then you   have a declarative style when it comes to hiding  and showing stuff. And a tag to hide that tag to   show is called shows, we're gonna bring in those  from solid js. And then from module Federation,   and the cart, we're gonna bring in the  John, and we're gonna bring in add to cart,   then we're going to create a signal for login.  So looks really similar, right? I mean, this,   you could imagine that to be used eight,  but it's called Create signal, in this case,   a really cool thing about solid is that it's  gonna actually be out here, it's really just a   question of where you want to store your state.  And it works the same way in both cases. So you   when it comes to state managers, solid jazz, most  of that's actually built into the core of stage   of solid, so you don't need a custom state  manager really cool. So let them do a create   effect. And that's going to do that same jaunt  subscribe thing. And when the subscribe fires   telling us that we're logged in, then we set that  signal. And then for the JSX, we are going to   return a show hide tag, essentially, that has  within it a button. That button has the same   kind of tailwind stuff as we had on before. In  this case, when you click it, it's going to do   add to cart. So there you go, that is our the  complete sum total of our assala js component.   Okay, so let's go over here to app dot JSX.  And let's see how this is actually done. So   the way that you render something in solid J  S, as you bring in render from solid JS web,   and then you render the component. So in this  case, that's that app that we had before.   So if we wanted to bring in our component that we  could import that here, the only thing is we're   not bringing in a header, so we're not going to be  authenticated. So it'll be difficult to test. So   I'm not going to do that. But what we need to do  is basically get this somehow, so that it works in   a React context. So I'm going to do that I'm going  to create a function and expose that. And that   function is going to take two arguments. The first  is the element that you want to attach it to.   And then the second is the product ID, which  is going to go into ID here. So I'm gonna copy   and paste this and I'm going to create a  new file called place Add to Cart dot j s.   And we're not gonna bring in index dot  css, we're not gonna bring in this,   but we are going to export a default  function called please add to cart,   it's gonna take an element, it's gonna take  an ID and it's going to render into element.   And what it's going to render  is Add to cart with that ID.   Cool, right? Okay, so let's go  and expose this. So we'll go   back over to our web pack config And you  know what we'll just also expose Add to Cart.   And also, of course, place Add to Cart,  which is what we're really going to use.   That's J S. Let's see is that JS Dojo dojo? Yep,  it is cool. All right. So let's go here to add   to cart, and restart it because we need to  update that exposes and get everything going.   And I'll see that it's got  a remote entry on there.   And it does is going to tell us that we've  exposed the add to cart, and also the place   Add to Cart. So let's go back over to our PDP  app and import that. So go close out these files,   and go to PDP down to Webpack. Config.  And we're gonna bring in add to cart.   And it's called Add to Cart.  And it's on that remote entry   on 3003. Cool. So now let's go back over to our  PDP content page. And we're going to bring that in   and bring in place Add to Cart from Add to Cart.   And let's go make sure that I get the name right,  and the car went back big. There we go. Cool. And   we'll just refresh to make sure everything's fine.  But of course, you can't find Add to Cart and why?   Because we haven't restarted the server.  So let's go again to PDP and restart.   And we'll refresh. And looks good. So fingers  crossed, things look good. All signs point to   things being good. So we're going to do is going  to mount this on a ref. So we need an element.   So we need to create a ref by using use ref. And  we're going to put that well put that down here.   ref is add to card. And let's make sure that  that works. Yeah, seems to be going okay   doesn't have any problems with that. So let's  add a use effect. Where if we have a current   on Add to Cart, meaning that that component is  mounted, we have an unique element, then we're   going to do place add to cart with that current  element and then give it the ID. So is it save?   Okay, looks like we have an error. So let's go in  look at the console and see what that error is.   Go over here to console scroll up. And it looks  like I messed up in my solid jazz code. I just   forgot to import Add to Cart, my solid jazz.  So let's go save that. And go over here to   add to cart go into add place Add to Cart. Yep,  absolutely. So let's go and import Add to Cart.   can't really use something until you've imported  that Jack. So let's say save there and run and   we haven't logged in. So we're probably okay so  far. Cool. Got it. Yeah. That is so cool. How   awesome is that. So now we've got a React app  hosting a solid js component because that's the   what we decided to use for that particular one.  And let's see, do we make a good choice. Let's   take a look and see over our network. Take  a look at the size of the payloads here.   So wow, we're bringing a lot but see place  add to cart was 2.7 kilobytes, that's a,   that's pretty nice. We're bringing in not a  lot for bringing that add to cart. And that's   one of the really nice things about solid Jas  is actually creates very, very small bundles.   Alright, so coming up next, we are going to take  a look at how to do routing in micro front ends   and module Federation. But before we do that,  if you are a Git kind of person Source Code   Control being all that I strongly recommend at  this point to commit we currently have because   it's gonna get real here real fast. So we're gonna  do some pretty cool stuff to address an issue that   I want to talk about right now. So we've got  our three apps, we got one on 3001, we got one   on 3002 and one on 3001. So let's go put those  kind of in the right order, I guess 3000 3001   3002 Right. So let's say I want to go and test out  how my homepage connects to my cart as an example,   right? So I'm logged in here, and I'm adding  stuff to my cart. If I go over to 3002 right now,   and then I see that I'm not actually logged in  anymore because I'm not actually storing the state   and I'm getting a whole new page Refresh  is not actually a single page application.   So is there a way we can actually turn these apps  into a single coherent single page application.   And this is a big deal, because what happens  is, when you fracture one of these monolithic   applications into a set of smaller applications,  yes, they become a lot easier to deploy.   But first, you run into the Header  Footer problem that we had before. So   you have to be able to share components,  ie my graphes, like the header and footer   between applications. But also, they become harder  to test, right? If you want to do a coherent test,   where you start at the homepage, you add something  to the cart, you may navigate to another page,   eventually, you'll end up on the cart page  and go through checkout, right. In order to   get that done. You have to stage your whole system  somewhere and then put in your code for say, cart,   as an example. But keep all of the code for  the existing apps, and it just gets very hairy   and hard to manage. Whereas if you had all of  them as essentially single page applications,   where any of these applications could vend  all of the pages for the other experiences,   then, for example, if you're working on a cart,  and you want to make a change to the cart, but   you want to run a smoke test that ran through the  entire system, you could do that. Is it possible?   Yes, it is. So let's go check it out. And  that's what I'm saying. We're going to make some   pretty significant changes here, although we  have set ourselves up nicely for this. So in   each one of these applications, so cart, home and  PDP, we have implemented the interior of the app   as content. So there's cart content, there's  PDP content, and there's home content.   And it might have seemed a little bit weird in  the moment. But I had a plan like the Cylons. So,   over here, in Webpack, config, we're going to go  and expose cart content in the cart app. So I'm   going to put in here cart content. And then I'm  going to get that from cart content, dot JSX.   Say that out, and we will go and  restart cart. So we're exporting that.   And that seems to be okay. So that's good. So  now I'm going to do the same thing over in,   let's see what is next home.  Okay, so we've got home contents,   I'm gonna go to web pack config there, and  home is going to export the home content.   So I'll just replace our cart with home just like  that. And again, save and now go to home. And   I'll stop it and start it. Now that looks good,  great. And then finally, let's go over to PDP and   go to its web pack config. And again, we're  going to expose out of PDP, the PDP content.   And we'll go down to PDP and restart that one.   And that looks good. So here's an undo  I'm going to go over to the app for PDP.   Since it has React Router baked into it already,  and I am going to copy some of this code,   I'm gonna copy all of it actually. And I'm gonna  take it over to home. And then we create a new   file in here called main layout, that JSX paste  that in there. And we'll call this one main   layout. And we'll get rid of that react  render Dom, you don't need that anymore.   But what I do need now in home is React  Router DOM. And so we don't have that.   So let's go over to home here and stop that  server and then yarn, add React Router DOM.   And then I'm going to start that server again.   And now we start getting to the point where  we need content, right, so we have PDP content   from PDP. We've got home content from home.  And we've got cart content from the cart.   And now let's go take this main  layout, and then go over here to app.   I'm going to bring that in as the one  thing that we're going to bring in.   And you know, I'm just gonna render it right  here. We're not even going to have an app anymore.   Save that out and we're gonna see how  we go. This is basically a test to see   that all the connections are okay. Looks like we  haven't exported main layout. So let's go over and   to let's just go make this an exported function   and then return this router.   Okay, cool. And now at least we're getting a page.  And that's good. But we don't have a home path. So   we're going to add a route for the home. So I've  just be slash now we're going to put in exactly   in there. So it needs to be that exact path. And  that's going to be the home content. So let's save   that out. And refresh, and eight. That's pretty  cool. And if I do slash product, slash one,   how cool is that I'm actually getting the PDP  out of the same app. This is 3000. This is the   Home app, but it's serving the content for  PDP has really cool, okay, so one more than,   let's go and bring in cart. So I'm gonna do  slash cart. And we're gonna do cart content.   Okay, cool. Now, let me refresh.  And now I'm gonna do cart.   There you go. Awesome. Very cool. So it's not  quite a spa yet, because we still need to do the   linking component of it. So you so in order  to get our spawn app going, we need to use   link from React Router DOM. So let's go over  to the header and add the appropriate links.   So I'm going to paste in React Router  DOM, and I'm going to bring in link.   And I'm going to put a link around fidget  spinner world. And that's going to go to slash.   And let's see, I'm going to  add a little diviner there.   And then I'm going to go make another  link to cart. And we'll call that cart.   Let's take a look. Cool. And so they  click on card. So I click on this,   I go to the homepage, and I click on this, I go  to the cart, and even better, so I log in here.   I click on cart, the login is retained, it  is a full spa. Now how awesome is that? That   is really cool. Okay, so another thing I want  to do is just make sure that I have an ID here   for the cart. And that's just to make sure that  our automation works properly. But I'm gonna go   because I'm a little bit of a stickler here, I'm  just going to go and add a little bit of padding   and margin on the X around that. Just make  it nice. And that'd be a Flexbox. Yeah,   that looks good. Okay, cool. So now if we want  to click on one of these, right, we're going to   go and use a spa link to get to our product detail  page. So let's go and change our home content to   point at that product. So I'm going to go and link  in here to that lecture, it looks pretty good.   And is wrapped the product name in that, and  also going to do the same thing for the image.   So if I log in, and then I click on solid rainbow,  I'm still logged in, everything is great. So I   have a spa coherent spawn AV, across the app.  So that's awesome. And yes, that seemed fast,   right. But at the same time, we were pretty  much set up from the get go to allow for that.   So now let's answer one of the biggest questions  that I get when it comes to Module Federation.   And like Raffys, which is how to test this stuff.  And we'll start off by looking at unit testing.   So I'm going to close out all these files. And  what we're going to do is we're going to add a   test to the homepage that will require the card  information. So we will need a mock the cart.   So I'm going to first go to home. And then I'm  going to stop the server and I'm going to add   the testing library for React hooks because  we're going to basically create a hook that   depends on the cart count. And then I'm going  to set up the jest environment by creating a   new file called jest dot config dot j s. And I'm  going to say that our environment is the j s DOM.   So now we're going to go and create our use card  count. So create a new file, we'll call that use   cart count. And I'm going to bring in use a use  effect from react, I'm going to bring in the cart   as you would, and then I'm going to export  use cart count. And that's going to set up   some state that has the initial cart items length  in it. And then I'm going to return that count.   And in the meantime, I'm going to also do a use  effect with no dependency array. So it's only   going to run on startup. And then I'm going to  subscribe to the cart and get that cart items.   And then set the count to the length of those cart  items. So that's pretty simple one All I want is   the number of items in the cart. Pretty simple.  So how am I going to test this? So I'm going to   go and create a new file called use cart count dot  spec dot j s and I'm going to bring in the testing   library with React hooks. And it's going to allow  us to render a hook and then To call functions on   it if we want to, but we're going to use this  to basically trigger that subscribe. And then   we're going to bring in our hook. And then we're  going to create our first test. So we're going to   describe use car count. And we're going to say  that it should return a car count. And we're   going to just get the result from use car count.  And we're going to expect that to be zero, since   there's no cart currently, and we're going to mock  the cart count. So how are we going to do that?   Well, let's just do just mock and then give it  cart cart, which is what we're looking for over in   use card count. So is that going to work?  Let's give that a try. So let's do yarn jest.   And we see that it can't find that  module cart cart. So so the way that   we can trick it into believing that there's  that module is to create a new manual mock.   For the cart, so I'll create a folder called  mocks inside that a folder called cart.   And then within that a new file called cart  dot j s, where we will export a default,   essentially just an empty object. Let's give  it a try. And there you go, ran and passed.   So we're going to have another test  where we essentially bump the cart count.   So we'll add that in. So use that cart count hook.  And that's going to basically send us a callback,   in that use effect. And then we're going to call  that back and say that we have a new set of CART   items. So we need to store that callback  somewhere. So I'm going to put that up   here. And then I'm going to replace  this subscribe with a function that   takes a callback and then sets that callback  value. So let's try this, see if it works.   All right, two passes. Okay, cool. So that's unit  testing. So you can mock out these remote modules,   that's not a problem. So now let's talk about IE  testing. So the way that I'm going to do that is   I'm going to use Cypress. So the first thing I  need to do is add Cypress. And then I'm going   to open Cypress by doing yarn run Cypress open.  And so what it's done is it's gone over here, and   it's created a cypress directory, and in there,  there's a bunch of tests, we're gonna do all the   integration tests and all that sort of stuff, we  don't need any of that. So we're just going to   get rid of that. I'm going to create a new file in  here, and we're going to call it Ed spec dot j s.   And I'm going to describe my first EDI test. So  now we have to record a test. So I'm going to go   and create yet another terminal, where I'm going  to run home. So I'm going to jump back into home,   and yarn started. And I'm going to bring up the  Cypress recorder, which is a extension on Chrome,   and I'm gonna do start recording, then I'm going  to log in, then I'm going to show the cart,   I'm going to clear the cart, I'm going to  go and add an item to the cart. And then I'm   gonna go to the cart page. Now let's go take a  look at what our test has. Alright, that looks   pretty good. So I'm going to stop recording.  And I'm going to copy that to the clipboard   and go over here and I'm going to say  it should add an item to the cart.   Alright, so let's go over and look at our Cypress.   And I'm going to run our ED spec,  that's gonna bring up Chrome.   Alright, and it didn't contain that localhost.  I'm not sure why that happened. So I'm going to go   over and get rid of this. I don't think that's the  case anyway. So let's stop and then restart it.   Alright, looks pretty good. Okay, so now what we  want to do is we want to test to make sure that we   get this 599 value at the very end. So we're gonna  need an ID on that. So let's go back over to our   cart page and make sure that we have an ID on that  grand total. So good on the cart content. And I'll   scroll down here and we'll make sure that we need  an ID on this. All that grand underscore total.   Excellent. Okay, let's go take a look at this.  And research to be able to say see, why'd I get   get the grand total? And I'm going to say that  should Yep, contain and what was the number we   wanted again? 599. So let's take a look and  do 599 here and see if we get a passing test.   Awesome. light is green. And that's an end  to end test over multiple independently   deployed applications. That is just super cool.  All right, so let's talk about what to look for   next when it comes to learning module Federation  and my graphes and one area in particular I think   you should have a look at is single spa. So single  spa fits on top of module Federation. And it   gives you a way of making your components cross  platform. So as I did with place Add to Cart,   that's a pretty simple hacky way to do it single  spa does it the right way and actually goes   and wraps all of the different platforms and  wraps their components in kind of a uniform   parcel. And then you can deploy those using  either a system js or using module Federation,   which I think is very easy. And then you can  consume those in any other application. So you   could parcel up a view component and then reuse  it in a React component. It makes it super simple.   Another thing I think you should keep an eye on is  bit. This is a company that has been doing micro   Fe slash share component work for a long time.  And they've been looking at auto Federation.   So there might be some interesting synergy is  going on there. So definitely keep an eye out   for my graffitis when it comes to bit. And then  I often get asked, like, have you actually seen   this in the wild yet, and a friend of mine was  working over at Lowe's. And they've actually used   the model Federation and Mike Griffeys to create  this really cool paint finder. So they've got a,   an app, and they embedded this paint finder in  it. And now these two things are independently   deployable, which is really really cool. So it is  out there in the wild and that's great. All right,   well, I hope you enjoyed this look into Microsoft  fees and you got a lot out of it. Be sure to put   any questions you have in the comment  section down below. And of course,   hit that like button if you liked the video.  Alright, enjoy your future in my graphes
Info
Channel: freeCodeCamp.org
Views: 116,681
Rating: undefined out of 5
Keywords: solidjs, reactjs, react, frontend development, web development, tutorial, course, beginners
Id: lKKsjpH09dU
Channel Id: undefined
Length: 116min 43sec (7003 seconds)
Published: Wed Nov 10 2021
Related Videos
Note
Please note that this website is currently a work in progress! Lots of interesting data and statistics to come.