Google+
4elements web design & consultancy

4elements

Blog

  • like 4 15

    Dramatically Speed Up Your React Front-End App Using Lazy Loading

    4elements | web design The Hague blog • Dramatically Speed Up Your React Front-End App Using Lazy Loading

    A constant challenge faced by front-end developers is the performance of our applications. How can we deliver a robust and full-featured application to our users without forcing them to wait an eternity for the page to load? The techniques used to speed up a website are so numerous that it can often be confusing to decide where to focus our energy when optimising for performance and speed.

    Thankfully, the solution isn't as complicated as it sometimes might seem. In this post, I'll break down one of the most effective techniques used by large web apps to speed up their user experience. I'll go over a package to facilitate this and ensure that we can deliver our app to users faster without them noticing that anything has changed.

    What Does It Mean for a Website to Be Fast?

    The question of web performance is as deep as it is broad. For the sake of this post, I'm going to try and define performance in the simplest terms: send as little as you can as fast as you can. Of course, this might be an oversimplification of the problem, but practically speaking, we can achieve dramatic speed improvements by simply sending less data for the user to download and sending that data fast.

    For the purpose of this post, I'm going to focus on the first part of this definition—sending the least possible amount of information to the user's browser. 

    Invariably, the biggest offenders when it comes to slowing down our applications are images and JavaScript. In this post, I'm going to show you how to deal with the problem of large application bundles and speed up our website in the process.

    React Loadable

    React Loadable is a package that allows us to lazy load our JavaScript only when it's required by the application. Of course, not all websites use React, but for the sake of brevity I'm going to focus on implementing React Loadable in a server-side rendered app built with Webpack. The final result will be multiple JavaScript files delivered to the user's browser automatically when that code is needed. If you want to try out the completed code, you can clone the example source code from our GitHub repo.

    Using our definition from before, this simply means we send less to the user up front so that data can be downloaded faster and our user will experience a more performant site.

    1. Add React Loadable to Your Component

    I'll take an example React component, MyComponent. I'll assume this component is made up of two files, MyComponent/MyComponent.jsx and MyComponent/index.js.

    In these two files, I define the React component exactly as I normally would in MyComponent.jsx. In index.js, I import the React component and re-export it—this time wrapped in the Loadable function. Using the ECMAScript import feature, I can indicate to Webpack that I expect this file to be dynamically loaded. This pattern allows me to easily lazy load any component I've already written. It also allows me to separate the logic between lazy loading and rendering. That might sound complicated, but here's what this would look like in practice:

    I can then import my component exactly as I normally would:

    I've now introduced React Loadable into MyComponent. I can add more logic to this component later if I choose—this might include introducing a loading state or an error handler to the component. Thanks to Webpack, when we run our build, I'll now be provided with two separate JavaScript bundles: app.min.js is our regular application bundle, and myComponent.min.js contains the code we've just written. I'll discuss how to deliver these bundles to the browser a little later.

    2. Simplify the Setup With Babel

    Ordinarily, I'd have to include two extra options when passing an object to the Loadable function, modules and webpack. These help Webpack identify which modules we should be including. Thankfully, we can obviate the need to include these two options with every component by using the react-loadable/babel plugin. This automatically includes these options for us:

    I can include this plugin by adding it to my list of plugins in my .babelrc file, like so:

    I'm now one step closer to lazy loading our component. However, in my case, I'm dealing with server-side rendering. Currently, the server will not be able to render our lazy-loaded components.

    3. Rendering Components on the Server

    In my server application, I have a standard configuration that looks something like this:

    The first step is going to be to instruct React Loadable that I want all modules to be preloaded. This allows me to decide which ones should be loaded immediately on the client. I do this by modifying my server/index.js file like so:

    The next step is going to be to push all components I want to render to an array so we can later determine which components require immediate loading. This is so the HTML can be returned with the correct JavaScript bundles included via script tags (more on this later). For now, I'm going modify my server file like so:

    Every time a component is used that requires React Loadable, it will be added to the modules array. This is an automatic process done by React Loadable, so this is all that's required on our part for this process.

    Now we have a list of modules that we know will need to be rendered immediately. The problem we now face is mapping these modules to the bundles that Webpack has automatically produced for us.

    4. Mapping Webpack Bundles to Modules

    So now I've instructed Webpack to create myComponent.min.js, and I know that MyComponent is being used immediately, so I need to load this bundle in the initial HTML payload we deliver to the user. Thankfully, React Loadable provides a way for us to achieve this, as well. In my client Webpack configuration file, I need to include a new plugin:

    The loadable-manifest.json file will provide me a mapping between modules and bundles so that I can use the modules array I set up earlier to load the bundles I know I'll need. In my case, this file might look something like this:

    This will also require a common Webpack manifest file to include the mapping between modules and files for internal Webpack purposes. I can do this by including another Webpack plugin:

    5. Including Bundles in Your HTML

    The final step in loading our dynamic bundles on the server is to include these in the HTML we deliver to the user. For this step, I'm going to combine the output of steps 3 and 4. I can start by modifying the server file I created above:

    In this, I've imported the manifest and asked React Loadable to create an array with module/bundle mappings. The only thing left for me to do is to render these bundles to an HTML string:

    6. Load the Server-Rendered Bundles on the Client

    The final step to using the bundles that we've loaded on the server is to consume them on the client. Doing this is simple—I can just instruct React Loadable to preload any modules it's found to be immediately available:

    Conclusion

    Following this process, I can split my application bundle into as many smaller bundles as I need. In this way, my app sends less to the user and only when they need it. I've reduced the amount of code that needs to be sent so that it can be sent faster. This can have significant performance gains for larger applications. It can also set smaller applications up for rapid growth should the need arise. 

    martijn broeders

    founder/ strategic creative at 4elements web design & consultancy
    e-mail: .(JavaScript must be enabled to view this email address)
    phone: 06 38 55 28 54
  • 1
    silhouette
    Darrel
    June 14, 2018 at

    You have made some good points there. I looked on the net to find out more about the issue and found most people will go along with your views on this website.

  • 2
    silhouette
    Rosalina
    January 31, 2014 at

    I am in fact thankful to the holder of this web site who has shared this fantastic post at at this time.

  • 3
    silhouette
    christelgerlach
    January 26, 2014 at

    Have you ever considered about including a little bit more than just your articles? I mean, what you say is important and everything. Nevertheless just imagine if you added some great graphics or video clips to give your posts more, "pop"! Your content is excellent but with pics and clips, this website could definitely be one of the best in its field. Fantastic blog!

  • 4
    silhouette
    deniDrainnisp
    May 02, 2013 at

    You have a wonderful site here that was a quality read for me. Good info! Thanks!

  • 5
    martijn broeders's avatar
    martijn broeders
    April 25, 2013 at

    Should be working.

  • 6
    silhouette
    habitatnys.org
    April 24, 2013 at

    Oh my goodness! Incredible article dude! Many thanks, However I am going through problems with your RSS. I don't understand why I can't subscribe to it.Is there anybody having identical RSS issues? Anybody who knows the solution will you kindly respond?Thanks!!

  • 7
    silhouette
    Como Fazer Um Site
    March 29, 2013 at

    Hello, I read your new stuff regularly. Your story-telling style is witty, keep up the good work!

  • 8
    martijn broeders's avatar
    martijn broeders
    March 07, 2013 at

    Hello carsten, Sorry for the late response. (blog is getting some spam so I need to check every entry before approving)Apple reserves memory and cpu for their own tasks. (like account manager, wiki a.o. apps from apple) But this makes other web related tasks and the server overall slower. By disabling you are in charge, what results in faster websites, mail and others...If you have any other question, please email me.Kind regards, Martijn

  • 9
    silhouette
    Carsten Hahn
    March 04, 2013 at

    Hi Martijn, i stuck at the beginning with the Server-Admin Screen where i have to disable "Dedicate system resources to server services". What should i do?BTW. What does this button do?Groetjes Carsten

  • 10
    martijn broeders's avatar
    martijn broeders
    March 04, 2013 at

    Hello carsten, Yes this tutorial is compatible. (paths, locations will be the same. Only some version numbers could be different (newer) but that's not a problem...)

  • 11
    silhouette
    carsten hahn
    March 01, 2013 at

    Hi, is your lion tutorial here compatible with mountain lion server? i got a new mac mini and cannot change to lion.groetjes from germanycarsten

  • 12
    silhouette
    www.sitementrix.com.ua
    February 23, 2013 at

    I have read a few excellent stuff here. Certainly value bookmarking for revisiting. I wonder how much attempt you set to make the sort of great informative site.

  • 13
    martijn broeders's avatar
    martijn broeders
    April 05, 2012 at

    @Eran, Thanks, I just send you an email on how to get your request working.

  • 14
    silhouette
    Eran Kendler
    April 05, 2012 at

    Fantastic work - was great to use, and works well.Was wondering if you can post your fix for webmin to work with Lion's apache, at the moment no ghosts showWill be highly appreciated.

  • 15
    martijn broeders's avatar
    martijn broeders
    January 20, 2012 at

    @Filip, Thanks. Depends, if you like to run your own mail server, multiple websites etc you would need to enable DNS on your MacMini Server.But you only need 1 static IP to get all running. (DNS e.a.)

  • 16
    silhouette
    Filip
    January 20, 2012 at

    Wow great, thank you. I spent almost a week installing Lion server on my new mac mini. Failed so many times. Services didn't run properly etc... At the end I found out it was BT fault. Their router is rubbish so I swapped it with Airport Extreme and it is working fine since. I have one silly question, do I need to set Dns when all my dns entries are with company where I registered domain? Thanks

By - category

    By - date