Fermer

octobre 14, 2020

Différer les images hors écran dans Episerver


Le chargement paresseux d'images est une technique pour les développeurs Web modernes où vous demandez au navigateur du client de télécharger uniquement les images en fonction de ses besoins. Cela conduit à d'énormes améliorations de performances, car les périphériques clients ne gaspillent pas de bande passante en téléchargeant des actifs qui ne sont pas rendus. Pour ce faire, nous utiliserons certains mécanismes côté client de css-tricks.com et les prendrons en charge avec le balisage approprié du CMS Episerver.

Images de premier plan et images d'arrière-plan

Quand on parle d'imagerie utilisées sur les sites Web, nous devons réfléchir aux façons dont ces images sont réellement utilisées. Une image de premier plan est votre balise d'image traditionnelle que vous apprenez en HTML 101. Il s'agit de la manière standard dont une image est rendue à l'écran.

L'imagerie d'arrière-plan, cependant, est une image qui est chargée via CSS et appliquée par le style. Pensez à une balise

avec une propriété background-image insérée dessus. Ceci est généralement utilisé pour les images de grandes bannières avec des superpositions de texte.

Dans les deux cas, ce que nous devons faire est de créer notre réponse HTML provenant du serveur pour prendre en charge une technique de traitement d'image paresseuse en Javascript.

Front- end Mechanics

La manière standard dont vous serviriez une image sur votre site Web serait d'implémenter une balise comme ceci:

La triste réalité derrière cette balise d'image, c'est que dès que le client est le navigateur le voit – il tentera de charger l'actif à l'attribut src . Même si cette image se trouve dans le pied de page d'une longue page, elle sera téléchargée immédiatement.

Pour empêcher ce téléchargement, ce que nous pouvons faire est de sortir le balisage d'une manière différente du côté serveur:

Remarque dans ce cas où nous n'avons pas produit du tout une propriété src. Au lieu de cela, nous sortons data-src. Le navigateur ne sait pas comment gérer cela et affiche généralement cette balise img sous la forme d'une "miniature cassée" (si nous l'avons autorisé). Parce que nous mettons une classe CSS de .lazy sur l'image, nous pouvons styliser cette image pour qu'elle soit cachée au cas où quelqu'un la ferait défiler sans Javascript.

 SAS IDC Episerver Commerce Guide

] Dans la section Head de votre document, ajoutez ceci à votre CSS critique:

Maintenant vient la partie amusante – nous devons exécuter un peu de Javascript côté client pour traiter nos images et tromper le navigateur en les chargeant à mesure qu'elles défilent dans la vue. Pour ce faire, utilisez un extrait de code comme celui-ci:

 function lazyload () {
    if (lazyloadThrottleTimeout) {
        clearTimeout (lazyloadThrottleTimeout);
    }
    lazyloadThrottleTimeout = setTimeout (function () {
        var lazyElements = document.querySelectorAll (". lazy");
        var scrollTop = window.pageYOffset;
        Array.prototype.forEach.call (lazyElements, function (elem) {
            // à moins de 100 pixels du bas de l'écran
            if (elem.offsetTop - 100 <(window.innerHeight + scrollTop)) {
                if (elem.dataset.src) {
                    // trouve n'importe quel data-src et le change en src
                    elem.src = elem.dataset.src;
                }
                elem.classList.remove ("paresseux");
            }
        });
        if (lazyElements.length == 0) {
            document.removeEventListener ("scroll", lazyload);
            window.removeEventListener ("redimensionner", lazyload);
            window.removeEventListener ("orientationChange", lazyload);
        }
    }, 20);
}
document.addEventListener ("scroll", lazyload);
window.addEventListener ("redimensionner", lazyload);
window.addEventListener ("orientationChange", lazyload);
lazyload (); // allez-y et invoquez au chargement de la page 

Dans ce cas, nous définissons une fonction lazyload () qui est utilisée comme rappel pour le scroll resize et orientationChange événements. Nous invoquons également directement cette fonction lors du chargement de la page, juste au cas où des images différées se trouveraient au-dessus du pli. Tout ce que Javascript fait est une boucle à travers le DOM et trouve chaque élément avec une classe de paresseux . Pour chaque objet trouvé, s'il se trouve dans la fenêtre, la classe lazy est supprimée et data-src est échangé contre src . C'est le cœur des images de chargement paresseux, et à partir de maintenant, nous devons simplement élaborer nos réponses côté serveur en conséquence. En guise de note latérale intéressante, il peut être extrêmement difficile de déterminer la fenêtre d'affichage du périphérique client du côté serveur, je recommande donc uniquement les images à chargement paresseux situées après les premiers ~ 1000 pixels de la hauteur de l'écran.

Notez également que pour nos images de fond c'est la même technique. Nous devons prendre ce balisage:

 

et à la place, rendez-le ainsi:

 

Avec le CSS que nous avons inséré dans la tête de nos documents, la classe .lazy prévaudra et forcera la propriété d'image d'arrière-plan à aucun! Important; . 19659002] Techniques d'Episerver Back-end

Jusqu'à ce point, nous avons parlé de la façon de faire fonctionner le chargement paresseux sur le front-end. Cette technique s'applique à une grande variété de technologies Web et peut être réalisée avec une multitude de plates-formes. Tout ce que nous avons à faire est d'obtenir le back-end pour rendre le balisage en conséquence.

Heureusement dans Episerver, contrôler la manière dont les images sont rendues est incroyablement facile. Tout d'abord, nous devons nous assurer que nous avons créé un DisplayTemplate pour nos fichiers image: ~ / Views / Shared / DispalyTemplates / Image.cshtml . Ce fichier indiquera à Episerver comment rendre le balisage d'une image. Dans mon cas, Image.cshtml ressemble à ceci ( en supposant que nous suivons Alloy… ):

 @using EPiServer.Editor
@model ImageViewModel

@if (Modèle! = null)
{
    var lazy = ViewBag.lazy ?? vrai;

    if (PageEditing.PageIsInEditMode ||! lazy)
    {
        
    }
    autre
    {
        
    }
} 

L'élément critique ici est que je passe un drapeau "paresseux" dans le ViewBag pour contrôler si l'image doit être chargée paresseusement ou non. Ceci est important pour les éléments tels que Heroes, où ils sont toujours présents au-dessus du pli et que vous voulez qu'ils se chargent aussi vite que possible.

Voici comment vous pouvez l'utiliser:

 @ * Ne sera pas paresseux chargé ... * @
@ Html.PropertyFor (x => x.CriticalImage, new {lazy = false})

@ * Sera chargé paresseusement ... * @
@ Html.PropertyFor (x => x.LazyImage)

Correction du texte enrichi Episerver

Une chose à noter: l'éditeur Episerver Rich Text TinyMCE n'utilise pas les modèles d'affichage pour le rendu des images. Il a ses propres mécanismes internes pour ce faire. Heureusement, nous pouvons contourner ce problème en appliquant une technique similaire: création d'un modèle d'affichage pour les types de propriété XhtmlString .

Create ~ / Views / Shared / DispalyTemplates / XhtmlString.cshtml to prenez le contrôle de la façon dont le texte enrichi est rendu et ajoutez du code similaire à celui-ci:

 @using EPiServer.Core
@model XhtmlString

@ Html.Raw (Model.FormatRichText (ViewContext)) 

À partir d'ici, notre méthode d'extension FormatRichText () peut gérer le rendu du balisage, saisir le résultat et l'ajuster avant de l'envoyer au client . J'utilise HtmlAgilityPack pour analyser le résultat HTML. Voici ma méthode d'extension:

 classe statique publique XhtmlStringExtensions
{
    /// 
    /// Analyse le XhtmlString pour les balises Image et les définit sur lazy load
    /// 
    chaîne statique publique FormatRichText (ce XhtmlString html, contexte ViewContext)
    {
        // html est nul lorsque le TinyMce n'est pas initialisé (création d'un nouveau bloc, etc.)
        if (html == null) return string.Empty;

        // Chargez HtmlHelper d'Epi et demandez-lui de rendre les résultats
        var hh = new HtmlHelper (contexte, nouveau ViewPage ());

        string epiRenderingResult;

        en utilisant (var writer = new StringWriter ())
        {
            hh.ViewContext.Writer = écrivain;
            hh.RenderXhtmlString (html);
            écrivain.Flush ();
            epiRenderingResult = writer.ToString ();
        }

        if (PageEditing.PageIsInEditMode)
            return epiRenderingResult;

        // une fois les résultats rendus, chargez HtmlAgilityPack et faites-le analyser les résultats

        var doc = nouveau HtmlDocument ();
        doc.LoadHtml (epiRenderingResult);

        // trouve toutes les balises d'image, s'il n'y en a pas, retourne simplement - sinon nous devons les ajuster

        var imgs = doc.DocumentNode.SelectNodes ("// img");
        si (imgs == null)
            return epiRenderingResult;

        // pour chaque image, remplacez src par data-src et lancez la classe "paresseuse" dessus
        foreach (var img dans imgs)
        {
            var src = img.Attributes ["src"] ?. Value;
            if (! string.IsNullOrEmpty (src))
            {
                // pour prendre en charge le chargement paresseux, nous devons échanger src pour data-src
                // et injecter une classe de "paresseux". Javascript le prendra à partir de là
                img.SetAttributeValue ("données-src", src);
                img.Attributes.Remove ("src");

                var css = img.Attributes ["class"] ?. Valeur;
                img.SetAttributeValue ("classe", $ "lazy {css}". Trim ());
            }
        }

        var externalHtml = doc.DocumentNode.OuterHtml;
        return externalHtml; // retourne le nouveau HTML résultant
    }
} 

Enjoy 🙂

À propos de l'auteur <! -: dmccurry, Architecte de solutions ->

Je suis un développeur Sitecore certifié, un singe de code et un nerd général. J'ai sauté dans l'espace .NET il y a 10 ans pour travailler sur des applications de classe entreprise et je n'ai jamais regardé en arrière. J'adore créer des choses, des Legos aux logiciels qui résolvent de vrais problèmes. Ai-je mentionné que j'aime les jeux vidéo?

Plus de cet auteur






Source link