<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: Ofir Oron</title>
    <description>The latest articles on DEV Community by Ofir Oron (@ofir_oron).</description>
    <link>https://dev.to/ofir_oron</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F221794%2F9c14f9be-3dc7-4ceb-a3c6-dc613acb53b8.jpg</url>
      <title>DEV Community: Ofir Oron</title>
      <link>https://dev.to/ofir_oron</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/ofir_oron"/>
    <language>en</language>
    <item>
      <title>Improve Azure Pipeline speed with caching</title>
      <dc:creator>Ofir Oron</dc:creator>
      <pubDate>Mon, 21 Mar 2022 21:21:14 +0000</pubDate>
      <link>https://dev.to/ofir_oron/improve-azure-pipeline-speed-with-caching-g07</link>
      <guid>https://dev.to/ofir_oron/improve-azure-pipeline-speed-with-caching-g07</guid>
      <description>&lt;p&gt;Ever wondered why it takes so long for your Azure pipeline to finish whatever it is supposed to do? Can we improve this somehow?&lt;br&gt;
In this post, I will try to point out the obvious reason for slowness in our pipelines that is running scripts based on the npm ecosystem, describe what solution Azure Pipelines offers to solve it and how it works, as well as how the implementation looks like.&lt;/p&gt;
&lt;h2&gt;
  
  
  Pipelines in Azure
&lt;/h2&gt;

&lt;p&gt;Azure pipelines are composed from stages, each of them running jobs that are divided into steps that run your scripts or tasks. These jobs are being run on top of an agent which is basically a computing infrastructure (you can think of it as an image with preinstalled software needed to run your scripts).&lt;br&gt;
These agents spin up into pristine state. Yes, this is the basics of a predictable CI environment. The problem - your script is doing everything from scratch every single time which is probably a big waste of time. Maybe we can shave off a few seconds or more.&lt;/p&gt;
&lt;h2&gt;
  
  
  Npm ecosystem
&lt;/h2&gt;

&lt;p&gt;In our npm ecosystem, we rely on the fundamentals of node modules as our dependencies. In our CI process, we will install dependencies in a predictable manner, which gives us a  lot of confidence that the CI environment is always going to be the same for given inputs (basically our lock file), so we can test it carefully and finally deploy or publish our artifact safely.&lt;br&gt;
This installation process along with our build process among others, can take a significant amount of time as our app grows and become more mature. Our pipeline therefore can take several minutes to complete. Why? - The problem lies within the nature of a CI ecosystem; The process repeats itself over and over on every single run of our pipeline. Luckily, CI systems and specifically Azure Pipelines enable us to potentially improve on this aspect, using a caching mechanism. &lt;/p&gt;
&lt;h2&gt;
  
  
  Cache your dependencies with Cache task
&lt;/h2&gt;

&lt;p&gt;The following example demonstrates how to use the &lt;em&gt;Azure Pipeline Cache task&lt;/em&gt; to cache our yarn dependencies.&lt;br&gt;
The process for caching your npm dependencies is the same while using your &lt;em&gt;package-lock.json&lt;/em&gt; and &lt;em&gt;.npm&lt;/em&gt; cache folder.&lt;br&gt;
Here is a brief summary of how the caching process is working:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Using Yarn task to set Yarn's cache folder to a location of our choice
&lt;/li&gt;
&lt;/ul&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;- task: Yarn@3
    inputs:
      arguments: 'config set cache-folder $(yarnCacheFolder)'
      displayName: Set Yarn cache folder
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;ul&gt;
&lt;li&gt;Use cache task to create a cache with a key based on a static description of 'yarn', the agent's operating system identifier, and the content of your yarn lock file. Azure Pipelines is actually creating a hash based on the contents of this file and when the pipeline is run it will check for cache hit with this key. At runtime, assuming your agent is running Windows, this will look similar to this - &lt;em&gt;yarn|"Windows_NT"|FupyH86xxxxxxxxxtBrhv+2fiXTRb/6Dew=&lt;/em&gt; .
&lt;/li&gt;
&lt;/ul&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;- task: Cache@2
    inputs:
      key: 'yarn | "$(Agent.OS)" | yarn.lock'
      restoreKeys: |
        yarn | "$(Agent.OS)"
        yarn
      path: $(yarnCacheFolder)
    displayName: Cache dependencies
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;ul&gt;
&lt;li&gt;On the first run there is a &lt;strong&gt;cache miss&lt;/strong&gt; with our key and the cache is created for the first time.
&lt;/li&gt;
&lt;/ul&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Getting a pipeline cache artifact with one of the following fingerprints:
Fingerprint: `yarn|"Windows_NT"|FupyH86xxxxxxxxxtBrhv+2fiXTRb/6Dew=`
Fingerprint: `yarn|"Windows_NT"|**`
Fingerprint: `yarn|**`
There is a cache miss.

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;At this stage, you might notice an additional &lt;em&gt;Post-Job&lt;/em&gt; step was dynamically appended to the pipeline. This step is used to actually create the cache item. The process is printed to the pipeline log:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Creating a pipeline cache artifact with the following fingerprint: `yarn|"Windows_NT"|FupyH86xxxxxxxxxtBrhv+2fiXTRb/6Dew=`
Cache item created.

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;On the second run, assuming no changes to our lock file and our agent's configuration, there will be a &lt;strong&gt;cache hit&lt;/strong&gt; and dependencies will be fetched from the previously created cache instead of resolving it from the registry. 
This doesn't mean it happens instantaneously but it should take less time then actually do all of the process from scratch. 
In the pipeline log, you can actually see that the cache is being downloaded from Azure storage before it is being used.
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;There is a cache hit: `yarn|"Windows_NT"|FupyH86xxxxxxxxxtBrhv+2fiXTRb/6Dew=`
Used scope: 30;7375ab34-xxxx-xxxx-8ef7-382c644dca33;refs/heads/xxxxx;

Entry found at fingerprint: `yarn|"Windows_NT"|FupyH86xxxxxxxxxtBrhv+2fiXTRb/6Dew=`
Expected size to be downloaded: 100.0 MB
Downloaded 0.0 MB out of 100.0 MB (0%).

7-Zip 21.07 (x64) : Copyright (c) 1999-2021 Igor Pavlov : 2021-12-26


Extracting archive: 
Downloaded 12 MB out of 100.0 MB (12%).
...

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;If there is a cache miss, it will try to fallback to one of the restore keys.&lt;br&gt;
Here is the complete example of our .yml file:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;variables:
  npmRegistry: 'xxxx-xxxx-xxxx-xxxx' #Your custom registry ID
  yarnCacheFolder: $(Pipeline.Workspace)/.yarn

steps:  
- task: Yarn@3
    inputs:
      arguments: 'config set cache-folder $(yarnCacheFolder)'
      displayName: Set Yarn cache folder

  - task: Cache@2
    inputs:
      key: 'yarn | "$(Agent.OS)" | yarn.lock'
      restoreKeys: |
        yarn | "$(Agent.OS)"
        yarn
      path: $(yarnCacheFolder)
    displayName: Cache dependencies

  - task: Yarn@3
    displayName: 'Install dependencies'
    inputs:
      arguments: '--frozen-lockfile'
      customRegistry: useFeed
      customFeed: '$(npmRegistry)'

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Conclusion
&lt;/h2&gt;

&lt;p&gt;Using the Azure Pipeline Caching feature can save us a great deal of time. Here is an example of a pipeline performance before applying a caching task. You can see the average run time is not great to say the least, and revolves around 10 minutes and sometimes more - depending on agent availability, other networking, CI and npm ecosystem performance aspects. Clearly there must have been room for improvement. &lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F59k5p52eeg2xz8hzpjr5.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F59k5p52eeg2xz8hzpjr5.jpg" alt="Pipeline run time before caching" width="611" height="249"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;And here is a summary of 2 runs after applying caching.&lt;br&gt;
The first run (2nd in the list) is longer due to the Post-Job step creating a new cache item and npm dependencies are installed from npm as usual. &lt;br&gt;
The second run (1st in the list) really shows the new performance improvement, as there is a cache hit, the npm dependencies are fetched from the cache - Our pipeline run time is now reasonable!&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F1w6uyviiv7slkbw35027.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F1w6uyviiv7slkbw35027.jpg" alt="Pipeline run time after caching" width="611" height="124"&gt;&lt;/a&gt;&lt;/p&gt;

</description>
      <category>azure</category>
      <category>performance</category>
      <category>npm</category>
      <category>yarn</category>
    </item>
    <item>
      <title>Lazy loading react components with React.lazy, Suspense and bundle splitting</title>
      <dc:creator>Ofir Oron</dc:creator>
      <pubDate>Tue, 23 Feb 2021 07:39:14 +0000</pubDate>
      <link>https://dev.to/ofir_oron/lazy-loading-react-components-with-react-lazy-and-suspense-4ll0</link>
      <guid>https://dev.to/ofir_oron/lazy-loading-react-components-with-react-lazy-and-suspense-4ll0</guid>
      <description>&lt;p&gt;So, you've finished your project, an outstanding yet simple web application or website that also looks awesome, performs great and you're really happy with it.&lt;br&gt;
The moment has come for you to share it with a peer, so you have set up a meeting at your favorite neighborhood coffee shop. You both arrive at the meeting, connect your laptops to WiFi and start browsing your project in order to discuss it. &lt;br&gt;
Oh no!...something is wrong :/ It seems that your awesome web application is taking forever to load. You both stare at the white page, waiting patiently for the UI to load, hopefully, it will finish loading in no time. But why? What happened? You're thinking, this application is just a bunch of react components on a page, no backend yet, nothing really complicated to load or go wrong...it was working just fine on my machine you said ¯\_(ツ)_/¯&lt;/p&gt;

&lt;h2&gt;
  
  
  Your solid internet connection is taken for granted
&lt;/h2&gt;

&lt;p&gt;What would happen if our web application is deployed to the cloud or some other hosting service? It is now live on production and available for everyone to use. globally.&lt;br&gt;
Let's say some potential user is browsing your application. The "problem" is that this user lives in Venezuela, which happens to be ranked somewhere at the bottom of this &lt;a href="https://seasia.co/2019/07/12/rank-of-countries-with-fastest-and-slowest-internet-in-the-world-2019" rel="noopener noreferrer"&gt;list&lt;/a&gt;, in terms of internet connection speeds. Or maybe this user is in the same region as you but is using their home WiFi with a laggy internet connection. This user is finally getting the first page of your application, but it took them forever to get it, and to make things even worse, you didn't have the chance to implement a loading animation or similar UX solution. We know this is a bad UX, right?&lt;br&gt;
&lt;strong&gt;Conclusion&lt;/strong&gt;: Our users not necessarily have the best or even average internet connection and we should take that into consideration when thinking about UX and developing the front end of our application.&lt;/p&gt;

&lt;h2&gt;
  
  
  The root cause: bundle size
&lt;/h2&gt;

&lt;p&gt;Our front end is bundled with webpack or a similar tool for a production build. In case our application has grown and we take a closer look at our bundle we can see it is probably quite heavy, which could be a problem with a poor internet connection. The browser is fetching that bundle from the server which might take some time, depending on connection speed, server configuration, load, and more. In the meantime, our users will just have to wait.&lt;/p&gt;

&lt;h2&gt;
  
  
  Bundle splitting
&lt;/h2&gt;

&lt;p&gt;What if we had an option to improve the UX and make our application initially load a lot faster? Well, we do have a good option. Webpack allows us to introduce &lt;em&gt;bundle splitting&lt;/em&gt;. We can split our bundle into one or more chunks in strategic points. What this means in practice, is that we will have to tell webpack where to split our bundle. But what does it mean? if we split the bundle won't our application break? How will react handle this? Won't we have some missing parts between 2 or more bundles of our application? No. Webpack along with React allows us to introduce &lt;strong&gt;lazy loading&lt;/strong&gt;, which is basically loading some parts of our application only when needed, or when the user will have to use them. This effectively reduces the initial bundle size. Let's assume it contains only the first page of our application. Only if the user will navigate to a different page or section of our UI, react will load the corresponding component, which under the hood tells the browser to fetch related bundles created by webpack earlier in the build process.&lt;br&gt;
If you're not using create-react-app, you may need to set up webpack for bundle splitting to work as you would expect. Your weback configuration should look similar to the following example:&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;

&lt;span class="nx"&gt;module&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;exports&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="na"&gt;entry&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="na"&gt;main&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;./src/app.js&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="p"&gt;},&lt;/span&gt;
  &lt;span class="na"&gt;output&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="c1"&gt;// `filename` provides a template for naming your bundles (remember to use `[name]`)&lt;/span&gt;
    &lt;span class="na"&gt;filename&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;[name].bundle.js&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="c1"&gt;// `chunkFilename` provides a template for naming code-split bundles (optional)&lt;/span&gt;
    &lt;span class="na"&gt;chunkFilename&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;[name].chunk.js&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="c1"&gt;// `path` is the folder where Webpack will place your bundles&lt;/span&gt;
    &lt;span class="na"&gt;path&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;./dist&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="c1"&gt;// `publicPath` is where Webpack will load your bundles from (optional)&lt;/span&gt;
    &lt;span class="na"&gt;publicPath&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;dist/&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;};&lt;/span&gt;


&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;
&lt;h2&gt;
  
  
  Lazy loading
&lt;/h2&gt;

&lt;p&gt;Lazy loading react components or modules is as simple as importing them with a special lazy function, part of react:&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;

&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nx"&gt;React&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;useState&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;Fragment&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;react&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="c1"&gt;//import MyComponent from './my-component';&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;MyComponent&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;React&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;lazy&lt;/span&gt;&lt;span class="p"&gt;(()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="k"&gt;import&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;./my-component&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;));&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;App&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;isVisible&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;setIsVisible&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;useState&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kc"&gt;false&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="k"&gt;return &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;Fragment&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;
      &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;span&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="nx"&gt;Component&lt;/span&gt; &lt;span class="nx"&gt;is&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;isVisible&lt;/span&gt; &lt;span class="p"&gt;?&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;visible&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;not visible&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="sr"&gt;/span&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;
&lt;/span&gt;      &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;button&lt;/span&gt; &lt;span class="nx"&gt;onClick&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;{()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nf"&gt;setIsVisible&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="nx"&gt;isVisible&lt;/span&gt;&lt;span class="p"&gt;)}&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;
        &lt;span class="nx"&gt;Toggle&lt;/span&gt; &lt;span class="nx"&gt;my&lt;/span&gt; &lt;span class="nx"&gt;component&lt;/span&gt;
      &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="sr"&gt;/button&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;
&lt;/span&gt;      &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;isVisible&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;MyComponent&lt;/span&gt; &lt;span class="o"&gt;/&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="sr"&gt;/Fragment&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;
&lt;/span&gt;  &lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;};&lt;/span&gt;


&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;Keep in mind that &lt;code&gt;MyComponent&lt;/code&gt; must be exported as default for &lt;code&gt;React.lazy&lt;/code&gt; to work properly.&lt;br&gt;
But wait, what happens after using this approach? if you take a look, you will notice that the component is imported dynamically and not statically, which means it is not available to render right away. &lt;br&gt;
This also means that once the page is loaded, that piece of UI my-component is responsible for is obviously not rendered yet. In addition and most importantly, after clicking the Toggle my component button, it may take some time for your lazy component to load, depending on its implementation and how heavy it is. The user doesn't get any feedback on how long the wait is going to be, or when it will be over and the missing UI will finally render. &lt;br&gt;
Let's take an extreme case where your component is actually a really complicated piece of UI with lots of dependencies. In that case, the loading time might be significant due to the split chunk weight, meanwhile, the user just waits without any clue on how long.&lt;br&gt;
FYI if you're using a modern version of &lt;code&gt;create-react-app&lt;/code&gt;, using the example above will result in a Suspense-related error because you may forget to use the&lt;code&gt;Suspense&lt;/code&gt; component. In our example, Suspense was left out on purpose, in order to illustrate how easy it is to lazy load components and that using Lazy loading without Suspense is technically possible. create-react-app is very opinionated on UX best practices and we are going to learn more about it and why this error is in place, in the next section.&lt;/p&gt;

&lt;h5&gt;
  
  
  &lt;em&gt;Real world example of multiple chunks loading&lt;/em&gt;
&lt;/h5&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Ftnmjla8aoqi6c47o8h2w.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Ftnmjla8aoqi6c47o8h2w.png" alt="Real world example of multiple chunks loading"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h4&gt;
  
  
  Naming your chunks
&lt;/h4&gt;

&lt;p&gt;Webpack supports a special comment directive that will be used to name our split chunks&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;MyComponent&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;React&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;lazy&lt;/span&gt;&lt;span class="p"&gt;(()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="k"&gt;import&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
&lt;span class="cm"&gt;/* webpackChunkName: "MyComponent" */&lt;/span&gt;
&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;./my-component&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;));&lt;/span&gt;



&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;
&lt;h2&gt;
  
  
  Lazy loading with react Suspense
&lt;/h2&gt;

&lt;p&gt;The react core team has come up with an elegant solution to the situation where the user waits for something to load: A special &lt;code&gt;Suspense&lt;/code&gt; component. This component is available as of react v16.6 and accepts the lazy component(s) as children, and a fallback prop for the UI you would like to render while loading is in progress.&lt;br&gt;
This time, the user will know something is loading. Once loading is finished, Suspense seamlessly replaces the fallback component with the actual component that was loaded.&lt;br&gt;
Suspense allows us to lazy load components in a declarative coding style.&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;

&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nx"&gt;React&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;Suspense&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;useState&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;react&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;App&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;isVisible&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;setIsVisible&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;useState&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kc"&gt;false&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="k"&gt;return &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;Suspense&lt;/span&gt; &lt;span class="nx"&gt;fallback&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;span&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="nx"&gt;Loading&lt;/span&gt;&lt;span class="p"&gt;...&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="sr"&gt;/span&amp;gt;}&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;
&lt;/span&gt;      &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;span&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="nx"&gt;Component&lt;/span&gt; &lt;span class="nx"&gt;is&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;isVisible&lt;/span&gt; &lt;span class="p"&gt;?&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;visible&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;not visible&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="sr"&gt;/span&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;
&lt;/span&gt;      &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;button&lt;/span&gt; &lt;span class="nx"&gt;onClick&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;{()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nf"&gt;setIsVisible&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="nx"&gt;isVisible&lt;/span&gt;&lt;span class="p"&gt;)}&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;
        &lt;span class="nx"&gt;Toggle&lt;/span&gt; &lt;span class="nx"&gt;my&lt;/span&gt; &lt;span class="nx"&gt;component&lt;/span&gt;
      &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="sr"&gt;/button&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;
&lt;/span&gt;      &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;isVisible&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;MyComponent&lt;/span&gt; &lt;span class="o"&gt;/&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="sr"&gt;/Suspense&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;
&lt;/span&gt;  &lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;};&lt;/span&gt;


&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;If for some reason, the loading process is canceled by the user, the browser is still fetching the bundle so next time the component will render immediately. In addition, once the bundle has been fetched and cached by the browser, Suspense will not use the fallback, and render will occur immediately.&lt;/p&gt;

&lt;h4&gt;
  
  
  What to render as a fallback
&lt;/h4&gt;

&lt;p&gt;The current UX trend is to use some kind of a placeholder animation while loading pieces of UI. &lt;a href="https://github.com/danilowoz/react-content-loader" rel="noopener noreferrer"&gt;react-content-loader&lt;/a&gt; is a popular npm package for this use case. It is customizable, supports react and &lt;code&gt;react-native&lt;/code&gt;, has some bundled presets, and actually supports SVG animation out of the box.&lt;/p&gt;

&lt;h5&gt;
  
  
  &lt;em&gt;Illustration of a loading animation&lt;/em&gt;
&lt;/h5&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Fgsofyzawhmaro8q2jh4p.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Fgsofyzawhmaro8q2jh4p.png" alt="Illustration of a loading animation"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Most modern design tools support exporting design directly as SVG which can be used with &lt;code&gt;react-content-loader&lt;/code&gt;. If you want to get your hands dirty and do it yourself, &lt;a href="https://editor.method.ac/" rel="noopener noreferrer"&gt;Method Draw&lt;/a&gt; is an excellent web tool that you can use to design your fallback placeholder animation. It supports exporting as SVG and it's even &lt;a href="https://github.com/methodofaction/Method-Draw" rel="noopener noreferrer"&gt;open source&lt;/a&gt;!&lt;/p&gt;

&lt;h5&gt;
  
  
  &lt;em&gt;Method Draw - a simple and easy vector editor for the web&lt;/em&gt;
&lt;/h5&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Fb2prsjg1otovc8uvxk34.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Fb2prsjg1otovc8uvxk34.png" alt="Method-Draw"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Using a fallback only when we have to
&lt;/h2&gt;

&lt;p&gt;In most cases our network speed is pretty solid, so we might encounter a situation where the fallback renders for a split second - that is the amount of time it took for the browser to download the bundle, even though the user might not need it in order to get a good UX from our app. This fast switching between the fallback and the actual component may seem like a bug, which is not good.&lt;br&gt;
Fortunately, we can add some logic to render our fallback only when we feel it is a must, meaning after a minimum period of time. Here is a more real-world example:&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;

&lt;span class="c1"&gt;//DelayedFallback.js&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nx"&gt;React&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;useEffect&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;useState&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;react&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nx"&gt;ContentLoader&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;react-content-loader&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;DelayedFallback&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="nx"&gt;children&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;delay&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;300&lt;/span&gt; &lt;span class="p"&gt;})&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;show&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;setShow&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;useState&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kc"&gt;false&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="nf"&gt;useEffect&lt;/span&gt;&lt;span class="p"&gt;(()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;timeout&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;setTimeout&lt;/span&gt;&lt;span class="p"&gt;(()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nf"&gt;setShow&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt; &lt;span class="nx"&gt;delay&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
        &lt;span class="k"&gt;return &lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="nf"&gt;clearTimeout&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;timeout&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
        &lt;span class="p"&gt;};&lt;/span&gt;
    &lt;span class="p"&gt;},&lt;/span&gt; &lt;span class="p"&gt;[]);&lt;/span&gt;

    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;show&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="nx"&gt;children&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="sr"&gt;/&amp;gt;&lt;/span&gt;&lt;span class="err"&gt;;
&lt;/span&gt;&lt;span class="p"&gt;};&lt;/span&gt;

&lt;span class="c1"&gt;//Header.js&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;DelayedFallback&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;./DelayedSuspenseFallback&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;SuspendedCreateMenu&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;./CreateMenu/CreateMenu.suspended&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="nx"&gt;expor&lt;/span&gt; &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;Header&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;props&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;
&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;Suspense&lt;/span&gt;
    &lt;span class="nx"&gt;fallback&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;DelayedFallback&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;
            &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;SuspendedCreateMenu&lt;/span&gt;
               &lt;span class="p"&gt;...&lt;/span&gt;
            &lt;span class="o"&gt;/&amp;gt;&lt;/span&gt;
        &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="sr"&gt;/DelayedFallback&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;
&lt;/span&gt;    &lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;

        &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;CreateMenu&lt;/span&gt;
           &lt;span class="p"&gt;...&lt;/span&gt;
        &lt;span class="o"&gt;/&amp;gt;&lt;/span&gt;
&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="sr"&gt;/Suspense&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;
&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="c1"&gt;//CreateMenu.suspended.js&lt;/span&gt;
&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;SuspendedCreateMenu&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;props&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="k"&gt;return &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;ContentLoader&lt;/span&gt;
        &lt;span class="nx"&gt;viewBox&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;0 0 1155 381&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;
        &lt;span class="nx"&gt;backgroundColor&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;#f4f4f4&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;
        &lt;span class="nx"&gt;foregroundColor&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;#d4d3d3&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;
        &lt;span class="nx"&gt;speed&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="mf"&gt;2.1&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="o"&gt;&amp;gt;&lt;/span&gt;
        &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;rect&lt;/span&gt;
            &lt;span class="nx"&gt;stroke&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;null&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;
            &lt;span class="nx"&gt;rx&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;9&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;
            &lt;span class="nx"&gt;id&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;svg_3&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;
            &lt;span class="nx"&gt;height&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;59.87731&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;
            &lt;span class="nx"&gt;width&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;371.44229&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;
            &lt;span class="nx"&gt;y&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;78.98809&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;
            &lt;span class="nx"&gt;x&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;289.67856&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;
            &lt;span class="nx"&gt;strokeOpacity&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;null&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;
            &lt;span class="nx"&gt;strokeWidth&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;1.5&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;
            &lt;span class="nx"&gt;fill&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;#ececec&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;
        &lt;span class="o"&gt;/&amp;gt;&lt;/span&gt;
&lt;span class="c1"&gt;// Rest of your SVG goes here&lt;/span&gt;
&lt;span class="p"&gt;...&lt;/span&gt;
&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="sr"&gt;/ContentLoader&amp;gt;&lt;/span&gt;&lt;span class="se"&gt;)&lt;/span&gt;&lt;span class="err"&gt;;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;


&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;As you can see, the fallback is just an SVG wrapped with a &lt;code&gt;ContentLoader&lt;/code&gt; component imported from the react-content-loader package. &lt;br&gt;
It is also worth mentioning that we are naming our fallback component the same as our actual component but with a &lt;code&gt;.suspended&lt;/code&gt; suffix. This is not mandatory.&lt;/p&gt;

&lt;h2&gt;
  
  
  A major UX change
&lt;/h2&gt;

&lt;p&gt;Lazy loading components is a big UX change for our users. Instead of waiting for the initial load and then interact freely with the application, introducing lazy loading actually means that initial loading time will be minimal but interacting with the application may include subsequent loading. A good architecture and UX design will result in a seamless and pleasant experience but keep in mind that it may require some joint planning of UX and development.&lt;/p&gt;

&lt;h2&gt;
  
  
  Don't rush into bundle splitting
&lt;/h2&gt;

&lt;p&gt;Before splitting our bundle we should exhaust all our efforts and try to reduce our bundle size. Sometimes we might find it contains a lot of unnecessary user code or dependencies.&lt;br&gt;
A popular dev dependency we can use just for this is &lt;code&gt;webpack-bundle-analyzer&lt;/code&gt;. This is a &lt;a href="https://github.com/webpack-contrib/webpack-bundle-analyzer" rel="noopener noreferrer"&gt;webpack plugin&lt;/a&gt; that can generate a bundle report, which allows us to dive into the content of our bundles in a visual manner, analyze them, and get some good insights.&lt;/p&gt;

&lt;h5&gt;
  
  
  &lt;em&gt;A bundle report (credit: webpack-bundle-analyzer)&lt;/em&gt;
&lt;/h5&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Fq5fupj8mylxq3nutcupu.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Fq5fupj8mylxq3nutcupu.gif" alt="A bundle report"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Debugging Suspense with react devtools
&lt;/h2&gt;

&lt;p&gt;When you start working with bundle splitting, Suspense, and lazy loading, you will soon find out that you need a quick and reliable way of simulating poor network speed, going back and forward between suspension modes, and examining what is actually loaded by the browser behind the scenes. &lt;br&gt;
In order to do that, you should get familiar with the network panel (assuming you're using Chrome) and the react &lt;a href="https://chrome.google.com/webstore/detail/react-developer-tools/fmkadmapgofadopljbjfkapdkoienihi?hl=en" rel="noopener noreferrer"&gt;Components dev tools panel&lt;/a&gt;.&lt;/p&gt;

&lt;h4&gt;
  
  
  Network panel
&lt;/h4&gt;

&lt;p&gt;This panel of Chrome dev tools lets your overview all of your web requests. We're currently specifically interested in the requests the browser is making to fetch our bundles which are javascript code (or chunks). For this purpose, you might want to filter the visible requests using the &lt;strong&gt;JS&lt;/strong&gt; preset at the top bar. You can also filter out what is not important by typing anything in the filter input. (&lt;code&gt;tcp&lt;/code&gt; in the example).&lt;br&gt;
In order to simulate a slower connection, you can choose one of the presets from the &lt;strong&gt;Throttling&lt;/strong&gt; dropdown. The default is Online. You can also add additional presets of your own which is great.&lt;br&gt;
Toggling between Online and Slow 3G etc, helps us test our application behavior at different network speeds. In practice, this may or may not trigger our Suspense fallback.&lt;/p&gt;

&lt;h5&gt;
  
  
  &lt;em&gt;An example of JS assets loading summary&lt;/em&gt;
&lt;/h5&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Fc54dxoci8928sk0da82e.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Fc54dxoci8928sk0da82e.png" alt="Network dev tool"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;It is highly recommended to get familiar with the &lt;a href="https://developers.google.com/web/tools/chrome-devtools/network" rel="noopener noreferrer"&gt;Netowrk panel&lt;/a&gt; which offers a lot more options and valuable insights, unfortunately, they are out of scope for this post.&lt;/p&gt;

&lt;h4&gt;
  
  
  React developer tool
&lt;/h4&gt;

&lt;p&gt;The React developer tool is a Chrome extension that augments our dev tools with a Components panel. This panel deserves a post on its own, but for the scope of this post, let's focus on the options to search for a component in our application components tree and toggling Suspense instances.&lt;br&gt;
You can search for your suspended component using the top search input. Once you find a component that contains a suspended content, you will notice a &lt;strong&gt;Suspended&lt;/strong&gt; toggle you can use to switch your fallback on and off without reloading your page or making any new requests to the server.&lt;/p&gt;

&lt;h5&gt;
  
  
  &lt;em&gt;An example a components tree with Suspended toggled on&lt;/em&gt;
&lt;/h5&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2F1q5gawq7kw1rs0f0s5px.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2F1q5gawq7kw1rs0f0s5px.png" alt="React components panel"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Final words
&lt;/h2&gt;

&lt;p&gt;We've learned how to dynamically load components using Suspense, what actually happens behind the scenes when we split our app bundle into chunks, render a fallback component while the user waits for loading to finish.&lt;br&gt;
We've also briefly discussed how big UX change lazy loading is causing in our application and that sometimes we may want to examine our bundle before making a step forward.&lt;br&gt;
Lastly, we saw an example of what to render as a Suspense fallback, how to create this fallback component, and finally, how to debug things in an efficient way using community tools.&lt;br&gt;
Remember, being lazy is not necessarily a bad thing :)&lt;/p&gt;

</description>
      <category>react</category>
      <category>components</category>
      <category>lazy</category>
      <category>split</category>
    </item>
  </channel>
</rss>
