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