Optymalizacja szablonu i samego sklepu na Shoperze to długi i ciężki temat. Saas jakim jest Shoper (czyli usługa w formie abonamentu) powoduje, że dla laika wszystko jest super: kliknij tu, przejdź tam, dodaj produkt i sprzedawaj!
Ale im więcej się człowiek zagłębia w rzeczywistą architekturę sklepu tym więcej ścian napotyka. No bo to co wystarczy laikowi często jest niewystarczające wyjadaczowi.
Dzisiaj zakładam, że jesteś takim średniakiem. Że trochę już wiesz o poruszaniu się po sklepie na Shoperze, ale jeszcze nie jesteś wyjadaczem, bo wtedy po co Ci nasza instrukcja :)
Kopia Zapasowa
Wykonasz ją w 45 sekund. W nieco ponad dwie minuty jeśli nie wiesz o czym mowa i będziesz musiał/a doczytać na przykład tutaj:
Zanim zaczniesz modyfikować szablon na Shoperze
To nie boli, nie zajmuje Ci cennego miejsca, a jak (na szczęście) nigdy Ci się do niczego nie przyda to i usuniesz ją w te 15 sekund. Wykonaj kopię zapasową swojej obecnej skórki dla świętego spokoju.
Teoria Lazy Loading
Lazy load / loading to parafrazując takie zoptymalizowane ładowanie. No bo po co ładować np. grafiki wszystkich bestsellerów na stronie głównej jeśli tam przed tym jest jeszcze dziesięć innych modułów.
W takiej sytuacji możemy tak to przerobić, żeby zdjęcia nie były ładowane przy ładowaniu całego sklepu -> czyli wydłużając czas ładowania. Oddalone zdjęcia możemy załadować, dopiero gdy będą potrzebne. Sprytne prawda?
Google PageSpeedInsights
Ludzie od zawsze ganiali za jakimiś cyferkami. Czy to na koncie w banku, czy w ilości koni mechanicznych. Obecnie nowocześni właściciele biznesów ścigają właśnie cyferki w PSI czyli narzędziu od Google, które ocenia jak szybką masz stronę / sklep.
Jest to ważne z dwóch powodów:
1. Google stara się, aby internet był przystępny. Czy masz najnowszego xiaomi czy starszą motorolę: żebyś mógł/a wygooglać sobie informację i żeby ona jako tako się wyświetliła bez znaczenia na wartość urządzenia. W związku z tym same testy są dość restrykcyjne bo zakładają takie urządzenie o średnim budżecie około $150 z ograniczonym łączem.
2. Google niejako powiązał (lub nadal próbuje) Twoje miejsce w wynikach wyszukiwarki (SEO) z tym jak dobry masz content (treści) jak to było od zawsze + linkowanie (czyli też po staremu) + teraz optymalizacja!
Optymalizacja czyli czy masz dobrze kolory dobrane (widoczność), czy masz podświetlenie dla ekranów dla niepełnosprawnych (dostępność), czy użytkownik nie czeka zbyt długo na załadowanie treści (prędkość) i kilka innych ciekawych elementów.
No i mniej więcej dlatego obecnie czasami warto ścigać te cyferki. Jak w tym teście na Shoperze masz około 10 punktów - no to ścigaj mocno bo to bardzo słaby wynik. Jak masz około 30 - jesteś średniak, ale moim zdaniem to wystarczy. W kontekście autoreklamy - szablon Modern 3.0 wyciska 50 punktów bez wspomagaczy. 65 ze wspomagaczami takimi jak Cloudflare.
Lozad
Takich bibliotek do optymalizacji prędkości i adekwatnie do lazy loadingu jest sporo na rynku. My w tym poradniku wykorzystamy Lozad. Ten sam sposób / kod wykorzystany jest w naszym szablonie, jak dla mnie bardzo solidny i dość uniwersalny.
Główny Skrypt
Skopiuj sobie główny kod całej biblioteki. Biblioteka, bo to taki skrypt, ale dłuższy, bardziej skomplikowany. W obrębie tego kodu nie wnoś żadnych poprawek.
W panelu swojego sklepu przejdź kolejno do "Wygląd i treści" -> "Wygląd sklepu" -> "Twoje szablony graficzne" i wybierz swoją kopię - na niej będzie najbezpieczniej pracować.
Wybierz drugi ołówek z rzędu. Ołówek nie pokaże Ci się, jeśli nie pracujesz na kopii i używasz oryginalnej wersji sklepu - kupionego szablonu czy szablonu podstawowego. Więc wróć do punktu pierwszego i wykonaj kopię zapasową :) Potem nadganiaj.
W nowo otwartym okienku nawiguj po lewej stronie do folderu "js" (powinien być drugi od góry). Tam znajdziesz user.js (NIE POMYL z main.js - jeśli widzisz main.js to zamknij to okienko w prawym górnym rogu i Ty korzystaj z edytora wybierając z szarego pola "Własny skrypt JS". Szlachta ma duży edytor, Ty niestety masz malutki. Hehe ).
Jeśli w naszym edytorze masz już jakiś kod - własny czy szablonu, to najbezpieczniej jest zjechać na sam dół, dodać za ostatnimi znakami trochę enterów żeby zrobić sobie miejsce i tam wklejamy naszą bibliotekę. Skopiuj ją sobie z miejsca poniżej lub kliknij tutaj, a skopiujesz sobie kod z CodePena.
/*! lozad.js - v1.16.0 - 2020-09-06 * https://github.com/ApoorvSaxena/lozad.js * Copyright (c) 2020 Apoorv Saxena; Licensed MIT */ !function(t,e){"object"==typeof exports&&"undefined"!=typeof module?module.exports=e():"function"==typeof define&&define.amd?define(e):t.lozad=e()}(this,function(){"use strict"; /** * Detect IE browser * @const {boolean} * @private */var g="undefined"!=typeof document&&document.documentMode,f={rootMargin:"0px",threshold:0,load:function(t){if("picture"===t.nodeName.toLowerCase()){var e=t.querySelector("img"),r=!1;null===e&&(e=document.createElement("img"),r=!0),g&&t.getAttribute("data-iesrc")&&(e.src=t.getAttribute("data-iesrc")),t.getAttribute("data-alt")&&(e.alt=t.getAttribute("data-alt")),r&&t.append(e)}if("video"===t.nodeName.toLowerCase()&&!t.getAttribute("data-src")&&t.children){for(var a=t.children,o=void 0,i=0;i<=a.length-1;i++)(o=a[i].getAttribute("data-src"))&&(a[i].src=o);t.load()}t.getAttribute("data-poster")&&(t.poster=t.getAttribute("data-poster")),t.getAttribute("data-src")&&(t.src=t.getAttribute("data-src")),t.getAttribute("data-srcset")&&t.setAttribute("srcset",t.getAttribute("data-srcset"));var n=",";if(t.getAttribute("data-background-delimiter")&&(n=t.getAttribute("data-background-delimiter")),t.getAttribute("data-background-image"))t.style.backgroundImage="url('"+t.getAttribute("data-background-image").split(n).join("'),url('")+"')";else if(t.getAttribute("data-background-image-set")){var d=t.getAttribute("data-background-image-set").split(n),u=d[0].substr(0,d[0].indexOf(" "))||d[0];// Substring before ... 1x u=-1===u.indexOf("url(")?"url("+u+")":u,1===d.length?t.style.backgroundImage=u:t.setAttribute("style",(t.getAttribute("style")||"")+"background-image: "+u+"; background-image: -webkit-image-set("+d+"); background-image: image-set("+d+")")}t.getAttribute("data-toggle-class")&&t.classList.toggle(t.getAttribute("data-toggle-class"))},loaded:function(){}};function A(t){t.setAttribute("data-loaded",!0)}var m=function(t){return"true"===t.getAttribute("data-loaded")},v=function(t){var e=1<arguments.length&&void 0!==arguments[1]?arguments[1]:document;return t instanceof Element?[t]:t instanceof NodeList?t:e.querySelectorAll(t)};return function(){var r,a,o=0<arguments.length&&void 0!==arguments[0]?arguments[0]:".lozad",t=1<arguments.length&&void 0!==arguments[1]?arguments[1]:{},e=Object.assign({},f,t),i=e.root,n=e.rootMargin,d=e.threshold,u=e.load,g=e.loaded,s=void 0;"undefined"!=typeof window&&window.IntersectionObserver&&(s=new IntersectionObserver((r=u,a=g,function(t,e){t.forEach(function(t){(0<t.intersectionRatio||t.isIntersecting)&&(e.unobserve(t.target),m(t.target)||(r(t.target),A(t.target),a(t.target)))})}),{root:i,rootMargin:n,threshold:d}));for(var c,l=v(o,i),b=0;b<l.length;b++)(c=l[b]).getAttribute("data-placeholder-background")&&(c.style.background=c.getAttribute("data-placeholder-background"));return{observe:function(){for(var t=v(o,i),e=0;e<t.length;e++)m(t[e])||(s?s.observe(t[e]):(u(t[e]),A(t[e]),g(t[e])))},triggerLoad:function(t){m(t)||(u(t),A(t),g(t))},observer:s}}}); $(document).on("ready", function() { if (!('IntersectionObserver' in window) || !('IntersectionObserverEntry' in window) || !('intersectionRatio' in window.IntersectionObserverEntry.prototype)) { $("img.lozad").each(function() { $(this).attr("src", $(this).attr("data-src")); }); } else { var observer = lozad('.lozad', { threshold: 0.1 // ratio of element convergence }); observer.observe(); } }); $(window).on("pageshow", function(event) { if (event.originalEvent.persisted) { console.log('page loaded from cache'); } function handleImages() { var imgs = $(document).find('img.clicked'); if (imgs.length) { $(document).find('img.clicked').each(function() { $(this).removeClass('fadeOut').attr('data-hovered', 'false').attr('src', $(this).attr('data-src')) }); } } $('.replace-img-list img').on('click', function() { $(this).addClass('clicked'); }); $(window).on("beforeunload pagehide", function() { setTimeout(function() { handleImages(); }, 2000); }); $(window).on("pageshow popstate", function(event) { if (event.originalEvent.persisted) { setTimeout(function() { handleImages(); }, 1); } }); });
Po wklejeniu naszej biblioteki w bezpiecznym miejscu z dala od reszty kodu kliknij "Zapisz" w prawym górnym rogu.
Użycie lozad na Shoperze
Użycie jest super proste. Wystarczy, że dodasz klasę .lozad oraz zamienisz domyślny src na taki z dopiskiem czyli data-src.
Robimy przykład. Zastaję gdzieś zdjęcie - załóżmy że to nasz moduł z banerem z płatnościami. Klikam edytuj w naszym module i widzę w środku (po wyłączeniu edytora):
Tu poniżej przepiszę to samo w formie kodu, żeby pokazać przed i po:
<img src="/skins/user/rwd_primary_4/images/user/shoper-platnosci.jpg" alt="" />
I zgodnie z naszym przepisem. Sprawdzam czy nasz element graficzny czyli
<img class="lozad" data-src="/skins/user/rwd_primary_4/images/user/shoper-platnosci.jpg" />
I tyle. Jeśli włączysz edytor to zdjęcie się nie wyświetli - zgodnie z planem! Zapisz moduł i przejdź do strony głównej zawierającej moduł - sprawdź czy wszystko ładnie się wyświetliło.
W ten sam sposób możesz edytować grafiki w opisie produktu, kategorii, we wpisie bloga ale także w plikach TPL! Czyli optymalizować to co serwuje nam sklep.
Grafika miniatura - Blog
Przejdź ponownie do naszego drugiego ołówka naszej kopii zapasowej. Czyli "Wygląd i treści" -> "Wygląd sklepu" -> "Twoje szablony graficzne" i wybierz swoją kopię klikając wspomniany drugi ołówek czyli Edytor HTML / CSS.
W nowym oknie nawiguj do folderu "Scripts" -> "News" i znajdź "listofarticles.tpl". Ten moduł odpowiada za wyświetlanie zbiorcze artykułów bloga, które umieściłeś/aś na stronie głównej tym pstryczkiem na liście wpisów:
Po znalezieniu naszego pliku "listofarticles.tpl" kliknij w niego. Otworzy Ci się edytor, w którym możesz kliknąć na górze "lupkę" i wyszukać:
article-image
Podświetli Ci się jeden element:
No i tam nie ma nic bardziej niezwykłego niż to co omówiliśmy. Mamy nasz IMG czyli zdjęcie, jest klasa już napisana, więc tylko dopiszemy naszą i jest src, które przerobimy na data-src.
Przeklejam to co na obrazie, żeby nam ładnie wyszło przed i po. Znalazłeś/aś tam taki kod:
<img class="article-image" src="{baseDir}/{$article->image}" alt="{$article->article->image_name|escape}">
Po klasie article-image dodaję spację i dopisuję lozad. Do src przyklejam przedrostek i powstaje data-src.
<img class="article-image lozad" data-src="{baseDir}/{$article->image}" alt="{$article->article->image_name|escape}">
Resztę zostaw bez zmian na ten moment. W prawym górnym rogu kliknij zapisz i obok masz trybik, X oraz lupkę - podgląd. Kliknij podgląd aby zobaczyć zmiany. Jeśli masz włączone artykuły to ich zdjecia powinny zostać zaczytane dopiero gdy będziesz bardzo blisko tej grafiki.
Podsumowanie
Użycie biblioteki lozad do zaimplementowania lazy loadingu jest stosunkowo proste. Mało jest miejsc gdzie się można pomylić.
Z ważnych kwestii: taka przeróbka naszego pliku tpl spowoduje, że ten nie przejdzie samoistnie aktualizacji od Shopera. Inna kwestia co tam aktualizować w taki głębokich zakątkach szablonu :)
Moim zdaniem jeśli aktywnie prowadzisz bloga - ta gra jest warta świeczki i implementacji. Adekwatnie możesz to dodać... wszędzie! Do galerii, do bestsellerów, nowości i promocji. Do logo producenta.
Nie dodawaj jedynie do elementów, które muszą załadować się na samym początku strony, bo sam sobie zepsujesz statystyki w PSI opóźniając wskaźniki pierwszego ładowania. Nie dodawaj więc lozad do logo sklepu, do głównego slidera czy do grafiki otwierającej np. wpis blogowy. Dodaj do każdej poniżej.
Jeśli jesteś właścicielem Modern 3.0 to nie musisz robić powyższego. Wszystko masz już w szablonie + to my odpowiadamy za aktualizację Twoich plików, jeśli Shoper zdecyduje się tam coś dodać.
Witek
Czy udałoby się dodać jakiś loader, który pokazuje się na chwilkę kiedy zdjęcie się jeszcze ładuje?