DEV Community

Cover image for Prevent Youtube iframes to improve Page Speed
Michael Gangolf
Michael Gangolf

Posted on

Prevent Youtube iframes to improve Page Speed

Improving your Core Web Vitals page speed with a simple JavaScript! No HTML changes required.

After Google introduced the Core Web Vitals to measure your web sites speed you have to make some changes to get a good score.

A big problem are YouTube iframes! They will make an external request as soon as you load your page. On the one hand it will load some kb/mb depending on your player settings but on the other hand it is an external request you might have to prevent because of the GDPR/DSGVO!

The problem

So a simple page like this:

<!DOCTYPE html>
<html lang="de">

<head>
    <meta charset="utf-8">
    <script src="main.js"></script>
</head>

<body>
    <main>
        <iframe id="ytplayer" type="text/html" width="640" height="360" src="http://www.youtube.com/embed/RNuUgbUzM8U?autoplay=1&origin=http://example.com" frameborder="0" />
    </main>
</body>

</html>
Enter fullscreen mode Exit fullscreen mode

will look like this in the DevTools network tab:
youtube1 32 requests / 2.92MB (3.47MB)

Lot's of external requests and it is preloading the video already.

How to fix it

Without changing the HTML code you can use this simple JavaScript file to prevent them from auto-loading:

function updateElements(elements) {
    // loop through all elements
    for (var i = 0; i < elements.length; i++) {
        const currentNode = elements[i].addedNodes;

        for (var j = 0; j < currentNode.length; j++) {
            if (currentNode[j].nodeName.toLowerCase() == "iframe") {
                const myLink = currentNode[j].src;

                // create local HTML code with Youtube link - replace ___data___ with data - dev.to's markdown parser won't let me use it :)
                const localHtml = '<html><body style="background:rgb(200,200,200)"><a href="' + myLink + '" style="font-size:14px;text-align:center;position: absolute;top: 50%;left: 50%;transform: translate(-50%, -50%);"><img src="___data___:image/svg+xml;base64,PHN2ZyB3aWR0aD0iMzMuOTJtbSIgaGVpZ2h0PSIyMy42Mm1tIiB2ZXJzaW9uPSIxLjEiIHZpZXdCb3g9IjAgMCAzMy45MiAyMy42MiIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIj4KIDxnIHRyYW5zZm9ybT0idHJhbnNsYXRlKC04OC4wNCAtMTM2LjcpIj4KICA8cGF0aCB0cmFuc2Zvcm09InNjYWxlKC4yNjQ2KSIgZD0ibTM0MS43IDUxNi42Yy00Ljk0NiAwLTguOTI4IDMuOTgxLTguOTI4IDguOTI4djcxLjQzYzAgNC45NDYgMy45ODEgOC45MjggOC45MjggOC45MjhoMTEwLjRjNC45NDYgMCA4LjkyOC0zLjk4MSA4LjkyOC04LjkyOHYtNzEuNDNjMC00Ljk0Ni0zLjk4MS04LjkyOC04LjkyOC04LjkyOHptNDcuMzIgMjkuNTYgMjYuNTIgMTUuMDktMjYuNTIgMTUuMDl6IiBmaWxsPSIjZjAwIiBzdG9wLWNvbG9yPSIjMDAwMDAwIiBzdHJva2Utd2lkdGg9IjMuMDM0cHgiIHN0eWxlPSJwYWludC1vcmRlcjpzdHJva2UgZmlsbCBtYXJrZXJzIi8+CiA8L2c+Cjwvc3ZnPgo=" width="80" height="55"/><br/>play video</a></body></html>';

                currentNode[j].setAttribute("data-src", myLink);

                // set local HTML
                // replace ___data___ with data - dev.to's markdown parser won't let me use it :)
                currentNode[j].src = "___data___:text/html;charset=utf-8," + localHtml;
            }
        }
    }
    // remove listeners at the end
    removeEventListener(document, updateElements);
}

function removeEvents(obj, callback) {
    if (window.__obs) {
        window.__obs.disconnect();
    }
}

function registerEvents(obj, callback) {
    const MutationObserver = window.MutationObserver || window.WebKitMutationObserver;
    if (MutationObserver) {
        const obs = new MutationObserver(function(mutations, observer) {
            callback(mutations)
        });
        obs.observe(obj, {
            childList: true,
            subtree: true
        });
        window.__obs = obs;
    }
}

// register events
registerEvents(document, updateElements);
Enter fullscreen mode Exit fullscreen mode

Attention: please replace all ___data___ with data. The markdown parser will throw an error when I just use data

This will register a MutationObserver and remove the iframe source when it is added to the DOM.

This will stop loading the original iframe source and show a local HTML file instead:
youtube2 no external request!


As soon as you click the link it will go to the original source and - since it is a user interaction - it will play the video
youtube3

Improvements

Of course you can change the localHtml page to look better or display an image and so on. For a proof of concept I've decided to keep it simple 😉

Top comments (0)