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 14

Preguntas 1

Ordenar por:

驴Quieres ver m谩s aportes, preguntas y respuestas de la comunidad?

o inicia sesi贸n.

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

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

One Piece 鉂わ笍

Vengo del curso de manejo del DOM y se nota mucho que te gusta el metodo del 鈥淚ntersection Observer鈥 鉂わ笍

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=鈥渓azy鈥 sea soportado por todo los navegadores ajajaja

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

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);
  });

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