‫We've talked a lot about optimizing
‫wasted renders and overall app performance.
‫However, probably the most important thing
‫that we can and should optimize is the bundle size.
‫And so let's now learn how to do that.
‫But before we go check out the code,
‫we first need to understand what that bundle actually is.
‫And let's start at the very beginning.
‫So whenever some user navigates to our application,
‫they're basically visiting a website
‫that is hosted on some server, right?
‫So that's just how every single website
‫and web application work.
‫Now, once the user actually navigates to the app,
‫the server will send back a huge JavaScript file
‫to the client that is requesting it.
‫And this file is the bundle.
‫So the bundle is simply a JavaScript file
‫that contains the entire code of the application.
‫And it is called a bundle because a tool
‫like Vite or Webpack has bundled all our development files
‫into one huge bundle which, again,
‫contains all the application code.
‫This means that once the code has been downloaded,
‫the entire React application is loaded at once,
‫which essentially turns it into a single-page application
‫that is running entirely on the client.
‫So whenever the URL changes in the app,
‫the client just renders a new React component
‫but without loading any new files from the server
‫because all the JavaScript code is already there
‫in the bundle.
‫Now, the bundle size is of course the amount
‫of JavaScript code that every single user needs to download
‫in order to start using the application.
‫So if the bundle has, for example, 500 kilobytes,
‫then all those bytes need to be downloaded
‫before the app even starts working.
‫And of course, the bigger the bundle,
‫the longer it's gonna take to download
‫which can become a huge problem.
‫Therefore, bundle size is probably
‫the most important thing that we need to optimize.
‫And thankfully for us and for our users,
‫it's not very hard to do.
‫So we can just use a technique called code splitting.
‫And code splitting basically takes the bundle
‫and, as the name says, splits it into multiple parts.
‫So instead of just having one huge JavaScript file,
‫we will have multiple smaller files
‫which can then be downloaded over time
‫as they become necessary for the application.
‫And this process of loading code sequentially
‫is called lazy loading.
‫And this really is one of the biggest performance gains
‫that you can achieve for your users.
‫And so let me now show you how it's done in practice.
‫Now, there are many ways in which we can split the bundle,
‫so in which we can lazily load our components.
‫But the most common one is to split the bundle
‫at the route level or, in other words, at the page level.
‫So basically what we're gonna do is to take
‫all the components that represent a page
‫and load each of them separately, okay?
‫So again, that's what most applications do,
‫but of course we don't have to do it this way
‫because this feature that I'm about to tell you
‫and to show you has really nothing to do with React Router.
‫So any component can be lazy loaded
‫in the way that I'm gonna show you.
‫So let's actually do that.
‫First, let's remove these imports from here
‫and place them here.
‫And so now let's first identify our pages.
‫So it's the Homepage, the Product, the Pricing, the Login,
‫then here the application itself, which is an AppLayout.
‫And finally, PageNotFound.
‫So those are our six pages.
‫So that are basically these six right here.
‫And so let's comment them out.
‫And again, we will now lazy load these.
‫So instead of writing import, let's now write just the name
‫of the component, for example, Homepage.
‫And then we use React's lazy function.
‫And you see here it has been successfully imported
‫from React.
‫Let's just place that at the top where I like it most.
‫So this lazy function here is actually a feature
‫that is built into React.
‫And then Vite or Webpack, they will automatically split
‫the bundle when they see this lazy function.
‫Alright, now actually thinking of these bundlers,
‫I had the idea that I should even show you
‫how the bundle looks like right now
‫before we do any of this.
‫So let's for a second just bring this back.
‫So just that everything works the same way as before.
‫And then here I want to open up a new terminal.
‫So again, in our project folder,
‫and then here let's run npm run build,
‫which will then create our JavaScript bundle.
‫And so we can then take this bundle
‫and actually deploy it on a web server.
‫So a bit later in the course when I show you deployment,
‫this is how we will export
‫basically our final application for production.
‫But anyway, we see here
‫that we just have this one huge JavaScript bundle.
‫So it's this almost 600 kilobytes.
‫And so Vite even warns us here
‫that some chunks are really large
‫and that we should use this dynamic import.
‫So that's exactly what we're gonna do next.
‫So for now, I just want, just for the fun of it,
‫copy these two lines and paste them here as comments,
‫just so that we can later compare
‫what we get after the lazy loading.
‫So let's clean this, make it a bit smaller,
‫and then let's actually implement the lazy loading.
‫And so in here, we now need a callback function
‫which will then call the dynamic import function
‫which is actually part of JavaScript.
‫And so here we then need again the path
‫to the component itself.
‫So pages/Homepage.
‫And here we actually need these
‫to come before the dynamic imports.
‫So just like this.
‫And of course, we still have some errors
‫because now all of these are not defined.
‫So I'm just gonna duplicate this a few times now
‫and then implement all of them.
‫So the Product, we have our Pricing page,
‫again with the capital P.
‫Then we have our Login,
‫we have the AppLayout,
‫and we have finally PageNotFound.
‫Okay, that should be it.
‫Let's reload this at the root.
‫And for now, everything is working fine,
‫but this is actually not yet the end of the story.
‫So this is only the first part.
‫But now we also want to display a loading spinner
‫while we go from one page to the other one.
‫So basically, while these pages are gonna be loaded
‫in the background.
‫Now here I see I have a problem,
‫so it needs to be like this.
‫But anyway, this is now where the React's Suspense API
‫comes into play for the first time.
‫So I've mentioned the Suspense API a few times already,
‫I believe, but now we're actually gonna use it
‫for the very first time.
‫So I will not go really deep into what it is right now
‫because I will leave that for some later point.
‫But for now, what you need to know is that Suspense
‫is a concurrent feature that is part of modern React,
‫and that allows certain components to suspend,
‫which basically means that it allows them to wait
‫for something to happen.
‫And in our case right here,
‫basically these lazy components are gonna be suspended
‫while they're loading.
‫And so we can then use the built-in Suspense component
‫to show a fallback, which, in our case,
‫is gonna be that loading indicator that I just mentioned.
‫So let's come here into our tree,
‫and above the routes, let's then include Suspense.
‫So making sure that component has been included from React.
‫And then here is where we specify the fallback prop.
‫So here, this then takes a React element,
‫which is going to be our full page spinner component.
‫So we have here the regular spinner,
‫and we also have a SpinnerFullPage,
‫which is basically just a spinner but inside one element
‫that takes up the entire page.
‫So SpinnerFullPage.
‫So it looks like we're gonna have to manually import that,
‫but that's no problem.
‫So we open the Suspense,
‫and then we need to close it here after the Routes.
‫Okay, now let's then import this spinner
‫from SpinnerFullPage.
‫And with this, we should be good to go.
‫So let's just very shortly recap here
‫before we actually try this out.
‫So here with this lazy loading, we will now load
‫each of these components here as we need them,
‫which will basically automatically split
‫our bundle into separate chunks.
‫And it is Vite, in our case here,
‫that's gonna take care of that.
‫And so then, of course, there will be a time
‫while we navigate from one page to the other
‫where that chunk has not been downloaded yet.
‫So for example, if we go to Login,
‫then that page has not been downloaded.
‫And so then this entire thing,
‫so this lazy functionality is powered by the Suspense API.
‫And so that will make the component basically suspended
‫in the meantime which will then display
‫this loading spinner.
‫And then once that has arrived,
‫it will no longer be suspended.
‫And then the content here, so the children of the Suspense,
‫is gonna be displayed, so it's gonna be rendered.
‫So let's see if that works.
‫And let's actually do some throttling here
‫like a Slow 3G so that we can actually see this happening.
‫So let's click on Pricing.
‫Let's even clear our network requests.
‫And it is working, so it's now loading that chunk.
‫And so now that arrived, and so now the page has loaded.
‫And you see that some additional kilobytes
‫were transferred in the meantime.
‫And the same thing is gonna happen with the Product page
‫and with all the other pages.
‫But of course, if I go back now,
‫then that chunk has already been loaded before,
‫and so it's not gonna be loaded again.
‫So it will nicely be integrated into the application
‫that we already have.
‫All right, so let's load up our next page,
‫and it looks already slow,
‫but that's just because we have
‫this throttling here activated.
‫So loading now the next thing,
‫a store app layout, which is the main part of the app,
‫and so that's why that takes a bit longer.
‫Okay, great.
‫And of course, now if we go back, so the second time,
‫everything is gonna work really fluidly.
‫Beautiful.
‫So this really is the most important feature, I would say,
‫that we should always implement
‫in any React application that we're building.
‫And now to finish, let's just see the actual chunks
‫that Vite has created for us.
‫So npm run build.
‫So these chunks here are not gonna be exactly the same ones
‫as in development, because in development,
‫everything is a bit different.
‫So this year is already optimized for production.
‫And so we see that it all is very different.
‫So we have lots of different chunks now here
‫which are then all lazy loaded.
‫So you see that we still have a huge one right here,
‫but probably all of them added together
‫will be these 572 kilobytes.
‫Alright, so this 415 is not a lot less
‫than this one, but that's already good enough.
‫So we could now try to lazy load some other components here.
‫So remember that it doesn't only work with routes,
‫but I think that this is good enough.
‫So for example, the AppLayout itself
‫was apparently 156 kilobytes.
‫And so it's really nice that we got that
‫out of the main bundle.
‫And notice how even the CSS is also split
‫into multiple parts.
‫All right, so really nice feature.
‫And yeah, again, powered by both the bundler,
‫so Vite or Webpack,
‫and the lazy function provided by React
‫plus the import function provided by JavaScript,
‫and then also this Suspense component.
‫So hopefully you found this easy enough
‫that you're going to implement this
‫in all your future applications.
‫And with this, we have now actually finally
‫really completed this WorldWise application.
‫So this was the last video in which we worked
‫on this project.
‫And so once again, congratulations for finishing
‫this big project where we learned so many new things
‫and covered so much ground.
‫So I hope that you liked it
‫and that I see you for another small project
‫with which we will finish this section.