Gestión avanzada de assets en WordPress

Disclaimer

Disclaimer

 

Soy responsable de lo que digo, no de lo que vosotros interpretéis

La velocidad es importante

 

Las grandes empresas invierten mucho dinero y recursos en optimizar los tiempos de carga de sus páginas. Un tiempo alto aumenta la tasa de abandono y empeora la experiencia de tu usuario/cliente.

WPO Stats

The Need for Mobile Speed

El ser humano es impaciente

Video Speed

¿Qué elementos pesan más en mi web?

Peso de la página

El peso medio de una web ronda los 3MB. Más información en SpeedCurve

Menos es más

 

La petición HTTP más rápida es aquella que no se hace. Piensa si "eso" es realmente necesario.

Verdad verdadera

Regla del 80 / 20

 

Conseguir el 80% de la optimización consume el 20% del esfuerzo, y el 20% restante de optimización nos supondrá el 80% del esfuerzo

Vilfredo Pareto

90 / 10

Las 9 reglas de Google

Optimizar el desarrollo y la gestión de tus recursos estáticos (Imágenes, CSS y JS) influirá en la velocidad de carga y rendimiento de tu página web.

  • Evitar redirecciones a páginas de destino

  • Habilitar la compresión

  • Mejorar el tiempo de respuesta del servidor

  • Aprovechar el almacenamiento en caché de los navegadores

  • Minificar recursos

  • Optimizar imágenes

  • Optimizar la entrega de CSS

  • Priorizar el contenido visible

  • Quitar el JavaScript que bloquea el renderizado del contenido

Enlace a la página de desarrolladores de Google

Habilitar la compresión


Esta regla se activa cuando PageSpeed Insights detecta que se han publicado recursos comprimibles sin compresión gzip.

Al habilitar la compresión gzip, se puede reducir el tamaño de las respuestas hasta en un 90%. Esto disminuye significativamente el tiempo de descarga de los recursos, y reduce el uso de datos del cliente y el tiempo que se tarda en renderizar las páginas por primera vez.

  • Apache: usa mod_deflate (algoritmo de compresión de datos sin pérdidas).
  • Nginx: usa ngx_http_gzip_module.
  • IIS: configura la compresión HTTP.

Habilitar la compresión

Ejemplos

A continuación un listado de recursos y su peso antes y después de comprimir con gzip.

Más información en la página de desarrolladores de Google

Biblioteca Tamaño Tamaño GZIP Compresión
jquery-1.11.0.js 276 kB 82 kB 70%
jquery-1.11.0.min.js 94 kB 33 kB 65%
angular-1.2.15.js 729 kB 182 kB 75%
angular-1.2.15.min.js 101 kB 37 kB 63%
bootstrap-3.1.1.css 118 kB 18 kB 85%
bootstrap-3.1.1.min.css 98 kB 17 kB 83%
foundation-5.css 186 kB 22 kB 88%
foundation-5.min.css 146 kB 18 kB 88%

Habilitar la compresión

Configuración en apache (.htaccess)

Reduce el tamaño de los ficheros enviados desde tu servidor, reduciendo así el tiempo que tardan en transferirse. Añade en el fichero .htaccess las siguientes reglas.

Más información en GTmetrics

<IfModule mod_deflate.c>
  # Compress HTML, CSS, JavaScript, Text, XML and fonts
  AddOutputFilterByType DEFLATE application/javascript
  AddOutputFilterByType DEFLATE application/rss+xml
  AddOutputFilterByType DEFLATE application/vnd.ms-fontobject
  AddOutputFilterByType DEFLATE application/x-font
  AddOutputFilterByType DEFLATE application/x-font-opentype
  AddOutputFilterByType DEFLATE application/x-font-otf
  AddOutputFilterByType DEFLATE application/x-font-truetype
  AddOutputFilterByType DEFLATE application/x-font-ttf
  AddOutputFilterByType DEFLATE application/x-javascript
  AddOutputFilterByType DEFLATE application/xhtml+xml
  AddOutputFilterByType DEFLATE application/xml
  AddOutputFilterByType DEFLATE font/opentype
  AddOutputFilterByType DEFLATE font/otf
  AddOutputFilterByType DEFLATE font/ttf
  AddOutputFilterByType DEFLATE image/svg+xml
  AddOutputFilterByType DEFLATE image/x-icon
  AddOutputFilterByType DEFLATE text/css
  AddOutputFilterByType DEFLATE text/html
  AddOutputFilterByType DEFLATE text/javascript
  AddOutputFilterByType DEFLATE text/plain
  AddOutputFilterByType DEFLATE text/xml
</IfModule>

Aprovechar el almacenamiento en caché de los navegadores


Esta regla se activa cuando PageSpeed Insights detecta que en la respuesta de tu servidor no se incluyen encabezados de caché explícitos, o el tiempo de expiración es corto.

Obtener recursos a través de la red es un proceso lento y costoso (ciclo de ida y vuelta entre un cliente y un servidor para descargarse). Almacena recursos en la caché del navegador evitando la transferencia y pérdida de tiempo consultando en cada petición al servidor.

Con Cache-Control se define cómo y durante cuánto tiempo los navegadores pueden almacenar una respuesta concreta.

Con ETag se proporciona un token de revalidación que los navegadores envían automáticamente para verificar si el recurso en cuestión ha cambiado desde la última vez que se solicitó.

Se recomienda establecer un tiempo de almacenamiento en caché mínimo de una semana.

Aprovechar el almacenamiento en caché de los navegadores

Leverage browser caching

No hay descarga del recurso desde el servidor. Se almacena el recurso en memoria o en disco.

Browser Cache

Aprovechar el almacenamiento en caché de los navegadores

Leverage browser caching

Añadimos reglas en el .htaccess para especificar el tiempo de expiración de los diferentes tipos de archivo.

Más información en GTmetrics

.htaccess completo en GitHub

<IfModule mod_expires.c>
  # Expires Caching
  ExpiresActive On
  ExpiresByType image/jpg "access plus 1 year"
  ExpiresByType image/jpeg "access plus 1 year"
  ExpiresByType image/gif "access plus 1 year"
  ExpiresByType image/png "access plus 1 year"
  ExpiresByType text/css "access plus 1 month"
  ExpiresByType application/pdf "access plus 1 month"
  ExpiresByType text/x-javascript "access plus 1 month"
  ExpiresByType application/x-shockwave-flash "access plus 1 month"
  ExpiresByType image/x-icon "access plus 1 year"
  ExpiresDefault "access plus 2 days"
</IfModule>

Minificar recursos


Esta regla se activa cuando PageSpeed Insights detecta que podría reducirse el tamaño de uno de tus recursos mediante la minificación.

Minificar es el proceso mediante el cual se eliminan datos innecesarios (comentarios, saltos de línea, emplear nombres de variables más cortos...) o redundantes de un recurso sin que se vea afectada la forma en que los navegadores lo procesan.

¿Qué se puede minificar?

  • HTML
  • CSS
  • JavaScript

Minificar recursos

Ejemplos

A continuación un listado de recursos y su peso antes y después de minificarlos.

Biblioteca Tamaño Dev Tamaño Min Ahorro
Font Awesome 5.2.0 58,9 kB 46,9 kB 20%
Bootstrap 4.1.3 CSS 173,6 kB 140,9 kB 19%
Bootstrap 4.1.3 JS 123,8 kB 51,0 kB 59%
jQuery 3.3.1 271,8 kB 86,9 kB 68%
Foundation 6.4.2 CSS 155,7 kB 117,4 kB 25%
Foundation 6.4.2 JS 422,6 kB 148,8 kB 65%

Minificar recursos

Minificando el HTML

En el caso del HTML, además de minificar podemos eliminar:

  • HTML de la cabecera de WordPress
  • Clases que no utilizamos en body, articles y menús
// Pasar de esto...
<!DOCTYPE html>
<html lang="es-ES" prefix="og: http://ogp.me/ns#">
  <head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1">
    <title>El blog de desarrollo WordPress...</title>
    <link rel="preload" href="css/styles.min.css" as="style">
    <link rel="preload" href="js/jquery.js" as="script">
    <link rel="preload" href="js/scripts.min.js" as="script">
    <meta name="description" content="Aquí podrás encontrar trucos...">
    <link rel="canonical" href="https://desarrollowp.com/">
    <link rel="publisher" href="//plus.google.com/+PabloLopezMestre">
    ...
  </head>

// a esto otro...
<!DOCTYPE html> <html lang="es-ES" prefix="og: http://ogp.me/ns#"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1"> <title>El blog de desarrollo WordPress...</title> <link rel="preload" href="css/styles.min.css" as="style"> <link rel="preload" href="js/jquery.js" as="script"> <link rel="preload" href="js/scripts.min.js" as="script"> <meta name="description" content="Aquí podrás encontrar trucos..."> <link rel="canonical" href="https://desarrollowp.com/"> <link rel="publisher" href="//plus.google.com/+PabloLopezMestre"> ... </head>

Minificar recursos

Minificando el HTML

Reduce y elimina HTML innecesario de la cabecera de WordPress. En una instalación por defecto se reducen 3kB.

Más información aquí

// Elimina HTML del head
function remove_headlinks_and_emojis() {
  remove_action( 'wp_head', 'wp_generator' );
  remove_action( 'wp_head', 'rsd_link' );
  remove_action( 'wp_head', 'wlwmanifest_link' );
  remove_action( 'wp_head', 'start_post_rel_link' );
  remove_action( 'wp_head', 'index_rel_link' );
  remove_action( 'wp_head', 'wp_shortlink_wp_head' );
  remove_action( 'wp_head', 'adjacent_posts_rel_link' );
  remove_action( 'wp_head', 'adjacent_posts_rel_link_wp_head', 10, 0 );
  remove_action( 'wp_head', 'parent_post_rel_link' );
  remove_action( 'wp_head', 'feed_links', 2 );
  remove_action( 'wp_head', 'feed_links_extra', 3 );
  remove_action( 'wp_head', 'print_emoji_detection_script', 7 );
  remove_action( 'wp_print_styles', 'print_emoji_styles' );
  remove_filter( 'wp_mail', 'wp_staticize_emoji_for_email' );
  remove_filter( 'the_content_feed', 'wp_staticize_emoji' );
  remove_filter( 'comment_text_rss', 'wp_staticize_emoji' );
}
add_action( 'init', 'remove_headlinks_and_emojis' );

Minificar recursos

Minificando el HTML

Elimina clases que no utilizas en body, articles, menús... (body_class, post_class, nav_menu_css_class).

Ejemplo: por defecto en la etiqueta body del hola mundo de un twentyseventeen aparecen las siguientes clases: post-template-default single single-post postid-1 single-format-standard has-header-image has-sidebar colors-light.

Más información aquí

// Eliminar las clases del body
function remove_body_classes( $classes ) {
  $whitelist = array( 'home', 'error404' );
  $wp_classes = array_intersect( $classes, $whitelist );
 
  return $wp_classes;
}
add_filter( 'body_class', 'remove_body_classes' );
 
// Eliminar las clases del article
function remove_post_classes( $classes ) {
  $whitelist = array( 'post' );
  $wp_classes = array_intersect( $classes, $whitelist );
 
  return $wp_classes;
}
add_filter( 'post_class', 'remove_post_classes' );
 
// Eliminar las clases del menú
function remove_menu_classes( $classes ) {
  $whitelist = array( 'menu-item' );
  $wp_classes = array_intersect( $classes, $whitelist );
 
  return $wp_classes;
}
add_filter( 'nav_menu_css_class', 'remove_menu_classes' );

Minificar recursos

Minificando el HTML

En GitHub podemos encontrar varias clases para lograr minificar el HTML. A través de expresiones regulares se eliminan los espacios, saltos de línea, tabulaciones, comentarios de desarrollo, etc...

Clase PHP para minificar HTML

HTML Minifier

O podemos utilizar algún plugin disponible en el Repositorio de WordPress

Minificar recursos

Minificando el CSS

Antes de minificar el CSS, deberíamos optimizar el número de reglas y cómo está escrito el código, para que el CSS de desarrollo pese lo menos posible

  • Uso de propiedades Shorthand
  • Eliminación de Vendor Prefix (-webkit, -moz, -ms, -o
  • Eliminación de unidades (px, em, rem) cuando el valor es 0
  • Códigos de color cortos (#fff, #000)

 

Mas información aquí

//En lugar de esto...
.my-class {
  padding-top: 15px;
  padding-right: 20px;
  padding-bottom: 15px;
  padding-left: 20px;
}

//Esto otro...
.my-class {
  padding: 15px 20px;
}

Con algo como esto podemos reducir entre 40 y 50 bytes

Minificar recursos

Minificando el CSS

Podemos hacer uso de herramientas como Gulp.

Gulp te ayuda a automatizar tareas comunes en el desarrollo de una aplicación, como pueden ser: mover archivos de una carpeta a otra, eliminarlos, minificar código, concatenación, validar sintáxis...

//Configuración de la tarea CSS
gulp.task('css', function () {
  gulp.src(['css/bootstrap.css','css/font-awesome.css','css/styles.css'])
    .pipe(concat('styles-concat.css'))
    .pipe(minifyCss())
    .pipe(rename('styles.min.css'))
    .pipe(gulp.dest('css')
  );
});

Minificar recursos

Minificando el JS

Antes de minificar el JS, deberíamos optimizar el número de reglas y cómo está escrito el código.

//jQuery
$(el).hide()

$(el).show()

$(el).addClass(className)


//Vanilla JS
el.style.display = 'none'

el.style.display = ''

if (el.classList)
  el.classList.add(className);
else
  el.className += ' ' + className;

Minificar recursos

Minificando el JS

También con Gulp.

En JS entra en juego Uglify, que permite una mayor ahorro de kB respecto a lo que podemos hacer en los recursos CSS.

//Configuración de la tarea JS
gulp.task('js', function () {
  gulp.src(['js/bootstrap.js','js/lazyload.js','js/main.js'])
    .pipe(concat('scripts-concat.js'))
    .pipe(uglify())
    .pipe(rename('scripts.min.js'))
    .pipe(gulp.dest('js')
  );
});

Optimizar imágenes


Esta regla se activa cuando PageSpeed Insights detecta que las imágenes de la página analizada pueden optimizarse para reducir su tamaño de archivo sin afectar significativamente la calidad visual.

Las imágenes representan gran parte del peso de una página, optimizarlas es clave.

  • El tamaño
  • La calidad/resolución
  • El formato
  • Imágenes responsive
  • Lazy Load

Optimizar imágenes

Optimizar imágenes en tamaño

Cuanto más grande sea una imagen, más pesa. Subiremos imágenes al tamaño definido en nuestro diseño para evitar el error de Serve scaled images.

Optimize Images
Tamaño Peso
5757 x 3238 px 4,42 MB
1024 x 576 px 552 kB

Optimizar imágenes

Optimizar imágenes en calidad/resolución

Lo ideal es tratar las imágenes antes de subirlas en software de edición como Photoshop o similares.

Optimize Images
Guardar como Peso
Calidad máxima (12) 552 kB
Optimizado para web (60) 147 kB

Optimizar imágenes

Optimizar imágenes en calidad/resolución

Existen muchos plugins que nos pueden ayudar a optimizar las imágenes que subamos, e incluso optimizar en lote las existentes.

Smush Image Compression and Optimization, Imagify, Kraken, EWWW

Optimizar imágenes

Formato de imágenes

Las imágenes en formato GIF, PNG o JPEG representan el 96% del total de imágenes de Internet.

Los formatos GIF y PNG son formatos de compresión sin pérdida, ya que no se produce ningún cambio visual en las imágenes al comprimirlas.

El formato JPEG es un formato con pérdida; es decir, el proceso de compresión elimina detalles visuales de las imágenes. No obstante, la tasa de compresión puede ser 10 veces mayor que la de los formatos GIF y PNG.

Más información en la página de desarrolladores de Google

GIF, PNG, JPEG

Optimizar imágenes

Haz uso de las imágenes responsive

Desde la versión 4.4 WordPress incorpora de manera nativa los atributos srcset y sizes en las etiquetas img que genera.

Al subir una imagen WordPress genera una serie de miniaturas (por defecto a 150px, 300px, 768px y 1024px). Se incluyen las miniaturas disponibles en el atributo srcset, y los navegadores muestran la adecuada a cada dispositivo.

Además, WordPress nos permite añadir nuevos thumbnails personalizados adicionales a los que vienen por defecto.

Más información aquí.

<img
width="848"
height="477"
src="image.jpg"
srcset="image.jpg 848w, image-300x169.jpg 300w, image-768x432.jpg 768w"
sizes="(max-width: 848px) 100vw, 848px"
alt="imagen responsive"
class="img-responsive wp-post-image">

Optimizar imágenes

Lazy Load

Lazy load, carga diferida o carga perezosa es una técnica que consiste en retrasar la carga de ciertos tipos de contenido como imágenes, vídeos y frames.

Esto se consigue reemplazando el src y srcset de una imagen por un pixel en blanco, de este modo ahorramos la petición http y el hecho de descargar una imagen que esté fuera del área visible.

Cuando hagamos scroll, mediante javascript se iran reemplazando estos atributos por los reales, y se irán mostrando las imágenes sólo si llegamos a ellas.

Más información aquí

Próximamente en navegadores

Lazy Load

Optimizar imágenes

Image Optimization Book

Resumiendo: Busca un equilibrio entre la calidad y el peso, elige un formato adecuado, súbelas al tamaño indicado, utiliza imágenes responsive y aplaza la carga mediante Lazy Load.

Más información en https://images.guide

Image Optimization Book

Optimizar la entrega de CSS


Esta regla se activa cuando PageSpeed Insights detecta que en una página se incluyen hojas de estilo externas que bloquean el renderizado.

Para renderizar el contenido de las páginas, los navegadores deben descargar y procesar todas las hojas de estilo externas.

Más información en la página de desarrolladores de Google

Optimizar la entrega de CSS

¿Qué nos recomienda Google?

El consejo es cargar en línea el Critical CSS y de forma asíncrona el resto.

Google nos aconseja utilizar loadCSS

Cómo hacerlo en WordPress

<html>
  <head>
    <style>
      .blue{color:blue;}
    </style>
  </head>
  <body>
    <div class="blue">
      Hello, world!
    </div>
    <noscript id="deferred-styles">
      <link rel="stylesheet" type="text/css" href="small.css">
    </noscript>
    <script>
      var loadDeferredStyles = function() {
        var addStylesNode = document.getElementById("deferred-styles");
        var replacement = document.createElement("div");
        replacement.innerHTML = addStylesNode.textContent;
        document.body.appendChild(replacement)
        addStylesNode.parentElement.removeChild(addStylesNode);
      };
      var raf = window.requestAnimationFrame || window.mozRequestAnimationFrame || window.webkitRequestAnimationFrame || window.msRequestAnimationFrame;
      if (raf) raf(function() { window.setTimeout(loadDeferredStyles, 0); });
      else window.addEventListener('load', loadDeferredStyles);
    </script>
  </body>
</html>

Optimizar la entrega de CSS

Critical CSS

Generaremos un archivo critical.min.css donde incluir todos los estilos que afectan al primer renderizado de la web.

Este archivo lo cargaremos en línea.

function print_critical_css() {?>
  <style>
    <?php include_once get_theme_file_path('css/critical.min.css');?>
  </style>
<?php }

add_action( 'wp_print_styles', 'print_critical_css', 1);

Optimizar la entrega de CSS

Uso del atributo media

Generaremos una hoja de estilos para cada media-query, de este modo no bloquearemos el renderizado. Por ejemplo, en bootstrap disponemos de las siguientes media queries:

// Small devices (landscape phones, 576px and up)
@media (min-width: 576px) { ... }

// Medium devices (tablets, 768px and up)
@media (min-width: 768px) { ... }

// Large devices (desktops, 992px and up)
@media (min-width: 992px) { ... }

// Extra large devices (large desktops, 1200px and up)
@media (min-width: 1200px) { ... }

wp_enqueue_style( string $handle, string $src = '', array $deps = array(), string|bool|null $ver = false, string $media = 'all' )

function enqueue_styles_by_media() {
  wp_enqueue_style( 'styles-small', get_theme_file_uri('/css/styles-small.min.css'), '', null, '(min-width:576px)' );
  
  wp_enqueue_style( 'styles-medium', get_theme_file_uri('/css/styles-medium.min.css'), '', null, '(min-width:768px)' );

  wp_enqueue_style( 'styles-large', get_theme_file_uri('/css/styles-large.min.css'), '', null, '(min-width:992px)' );

  wp_enqueue_style( 'styles-xlarge', get_theme_file_uri('/css/styles-xlarge.min.css'), '', null, '(min-width:1200px)' );
}
add_action( 'wp_enqueue_scripts', 'enqueue_styles_by_media' );

Optimizar la entrega de CSS

Uso del atributo media

Acepta valores de ancho (min-, max-), alto (min-, max-), orientación (portrait, landscape), resolución...

Más información sobre el atributo https://www.w3schools.com/tags/att_link_media.asp

<link rel='stylesheet' id='styles-small-css' href='https://yourdomain.com/wp-content/themes/yourtheme/css/styles-small.min.css' type='text/css' media='(min-width:576px)' />

<link rel='stylesheet' id='styles-medium-css' href='https://yourdomain.com/wp-content/themes/yourtheme/css/styles-medium.min.css' type='text/css' media='(min-width:768px)' />

<link rel='stylesheet' id='styles-large-css' href='https://yourdomain.com/wp-content/themes/yourtheme/css/styles-large.min.css' type='text/css' media='(min-width:992px)' />

<link rel='stylesheet' id='styles-xlarge-css' href='https://yourdomain.com/wp-content/themes/yourtheme/css/styles-xlarge.min.css' type='text/css' media='(min-width:1200px)' />

Quitar el JavaScript que bloquea el renderizado del contenido


Esta regla se activa cuando PageSpeed Insights detecta que en tu código HTML se hace referencia a un archivo JavaScript externo que bloquea el renderizado del contenido de la mitad superior de tu página.

Siempre que se encuentra con una secuencia de comandos, debe detenerse y ejecutarla para poder continuar analizando el código HTML.

Se detecta una etiqueta <script> como bloqueante siempre que:

  • Está en el <head> del documento
  • No posee un atributo defer
  • No posee un atributo async

Quitar el JavaScript que bloquea el renderizado del contenido

Siempre que sea posible, los scripts al footer.

Scripts
// Estableciendo '$in_footer' a true, se encolará el JS en el footer.
wp_enqueue_script(
  string $handle,
  string $src = '',
  array $deps = array(),
  string|bool|null $ver = false,
  bool $in_footer = false
);


// Forzar otros scripts al footer.
function move_scripts_from_head_to_footer() {
  remove_action( 'wp_head', 'wp_print_scripts' );
  remove_action( 'wp_head', 'wp_print_head_scripts', 9 );
  remove_action( 'wp_head', 'wp_enqueue_scripts', 1 );
  
  add_action( 'wp_footer', 'wp_print_scripts', 5 );
  add_action( 'wp_footer', 'wp_enqueue_scripts', 5 );
  add_action( 'wp_footer', 'wp_print_head_scripts', 5 );
}
add_action( 'wp_enqueue_scripts', 'move_scripts_from_head_to_footer' );

Quitar el JavaScript que bloquea el renderizado del contenido

Atributo async

async se introduce en HTML5 para indicar que el script debe cargarse de forma asíncrona, sin bloquear la presentación del resto de contenido, y ejecutarse inmediatamente cuando se haya descargado.

El orden de ejecución no se garantiza.

Scripts Async
// Add async attr to scripts.
function add_async_attr_to_all_scripts( $tag ) {
  return str_replace( ' src', ' async="async" src', $tag );
}
add_filter( 'script_loader_tag', 'add_async_attr_to_all_scripts', 10 );

Quitar el JavaScript que bloquea el renderizado del contenido

Atributo defer

defer indica al navegador que continúe con el parseo y presentación del HTML. El script se ejecutará cuando la página se ha terminado de parsear, justo antes de lanzarse el evento DOMContentLoaded.

Además, los scripts con defer deben ejecutarse en el orden en que se especificaron en la página.

Scripts Defer
// Add defer attr to scripts.
function add_defer_attr_to_all_scripts( $tag ) {
  return str_replace( ' src', ' defer="defer" src', $tag );
}
add_filter( 'script_loader_tag', 'add_defer_attr_to_all_scripts', 10 );

Generalizando...

async, defer, inline

Bola extra: Resource Hints


Los Resource Hints, o precarga de recursos, es una técnica que funciona client-side y que puede tener un impacto importante en WPO, sobretodo en conexiones lentas.

Un resource hints sugiere al navegador que descargue recursos que no van a ser utilizados en ese momento pero que pueden ser utilizados en el futuro.

La descarga se realiza en segundo plano y antes de que el cliente necesite el recurso, de ahí que se hable de "precarga".

Hay varios tipos: dns-prefetch, preconnect, prefetch, prerender... pero vamos a ver el preload.

Resource Hints: preload

Diferentes métodos para hacer preload de un recurso

La directiva preload es obligatoria y de alta prioridad, por lo que su uso está centrado en la navegación actual.

El link preload permite notificar al navegador como debe tratar el recurso precargado a través del atributo as.

Los assets que pueden hacer uso de preload son: audio, video, track, script, style, font, image, fetch, worker, embed, object y document.

La precarga de un recurso puede especificarse a través de marcado HTML (a través de una etiqueta link), vía JavaScript, o mediante una cabecera HTTP.

Más información en W3C

Más información en Mozilla.org

// Preload mediante marcado HTML (etiqueta link)
<link rel="preload" href="/styles/other.css" as="style">


// Preload mediante JavaScript
<script>
var res = document.createElement("link");
  res.rel = "preload";
  res.as = "style";
  res.href = "styles/other.css";
  document.head.appendChild(res);
</script>


// Preload mediante cabecera HTTP
Link: <https://example.com/other/styles.css>; rel=preload; as=style

Resource Hints: preload

Preload a través de una cabecera HTTP

¡OJO! Si eliminas el parámetro ver de tus recursos, no lo concatenes aquí porque el navegador lo interpretaría como un recurso diferente y no haría preload.

function preload_assets() {
  header( 'Link: <https://yourdomain.com/yourcss.css>; rel=preload; as=style', false );

  header( 'Link: <https://yourdomain.com/yourjs.js>; rel=preload; as=script', false );

  header( 'Link: <https://yourdomain.com/yourfont.woff>; rel=preload; as=font; crossorigin', false );
}
add_action( 'send_headers', 'preload_assets' );

Audits

Preload fonts

HTTP Headers

HTTP Headers

Bola extra 2: Carga condicional


Menos es más, ¿lo recuerdas?

Gracias a los conditional tags de WordPress podemos hacer carga condicional de recursos

¿Para qué cargar los CSS y JS de Disqus en un listado de categorías o la home? ¿Para qué cargar los CSS y JS de un formulario de contacto en el resto de páginas que no tienen un formulario de contacto?

Carga condicional

No cargues recursos CSS y JS donde no se utilicen

Disponemos de multitud de conditional tags para ejecutar código allí donde sea necesario: is_single(), is_page(), is_home(), is_category()...

Más información aquí

// Disqus sólo en single
function disqus_only_in_single() {
  if ( is_singular( 'post' ) && comments_open() ) {
    return;  
  }
        
  wp_dequeue_script( 'disqus_count' );
  wp_dequeue_script( 'disqus_embed' );
}
add_action( 'wp_enqueue_scripts', 'disqus_only_in_single', 100 );

Bola extra 3: CDN


Si utilizamos una CDN, podremos servir nuestros recursos estáticos desde el servidor más cercano al usuario que disponga la CDN. Además, están optimizados.

Además de ganar en velocidad de carga, sobrecargamos menos nuestro servidor.

jQuery sin CDN

assets from server

jQuery con CDN

assets from cdn

¡GRACIAS!