Lazy laad je afbeeldingen en iframes • Proudnerds


Lazy loading is een effectieve manier om uw frontend-prestaties te verbeteren. En dat is vooral belangrijk op eCommerce-websites. In dit artikel leest (en leert) u hoe u de laadtijd van de pagina kunt verkorten door uw

  1. afbeeldingen op scroll en
  2. iframes op aanvraag.

Laten we aan de slag gaan met lazy load!

Functieverzoek

Stel je een informeel kantoorgesprek (of tegenwoordig Slack) voor tussen een Marketing Specialist (MS) en jou, een Ontwikkelaar (D).

  • MS: Luister, we hebben ons marketingonderzoek afgerond en als resultaat hebben we een aantal coole video’s over onze productlijn gemaakt die vóór de voettekst op de startpagina van onze site moeten worden getoond! We willen graag dat er voor elke video een statische afbeelding wordt weergegeven en zodra de gebruiker op de afbeelding klikt, wordt de video afgespeeld.
  • D: Natuurlijk, geen probleem! Zijn de video’s geüpload naar het officiële YouTube-kanaal?
  • MS: Dat hebben ze zeker! Ze zijn gisteren goedgekeurd door de CEO, we zijn klaar om te gaan!
  • D: Uitstekend! Als je tijd hebt, stuur me dan de links voor de video’s en ik zal het overnemen en beginnen met de implementatie.
  • MS: Dat is geweldig, heel erg bedankt! Ik zal je ook enkele afbeeldingen voor de video’s e-mailen.
  • D: Er zijn geen afbeeldingen nodig, YouTube-links zijn voldoende.
  • MS: Echt? Waarom is dat?
  • D: Omdat YouTube je standaard een screenshot van je video geeft.
  • MS: Echt? Dat is geweldig!
  • D: YouTube is geweldig!
  • MS: Uitstekend! Ik stuur je de links zodra ik weer op mijn computer zit. Weet je wat? Je bent geweldig! Spreek je later!

En de MS loopt weg… Na een paar minuten hierover nagedacht te hebben, open ik mijn IDE en rek en prik mijn vingers. En nek.

Planning en uitrol

Allereerst moet ik een lay-outhandvat selecteren en waar de video’s moeten worden weergegeven. De MS zei:

…we willen dat deze vóór de footer op de homepage worden getoond…

Dus, cms_index_index.xml in Magento_Cms het is. Ook moet het attribuut “na” worden gebruikt.

app/design/frontend/Vendor/Theme/Magento_Cms/layout/cms_index_index.xml

<?xml version="1.0"?>
<page xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
      xsi:noNamespaceSchemaLocation="urn:magento:framework:View/Layout/etc/page_configuration.xsd">
    <body>
        <referenceContainer name="content">
            <block name="videos"
                   class="MagentoFrameworkViewElementTemplate"
                   template="Magento_Cms::videos.phtml"
                   after="-" />
        </referenceContainer>
    </body>
</page>

Het volgende dat ik nodig heb, is het sjabloonbestand “videos.phtml”. :start_typing_on_the toetsenbord: :fetch_some_youtube_videos_from_history_list: :take_out_the_ids:

En daar ga je!

app/design/frontend/Vendor/Theme/Magento_Cms/templates/videos.phtml

<?php $youtube_ids = ["ccnwzScp6bM","n2HgXRNVT7g","ux8GZAtCN-M","mtk5Ej-xLsM"]; ?>
<ul class="featured-videos">
    <?php foreach ($youtube_ids as $id): ?>
        <li class="featured-video">
            <div class="iframe-container iframe-container--56">
                <img class="poster"
                     src="https://img.youtube.com/vi/<?= $block->escapeHtml($id) ?>/hqdefault.jpg"
                     alt="<?= $block->escapeHtml(__('Youtube video')) ?>" />
                <iframe src="https://www.youtube.com/embed/<?= $block->escapeHtml($id) ?>"
                        frameborder="0"
                        allow="accelerometer; autoplay; encrypted-media; gyroscope; picture-in-picture"
                        allowfullscreen></iframe>
            </div>
        </li>
    <?php endforeach ?>
</ul>

En om het er mooi uit te laten zien en volgens de stijlgids…

app/design/frontend/Vendor/Theme/Magento_Cms/web/css/source/_extend.less

@import './_videos';

app/design/frontend/Vendor/Theme/Magento_Cms/web/css/source/_videos.less

& when (@media-common = true) {
    .featured-videos {
        margin: 0;
        padding: 0;
        list-style: none;
        display: flex;
        justify-content: space-between;
    }
 
    .featured-video {
        flex: 0 0 24%;
    }
 
    .iframe-container {
        position: relative;
        height: 0;
        overflow: hidden;
 
        &:before {
            content: '▶';
            display: block;
            position: absolute;
            top: 50%;
            left: 50%;
            transform: translate(-50%, -50%);
            background: black;
            border-radius: 50%;
            border: 2px solid white;
            padding: 8px;
            z-index: 2;
            width: 20px;
            height: 20px;
            color: white;
            text-align: center;
        }
    }
 
    .iframe-container--56 {
        padding-top: 56.25% !important;
    }
 
    .iframe-element {
        position: absolute;
        width: 100%;
    }
 
    .poster {
        cursor: pointer;
        top: 50%;
        left: 50%;
        transform: translate(-50%, -50%) scale(1);
        transition: transform .3s linear;
        max-height: none;
        opacity: 1;
 
        &:hover {
            transform: translate(-50%, -50%) scale(1.05);
            transition: transform .3s linear;
        }
    }
 
    .iframe-container.clicked {
        &:before,
        &:after {
            content: none;
        }
 
        .poster {
            opacity: 0;
            transition: opacity 1s linear .3s;
        }
    }
 
    .iframe {
        top: 0;
        opacity: 0;
        visibility: hidden;
        transition: opacity .3s linear 1s;
        height: 100%;
 
        &.loaded {
            opacity: 1;
            visibility: visible;
        }
    }
}

Het is tijd om te zien hoe het eruit ziet in de browser!

Lazyload 1 Img

Super goed! Er werd ook gezegd:

zodra de gebruiker op de afbeelding klikt, begint de video af te spelen.

OK, dus verberg het iframe en toon het nadat een gebruiker erop heeft geklikt. Makkelijk! Om dat te doen, moet ik een JS-component maken, die moet worden aangeroepen vanuit het sjabloonbestand.

app/design/frontend/Vendor/Theme/Magento_Cms/templates/videos.phtml

<?php $youtube_ids = ["ccnwzScp6bM","n2HgXRNVT7g","ux8GZAtCN-M","mtk5Ej-xLsM"]; ?>
<ul class="featured-videos">
    ...
</ul>
 
<!-- added the code below -->
<script type="text/x-magento-init">
    {
        ".featured-videos": {
            "toggle-img-iframe": {}
        }
    }
</script>

Eindelijk kan ik wat JavaScript-code schrijven ….

app/design/frontend/Vendor/Theme/Magento_Cms/requirejs-config.js

var config = {
    "map": {
        "*": {
            "toggle-img-iframe": "Magento_Cms/js/toggle-img-iframe"
        }
    }
};

app/design/frontend/Vendor/Theme/Magento_Cms/web/js/toggle-img-iframe.js

define(['jquery'], function ($) {
    'use strict';
 
    $.widget('Proudnerds.toggleImgIframe', {
        _init: function () {
            $(this.element).find('.iframe-container').each(function (i, img) {
                $(this).on('click', function () {
                    $(this).addClass('clicked');
                });
            });
        }
    });
 
    return $.Proudnerds.toggleImgIframe;
});

Het lijkt erop dat alles in orde is, IDE geeft geen fouten naar mij … Ik zal de browser opnieuw openen en gewoon op het derde item klikken om te zien of het werkt …

Lazyload 2 Iframe

En het werkt! Lief hoor! Voor de zekerheid zal ik het tabblad Netwerken openen en kijken hoe dit de prestaties beïnvloedt.

Lazyload 3 Network Tab Lazyload 0

via GIPHY

Tijd om te optimaliseren

Whoooops! Deze vier video’s brengen 132 kB extra paginalading (33,3 kB gecombineerd gemiddeld per video) – DOMLoaded is 1,05s, paginalading is voltooid in 2,96s! Deze nieuwe functie heeft een negatieve invloed op de laadtijdindicatoren van de pagina! Ik moet iets doen om de paginaprestaties te verbeteren…

Gelukkig heb ik hier de tool voor! Ik zal het lazyloading-script van aFarkas toevoegen, dat zou voor mijn prestatieprobleem moeten zorgen!

OK, dus dit is een pure JavaScript-plug-in, ik kan het opnemen als een zelfstandige bibliotheek. De beste manier zou zijn om het op themaniveau te plaatsen.

app/design/frontend/Vendor/Theme/requirejs-config.js

var config = {
    "deps": [
        "js/lazysizes.min"
    ]
};

Volgens de documentatie moet ik de volgende wijzigingen toepassen op elke: img elementen die worden gebruikt:

  1. hernoemen src toeschrijven aan data-src attribuut
  2. toevoegen lazyload CSS-klasse

Maar hé! Als het pad naar de daadwerkelijke afbeelding moet worden gedefinieerd als: data-src attribuut, de img element zal ongeldig zijn! Wat nu?

:starts_researching_on_the_Internet:

Bingo! Ik zal de kleinst mogelijke GIF gebruiken (slechts 26 B, ik maak geen grapje!) die op deze blogpost te vinden is. Het wordt gebruikt als de standaardafbeelding bij het laden van de pagina, dus alles zal soepel werken!

app/design/frontend/Vendor/Theme/Magento_Cms/templates/youtube.phtml

<?php 
...
 
// changes on <img />
// 1 - added lazyload class
// 2 - renamed src -> data-src
// 3 - added new src attribute and its associated value: src="<?= $block->getViewFileUrl('images/smallest.gif') ?>"
 
                <img class="iframe-element poster lazyload"
                     src="<?= $block->getViewFileUrl('images/smallest.gif') ?>"
                     data-src="https://img.youtube.com/vi/<?= $block->escapeHtml($id) ?>/hqdefault.jpg"
                     alt="<?= $block->escapeHtml(__('Youtube video')) ?>" />

Laten we nu de resultaten in de browser bekijken.

Lazyload 4 Network Tab Lazyload Img

De laatste hand

Prachtig! En nu om het laatste deel voor deze functie af te maken …

…statische afbeelding weergegeven en zodra de gebruiker op de afbeelding klikt, de video begint te spelen.

app/design/frontend/Vendor/Theme/Magento_Cms/templates/youtube.phtml

<?php 
...
 
// changes on <iframe>
// 1 - renamed src -> data-src
// 2 - added new src attribute and its associated value: src="<?= $block->getViewFileUrl('images/smallest.gif') ?>"
 
                <iframe class="iframe-element iframe"
                    src="<?= $block->getViewFileUrl('images/smallest.gif') ?>"
                    data-src="https://www.youtube.com/embed/<?= $block->escapeHtml($id) ?>"
                    frameborder="0"
                    allow="accelerometer; autoplay; encrypted-media; gyroscope; picture-in-picture"
                    allowfullscreen></iframe>
 
...

app/design/frontend/Proudnerds/Blog/Magento_Cms/web/js/toggle-img-iframe.js

...
                $(this).on('click', function () {
                    $(this).addClass('clicked');
 
// changes
// 1 - get the iframe element in DOM
// 2 - get the actual URL of the video from the data-src attribute
// 3 - append "?autoplay=1" string to the actual URL of the video
// 4 - show the iframe by adding the "loaded" CSS class 
 
                    var iframe = $(this).children('.iframe');
                    var iframeSrc = iframe.data('src');
 
                    iframe
                        .attr('src', iframeSrc + '?autoplay=1')
                        .addClass('loaded');
                });
...

Laten we de browser nog een keer controleren om te zien of het echt werkt.

Lazyload 5 Autoplay

En het tabblad Netwerken om de eindresultaten te zien….

Lazyload 6 Network Tab Lazyload Iframe

Geweldig! De video’s zijn hier, aan alle vereisten is voldaan, laat me even de laadtijden van de pagina’s vergelijken.

  • Klaar voor DOM – van 1.05s naar .75s (daling met bijna 29%)
  • laadtijd van de pagina – van 2,96s tot 1,76s (daling met bijna 41%)

:checking_my_inbox:

Oh, geweldig, de YouTube-links zijn hier!. Laat me die ID’s nemen en in het bestand stoppen… Oké… Nu de browser…

Oh, de video’s zijn er, geweldig! Ik zal gewoon antwoorden en de lidstaten laten weten dat de video’s klaar zijn om te worden bekeken en/of te worden geïmplementeerd op de live-site.

Was dit nuttig?

Ik wilde een realistisch voorbeeld van mijn proces delen en hoe ik van functieverzoek via planning, testen en prestatie-optimalisatie ging. Ik hoop dat je dit nuttig vond en dat je enkele van deze technieken in je dagelijkse werk zult toepassen.

En als u hulp nodig heeft bij het optimaliseren van de prestaties van uw projecten, neem dan gerust contact met ons op via het onderstaande formulier!

badges

Let’s connect

We hebben altijd zin in nieuwe en uitdagende projecten. We gaan graag met je in gesprek!