DEV Community

Cover image for Lazy load any charts and ads with lazysizes.js
Oleh Mertviacheko
Oleh Mertviacheko

Posted on

Lazy load any charts and ads with lazysizes.js

After adding emoji trends charts on 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 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 thelazyload 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 usedata-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.

Top comments (0)