Entendiendo el rendimiento

1

Todo lo que aprenderás sobre optimización web

2

¿Vale el esfuerzo optimizar un sitio web?

3

¿Cuándo realmente un sitio es rápido o lento?

Antes de optimizar...

4

Aprendiendo a medir

5

User Performance Metrics

6

Nuestro proyecto

Crítical Rendering Path

7

Etapas de render del navegador

8

Network waterfall y recursos que bloquean el navegador

9

Priorización de recursos

10

Preloading y prefetching de recursos

11

Fases Paint y Layout del Critical Render Path

CSS

12

Detectando Paints costosos y optimizando animaciones

13

Bloqueos y complejidad en selectores

WebFonts

14

WebFonts y su impacto en rendimiento

Imágenes, Iconos y SVG

15

Imágenes, formato y compresión

16

Imágenes y compresión

17

¿WebFont, Imagen o SVG?

18

Técnicas avanzadas con Lazy Loading

19

Técnicas avanzadas con Responsive Loading

Aplicaciones JavaScript

20

JavaScript y aplicaciones modernas y Utilizando un servidor de producción

21

Analizando el bundle de la aplicación

22

Reduciendo el tamaño del bundle

23

Code Splitting

24

Lazy Module Loading

25

Llevando los listeners a otro nivel

26

Instalando Modal video

27

Lazy loading del modal

28

Moviendo la carga de rendering hacia el servidor: Server Side Rendering

29

Aplicando SSR

30

Pre-renderizando el contenido: Static Generation

Caché

31

Cómo funciona el Caché de recursos y CDN

32

Deploy en Netlify y automatización de contenido en GitHub Actions

33

Aplicando Github Actions

34

Interceptando los requests del navegador con Service Workers

Performance Budget

35

Performance budget y auditorias automatizadas

36

Automatizando una auditoría con Lighthouse CI

37

Medidas reales y monitoreo constante

Conclusiones

38

Conclusiones

No tienes acceso a esta clase

¡Continúa aprendiendo! Únete y comienza a potenciar tu carrera

Técnicas avanzadas con Lazy Loading

18/38
Recursos

Aportes 17

Preguntas 1

Ordenar por:

¿Quieres ver más aportes, preguntas y respuestas de la comunidad?

Implementado https://www.npmjs.com/package/vanilla-lazyload:

Instalar con el comando:
npm i vanilla-lazyload

CarouselItem.js:

import h from 'hyperscript'
import moment from 'moment'

const relativeDate = dateStr => moment(dateStr, 'YYYY-MM-DD').fromNow()

const Controls = ({ slug, youtubeVideoId }) =>
  h(
    'div',
    h(
      'a',
      {
        href: `https://www.youtube.com/watch?v=${youtubeVideoId}`,
        title: 'Watch trailer',
        target: '_blank',
        rel: 'noreferrer',
      },
      h('img.carousel-item__details--img', {
        src: 'assets/play-icon.png',
        alt: 'Play',
      })
    ),
    h(
      'a',
      {
        href: `https://kitsu.io/explore/anime/${slug}`,
        title: 'See more',
        target: '_blank',
        rel: 'noreferrer',
      },
      h('img.carousel-item__details--img', {
        src: 'assets/plus-icon.png',
        alt: 'More info',
      })
    )
  )

const CarouselItem = ({
  imageUrl,
  title,
  subtitle,
  slug,
  youtubeVideoId,
  startDate,
}) =>
  h(
    'div.carousel-item',
    h('img.carousel-item__img.lazy', { 'data-src': imageUrl, alt: '' }),
    h(
      'div.carousel-item__details',
      Controls({ slug, youtubeVideoId }),
      h('p.carousel-item__details--title', title),
      h('p.carousel-item__details--subtitle', subtitle),
      h(
        'p.carousel-item__details--date',
        `Released: ${relativeDate(startDate)}`
      )
    )
  )

export default CarouselItem

index.js:

import h from 'hyperscript'
import { fetchPopular, fetchHighestRated, fetchTrending } from './api'
import CarouselItem from './CarouselItem'
import LazyLoad from 'vanilla-lazyload'

var lazyLoadInstance = new LazyLoad({
  // Your custom settings go here
})

const SectionTitle = title => h('h3.carousel__title', title)

const Carousel = ({ itemsList = [] }) =>
  h(
    'section.carousel',
    h(
      'div.carousel__container',
      itemsList.map(
        ({
          attributes: { titles, posterImage, slug, youtubeVideoId, startDate },
        }) =>
          CarouselItem({
            imageUrl: posterImage.medium,
            title: titles.en,
            subtitle: titles.ja_jp,
            slug,
            youtubeVideoId,
            startDate,
          })
      )
    )
  )

!(async function(document) {
  const mountReference = document.querySelector('.main').lastElementChild

  if (!mountReference) {
    return 0
  }

  const trending = await fetchTrending()
  const popular = await fetchPopular()
  const highestRated = await fetchHighestRated()

  mountReference
    .insertAdjacentElement('afterend', SectionTitle('Trending Anime'))
    .insertAdjacentElement(
      'afterend',
      Carousel({
        itemsList: trending,
      })
    )
    .insertAdjacentElement('afterend', SectionTitle('Highest Rated Anime'))
    .insertAdjacentElement(
      'afterend',
      Carousel({
        itemsList: highestRated,
      })
    )
    .insertAdjacentElement('afterend', SectionTitle('Most Popular Anime'))
    .insertAdjacentElement(
      'afterend',
      Carousel({
        itemsList: popular,
      })
    )

  lazyLoadInstance.update()
})(document, window)

👨‍🚀 Técnicas avanzadas con Lazy Loading

<h4>Ideas/conceptos claves</h4>

Intersection observer es una API del navegador la cual ve cuales son los elementos visibles del documento y según a esa información genera eventos

<h4>Recursos</h4>

eloquent-joliot-wcc52

ApoorvSaxena/lozad.js

Can I use… Support tables for HTML5, CSS3, etc

<h4>Apuntes</h4>
  • Existen lazy loading de carga y de progresión
  • Medium aplica una técnica de lazy loading en las imágenes
    • Al principio nos aparecerá una imagen borrosa y pixelada hasta que la tengamos lista y sea visible en pantalla
    • Ira progresivamente mejorando la imagen
  • El lazy loading de carga, trata de cargar las imágenes cuando la imagen sea de carga
    • Esto es conveniente para ahorrar recursos a los usuarios
  • Existen tres formas de hacer lazy loading de carga
<h3>De forma nativa</h3>

El navegador se encargará de hacerlo de forma automática

<img src="..." loading="lazy" alt="..." />

Ventajas

  • Nativo
  • Facil
  • Conveniente
  • Video, iframes

Desventajas

  • Es tan nuevo, que tiene poco soporte (actualmente)
<h4>Intersection Observer</h4>

Ventajas

  • Técnicamente más correcto (luego de nativo)
  • Relativamente fácil

Desventajas

  • No soportado por internet explorer
  • Versión 2 en proceso
<h3>Scroll Listener</h3>

ventajas

  • Soportado en todos los navegadores

Desventajas

  • Scroll listener
  • Muchos cálculos por evento

RESUMEN: Para poder cargar las imágenes dinámicamente tenemos diferentes alternativas, en cada una debemos considerar el soporte que tiene con los navegadores y como lo implementaremos en el proyecto

One Piece ❤️

Ya es muy factible utilizar lazy loading en nuestos proyectos. (Excepto safari, todavia es un feature experimental)

Dejo aquí otra librería de lazy loading, facil de implementar https://github.com/aFarkas/lazysizes

Vengo del curso de manejo del DOM y se nota mucho que te gusta el metodo del “Intersection Observer” ❤️

La buena noticia es que esta mejor soportada la opción de loading= “lazy” 3 años después.

Aquí les dejo una forma alternativa de hacer el lazy loading:

const imgs = document.querySelectorAll("div.carousel-item__img");
  imgs.forEach((img) => {
    const observer = new IntersectionObserver((entries) => {
      if (entries[0].isIntersecting) {
          img.setAttribute("style", `
            background-image: url("${img.dataset.src}");
            background-size: cover;
            background-position: center;
          `);
      } else
        img.removeAttribute("style");
    });
    observer.observe(img);
  });

Luego de un tiempo pude implementar el lazy loading con a estrategia del CodeSandbox que dejó el profesor:

  1. Lo primero que hice fue modificar la función carouselItem para que las imágenes tuvieran la clase .lazy y la url de la imagen quedara guardada en el dataset.
const imgObject =  { alt: ''}
  imgObject['data-src'] = imageUrl
  const codigo = 
  h('div.carousel-item',
    h('img.carousel-item__img.lazy', imgObject),
    h('div.carousel-item__details',
      Controls({ slug, youtubeVideoId }),
      h('p.carousel-item__details--title', title),
      h('p.carousel-item__details--subtitle', subtitle),
      h('p.carousel-item__details--date', `Released: ${relativeDate(startDate)}`)
    )
  )

  return codigo
>```



2. Luego en el index.js, en la parte de arriba justo después de los imports, cree una función que contiene la lógica del Lazy Loading:



```<
function imgLazyLoad (){
  const isIntersecting = intersectionEntry => intersectionEntry.isIntersecting

  let lazyImageObserver = new IntersectionObserver (entries => {entries.filter(isIntersecting).forEach(loadImage)})
    
  function loadImage (intersectionEntry) {
    const lazyImage = intersectionEntry.target
    lazyImage.src = lazyImage.dataset.src
    lazyImage.classList.remove('lazy')
    lazyImageObserver.unobserve(lazyImage)
  }
    
  const lazyImages = [...document.querySelectorAll('img.lazy')]
  lazyImages.forEach(lazyImage => lazyImageObserver.observe(lazyImage)) 

}
>```



3. Por último, dentro de la IIFE asíncrona principal justo después del crear los carousel, puse el siguiente código que ejecuta la función del punto 2.



```<
if (document.readyState === "complete"){
    imgLazyLoad()
  } else {
    document.addEventListener("DOMContentLoaded", imgLazyLoad)
  }
>```


Un hilo muy interesante de qué es un throttle para implementarlo con el scroll event.
Hilo

Use lozad.js 😊

lo instale con:

npm install --save lozad

y agrege en el HTML:

<script type="text/javascript" src="https://cdn.jsdelivr.net/npm/lozad/dist/lozad.min.js"></script>

en CarouselItems.js modifique la etiqueta de img, le agregue una clase y cambie el src por data-src

h('img.carousel-item__img.lozad', { 'data-src': imageUrl, alt: '' }),

en styles.css agregue

.fade {
  animation-name: fade;
  animation-duration: 2s;
}

@keyframes fade {
  from {
    opacity: 0;
  }
  to {
    opacity: 1;
  }
}

y agregue este codigo al final de la funcion anonima del index.js:

lozad('.lozad', {
    load: function(el) {
      el.src = el.dataset.src
      el.onload = function() {
        el.classList.add('fade')
      }
    },
  }).observe()

Aqui pueden ver una explicacion de lozad y un ejemplo: https://css-tricks.com/lozad-js-performant-lazy-loading-images/

Debouncing o Throttling son técnicas que nos permiten reducir el impacto de Perfomance causado por los eventos del scroll. Dejo un enlace a un articulo que los explica,

También dejo este video del Dev Web Simplified que lo explica de manera practica y bastante clara

Necesitamos que el loading=“lazy” sea soportado por todo los navegadores ajajaja

Mi implementacion de Lazy Loading con I.O.
Codigo: GitHub

Debo decir que por alguna razon que desconozco no me funciono con google chrome de ubuntu

Yo implementé un intersection observer👀

  const options = {
    rootMargin: '10px',
    threshold: 0.2,
  }
  const imagesObserver = new IntersectionObserver(elements => {
    elements.forEach(entry => {
      const image = entry.target.querySelector('img')
      if (entry.isIntersecting) {
        image.style.display = 'block'
        imagesObserver.unobserve(image)
      } else {
        image.style.display = 'none'
      }
    })
  }, options)
  carouselItems.forEach(img => imagesObserver.observe(img))

  return h('section.carousel', h('div', carouselItems))

Estaba viendo el performance de medium y veo que es super bajo miren nomas el trace