Use Lazy Loading to Limit Access to Code

Ryan Chenkie: [0:00] The frontend of our application is currently protecting routes such that if we're not logged in and we tried to go to the dashboard, we'd get kicked back over to the home page. If we don't have a role of admin, but we tried to access inventory, we'd get kicked out as well.

[0:15] The app still contains something that some might consider a security issue. That is even though users can get to those routes, the code that powers them is still loaded in the browser.

[0:27] Let's consider this. If we go to the home route here, let's say that we are not logged in at all. In fact, we can just explicitly log ourselves out. Then, go to home.

[0:39] If we adjust our filters in the Network tab to look for everything that would come back and we refresh. Even if a user is not logged in, if we look in our main chunk.js file and we do a search for something like dashboard, what we'll see is that we've got all stuff that goes into powering the dashboard.

[0:59] Likewise, all of the stuff that goes into powering the inventory route. All of that is found in this main chunk.js that comes back when the application loads. Now, as long as you're not keeping sensitive info in your code is might not be such a big deal. I think it really is a good idea if we limit access to the code that powers those routes.

[1:19] Fortunately, we can do that really easily with React's lazy loading function. Lazy loading is when we split the application up into different bundles. We can load the appropriate bundle at the appropriate time. In this case, that would be when a certain route is loaded. To see how to do that, let's come into app.JS.

[1:38] What we'll need to do here is replace all of these imports for the dashboard, for inventory, etc. Anything that shouldn't be public will need to lazyLoad that instead. Let's pull in the lazy function that comes from React. Let's replace all of these imports here with the lazy loaded variety.

[1:57] To do that, we would say, "Give us a const dashboard = lazy()." Lazy takes this callback which is then going to import from the same spot. We'll go into pages/dashboard. We can do the same for our other routes as well.

[2:14] We can do one for inventory here. Then we can do one for account. We can do one for settings. We can do one for users. We, then, need to remove all of these imports here. Anything that has now been moved over to lazy, we'll take it out.

[2:42] That is generally all that's required to lazyLoad these routes. However, we do need to wrap them in suspense, because as they're loading, React may need to render something else as a fallback. That's pretty easy. We pull in suspense from React. We come down to our routes here.

[2:59] Just above this switch statements, we can call for suspense and give it a fallback. The fallback is going to just be something to render as the application loads. Let's say, for now, we just want to render this div that says, "loading inside."

[3:15] For the closing suspense tag, we can move that down below this switch statement. Let's see what we get. Let's save this. We'll come back over to our application. Let's give it one more refresh looking now into our main chunk.js code. It should be the case that we don't see anything related to inventory for example.

[3:34] If we do a search for inventory, we're going to get the import and some other stuff that's related to it. We aren't getting any of the code that goes into power the inventory route. We can get a better sense of this if we go to log in, for example.

[3:51] If I log in and clear our network tab here, and then I go to inventory, this chunk here is going to be all of the code that powers the inventory route. Down here, we can see the inventoryItem schema, the form and all of the other stuff for the route. In my mind, this isn't critical for the security of your application.

[4:11] Again, once the code that powers your application gets to the user's browser, you lose control of what they might do with it. Keeping certain portions of code away from users that shouldn't be seeing it is a good practice. It has the benefit of boosting the performance of your application because your code bundle is going to be smaller.