DEV Community

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

Posted on

3 1

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)