Check out a free preview of the full JavaScript Design Patterns for Web Apps course
The "Lazy Loading JavaScript Components" Lesson is part of the full, JavaScript Design Patterns for Web Apps course featured in this preview video. Here's what you'd learn in this lesson:
Max implements a lazy loading design pattern, which solves performance and memory usage issues related to loading too many JavaScript files when the app loads. Replacing the static imports with dynamic imports allows the scripts to be downloaded when needed.
Transcript from the "Lazy Loading JavaScript Components" Lesson
[00:00:00]
>> Maximiliano Firtman: Let's talk a little bit about, well, it's doing web components. So for example, right now, if I analyze the content, I have a main, and inside the main, I'm right now in an order page. Can you see that order-page? That's a custom element. That's the order page.
[00:00:17]
If I'm going to the home, now it's menu-page. If I get into the details, it's details-page, okay? So these are web components. That is actually the design pattern, okay, web components. Inside that web component, it has a shadow-root, shadow DOM, that actually that's kind of its own mini DOM and CSS.
[00:00:40]
When you apply CSS, it applies only to that tree, to that sub-tree and not to the whole page. That's the idea. Anyway, and you have HTML, okay? Well, these tags are actually defined in a module, in an ECMAScript module. And all of them, if we go to the Network tab,
>> Maximiliano Firtman: Let's do this so we can see better.
[00:01:12]
>> Maximiliano Firtman: Decrease a little bit the font size, and let's go to the home, refresh, and now I'm going to see JS. So you can see that every DetailsPage.js is the web component for DetailsPage, ProductItem, CartItem, Menu, OrderPage, MenuPage. So, when we load the project, actually, all the pages are being loaded.
[00:01:40]
So the web component of all the pages are being loaded. This is how modules work. When the page loads, the ECMAScript engine creates a tree, a modules tree. So I'm loading this module, that module is importing from another module, that other module is importing from another module. So it's downloading all the JavaScript files, okay?
[00:02:02]
So, that loading process is taking the network, is taking time in parsing and execution when the page loads. And maybe we can increase performance if we can do lazy load. So for example, if I'm in the home, I shouldn't download all the content for the order. If I'm getting into the order, I'm gonna do that.
[00:02:28]
Okay, makes sense? So now we are going to implement that. So to do that, the first step is to remove the static import. So, right now, these static imports are in app.js. So if you open app.js, there is a section here that says Web Components Imports. These are static imports.
[00:02:53]
So, this is the one that says hey, you should download OrderPage even if you are not using it right now. So if I remove OrderPage from here, then it's not part of the tree anymore, the import tree anymore. So, if I go back here and refresh, I shouldn't be seeing OrderPage, just MenuPage and DetailsPage, not OrderPage.
[00:03:16]
Now if I go to OrderPage, I see nothing rendered. Why is that? Because there is an order page component there or tag, html tag, that has no web component register. So it's empty, okay? So, what I need then is that when you go to that section, when you go to the order section, I wanna dynamically import that file, okay?
[00:03:45]
Makes sense? To solve the problem, I need to open services, Router.js. That has all the logic for routing. Let me decrease the font size a little bit, and go back, there we are. So, here you can see that it's creating the element of type order-page at that point.
[00:04:05]
So but now we know that before doing that, we need to download and parse and execute lazy load. That's the term. We need to lazy load the JavaScript file for that. Before dynamic imports was available in browsers, there were a lot of techniques to do that. So, one technique was actually to inject a script tag, and I'm not sure if you have heard about JSONP.
[00:04:33]
Have you heard about JSONP, JSON with payload [INAUDIBLE]? Anyway, the idea is that something similar to JSONP where you were loading that and that script at the end should, callback function so you know when it's ready. It was really complicated. Now it's actually much simpler. So here we are going to implement the Lazy Load Pattern.
[00:04:57]
We will just do this. We are going to await for importing components/OrderPage.js. Import is a new function. So it's the same import that we use at the top. It looks like the same, but this one is a function. The function version will dynamically load that, and it returns a promise, okay?
[00:05:25]
So I can use then and catch, or I can use async await. But to use await, I need to change my function and convert that into an async function, okay? If not, I can just stay with then. So I wait for that, and it will just kind of stay there waiting for that import to appear.
[00:05:47]
And now, I'm done, so pretty simple. So going back to the home, I'm refreshing. I'm going to order, and now I'm seeing something, which means it works. What's the difference compared with the previous version? I mean, it's difficult to see the difference visually in the context of the page, but let me decrease a little bit this, like that.
[00:06:20]
If I refresh, I'm not seeing OrderPage until I'm getting into the page for the first time. So OrderPage and actually CartItem, that is a dependency of OrderPage, they're being downloaded later when they are needed. That's lazy load. That's how you lazy load. It can become web components, or it can be any module, okay, so any module.
[00:06:49]
Again, talking about the registration form example we mentioned before, you load the JavaScript necessary for that registration for only when the user goes there.
>> Speaker 2: Have you seen that pattern used with infinite scroll or the intersection observer, or is that gonna be too slow to-
>> Maximiliano Firtman: The thing is that in that case when you have an infinite scroll, you are talking about data, not behavior, so you are loading data.
[00:07:20]
I mean, I don't think I can find a use case for loading this in that moment, but yeah, you have to understand that that await is making an HTTP request. And maybe not just one because it's creating another tree because in fact, in this case, OrderPage is including CartItem.
[00:07:44]
So actually, you need to download two files. It can be 100 files, and it takes time. So, if you are doing that in a scroll, it's a bad practice. Also, if you are reading the onscroll, probably you are using passive event listeners that, yeah, blah, blah, blah, blah, blah.
[00:08:04]
I don't think you will use this pattern in that situation.
Learn Straight from the Experts Who Shape the Modern Web
- In-depth Courses
- Industry Leading Experts
- Learning Paths
- Live Interactive Workshops