Lazy load any charts and ads with lazysizes.js
Tags: javascript, html, charts, lazyload
Published: 2020-10-04 12:18:01

After adding emoji trends charts on  [emojigraph.org/chart-decreasing/](https://emojigraph.org/chart-decreasing/), I faced a significant drop 📉 in page loading speed on mobile devices. And the same problem I had with ads.

I’ve already used  [**_lazysizes.js_**](https://github.com/aFarkas/lazysizes)  for lazy loading images, so I started to search for a way to use the same library to lazy load charts and ads.

Hopefully, there is a  **lazybeforeunveil**  event fired on each lazyload element right before the “unveil” transformation.

First, add your chart library dns-prefetch in  `<head>…</head>`  section, so you won’t waste time loading the library but will be ready to load a bit faster once you need it:

    <link rel=”preconnect dns-prefetch” href="https://cdn.jsdelivr.net/npm/apexcharts@3.19.3/dist/apexcharts.min.js" crossorigin=”anonymous”>

Then add the`lazyload`  class to the div containing your chart.

    <div id="tracker_chart" class="chart lazyload" data-expand="-150" style="height: 510px;"></div>

You can also set  `data-expand`  attribute to set in pixels when to start to lazy preload images/iframes. It could be set to a negative value, I use`data-expand="-150"`  to load chart only after 150px of my chart placeholder are in the viewport area.

I’m using an URL-encoded SVG to make a nice looking chart placeholder.

    <div id="chart_brush" style="  
        height: 510px; width: 100%;   
        background-image: url('data:image/svg+xml;charset=utf8,%3Csvg xmlns="[http://www.w3.org/2000/svg](http://www.w3.org/2000/svg)" ...%3E ... %3C/svg%3E');  
        background-repeat: no-repeat;" >

Add following js code before closing  `</body>`  tag:

    <script type="text/javascript">  
    document.getElementById("tracker_chart").addEventListener("lazybeforeunveil", function() {  
        var scriptLibrary = document.createElement('script');  
        scriptLibrary.onload = function () {  
            var scriptChart = document.createElement('script');  
            scriptChart.src = '/js/chart.js';  
            document.body.appendChild(scriptChart);  
        };  
        scriptLibrary.src = 'https://cdn.jsdelivr.net/npm/apexcharts@3.19.3/dist/apexcharts.min.js';  
        document.head.appendChild(scriptLibrary);  
    });  
    </script>

Here we add EventListener to your chart div, which loads your chart library and javascript to plot the chart after the event is fired.  
Where  **scriptLibrary.src**  — link to your library, and  **scriptChart.src** — link to js plotting a chart that is dependent on that library.

✅ And that’s all!

To lazy load ads — we can use the same technique:

    <script type="text/javascript">  
    window.addEventListener('DOMContentLoaded', (event) => {  
        if (window.innerWidth<992){  
           /*your functions for big screen*/  
    document.getElementById("widget_ad_mobile").addEventListener("lazybeforeunveil", function() {  
            var scriptAds = document.createElement('script');  
            scriptAds.onload = function () {  
                    (adsbygoogle = window.adsbygoogle || []).push({});  
                };  
            scriptAds.src = '[https://pagead2.googlesyndication.com/pagead/js/adsbygoogle.js'](https://pagead2.googlesyndication.com/pagead/js/adsbygoogle.js');  
            document.getElementById("widget_ad_mobile").appendChild(scriptAds);  
            });  
        }  
    });  
    </script>

In my case I use lazy ads loading only on mobile devices (window.innerWidth<992) for widget that are way below the fold (“widget_ad_mobile”).

After implementing chart and ads lazy load I got back to 90+ score and  _<3s_ load time on Google PageSpeed for mobile.

If you have any questions, or suggestions for improvement — please let me know in the comments.