Gestión avanzada de assets en WordPress
Puedes encontrarme...
-
En Twitter: @desarrollowp
Twitteo artículos, información y noticias sobre WordPress y el sector web en general. -
En mi blog: https://desarrollowp.com
Blog sobre tutoriales, guías, consejos, noticias y entrevistas en el mundo WordPress. -
En Slack
En los slacks de wpes y wpmadrid. -
En la comunidad
Ayudo a organizar el grupo de meetup de Madrid WordPress y la WordCamp Madrid. -
WordPress developer en UNIR
Trabajo con WordPress tratando de hacer cada proyecto mejor que el anterior.
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
Gestión de assets en WordPress
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.
Mr. Google
Herramientas de medición
Las 9 reglas de Google
-
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.
En todos los navegadores modernos se admite y negocia automáticamente la compresión gzip en todas las solicitudes HTTP.
Al habilitar la compresión gzip, se puede reducir el tamaño de las respuestas transferidas hasta en un 90%, lo que puede, a su vez, disminuir significativamente el tiempo necesario para descargar el recurso correspondiente, así como reducir 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
Configuración en apache (.htaccess)
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>
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 comprimido | 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% |
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 que se ha indicado que los recursos se almacenen en la memoria caché durante poco tiempo.
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.
Esto retrasa el procesamiento y puede bloquear el renderizado del contenido de las páginas. Además, este proceso puede suponer costes de datos a los visitantes.
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ó. El servidor web no necesita enviar una respuesta completa si el contenido no ha cambiado.
Aprovechar el almacenamiento en caché de los navegadores
Leverage browser caching
Almacena recursos en la caché del navegador evitando tener que ir a buscarlos al servidor. Evitamos transferencia y pérdida de tiempo consultando en cada petición al servidor.
Aprovechar el almacenamiento en caché de los navegadores
Leverage browser caching
Añadimos en el .htaccess las siguientes reglas.
Más información en GTmetrics
<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>
Aprovechar el almacenamiento en caché de los navegadores
Leverage browser caching
.htaccess completo en GitHub
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.0.12 | 46 KB | 37 KB | 20% |
Bootstrap 4.1 CSS | 169 KB | 138 KB | 18% |
Bootstrap 4.1 JS | 120 KB | 50 KB | 58% |
jQuery 3.3.1 | 266 KB | 85 KB | 68% |
Foundation 6.4.2 CSS | 153 KB | 115 KB | 25% |
Foundation 6.4.2 JS | 413 KB | 146 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, menús... (body_class, post_class, nav_menu_css_class)
- QueryString versión WordPress
// 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 en español con tutoriales</title> <link rel="preload" href="https://desarrollowp.com/wp-content/themes/desarrollowp/css/styles.min.css" as="style"> <link rel="preload" href="https://desarrollowp.com/wp-includes/js/jquery/jquery.js" as="script"> <link rel="preload" href="https://desarrollowp.com/wp-content/themes/desarrollowp/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="https://plus.google.com/+PabloLopezMestre"/> // 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 en español con tutoriales</title><link rel="preload" href="https://desarrollowp.com/wp-content/themes/desarrollowp/css/styles.min.css" as="style"><link rel="preload" href="https://desarrollowp.com/wp-includes/js/jquery/jquery.js" as="script"><link rel="preload" href="https://desarrollowp.com/wp-content/themes/desarrollowp/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="https://plus.google.com/+PabloLopezMestre"/>
Minificar recursos
Minificando el HTML
Reduce y elimina HTML inncesario de la cabecera de WordPress.
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
Elimina el parámetro versión en los assets de WordPress. Ejemplo: ?ver=4.9.6
Más información aquí
// Eliminar las versiones de los parámetros en las URLs
function remove_version_params( $src ){
$parts = explode( '?ver', $src );
return $parts[0];
}
add_filter( 'script_loader_src', 'remove_version_params', 15, 1 );
add_filter( 'style_loader_src', 'remove_version_params', 15, 1 );
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
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.min.css','css/font-awesome.min.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
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.min.js','js/lazyload.min.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.
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 en software de edición como Photoshop o Gimp.
Guardar como | Peso |
---|---|
Calidad máxima (12) | 552 KB |
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.
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
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 el el atributo srcset
, y los navegadores muestran la adecuada a cada dispositivo.
Para ayudar a los navegadores a elegir la mejor imagen de la lista de srcset, se incluyen los tamaños en el atributo sizes
.
Más información aquí.
<img width="848" height="477" src="imagen.jpg" srcset="imagen.jpg 848w, imagen-300x169.jpg 300w, imagen-768x432.jpg 768w" sizes="(max-width: 848px) 100vw, 848px" alt="imagen responsive" class="img-responsive wp-post-image">
Optimizar imágenes
Añade nuevos "puntos de corte"
WordPress nos permite añadir nuevos thumbnails además de los que vienen por defecto.
add_image_size( string $name, int $width, int $height, bool|array $crop = false )
function my_custom_image_size() {
add_image_size( 'my-custom-size', 512 );
}
add_action( 'after_setup_theme', 'my_custom_image_size' );
Optimizar imágenes
Funciones y hooks disponibles
Tenemos a nuestra disposición varias funciones y hooks útiles si estamos desarrollando un tema y/o plugin a medida.
Más información aquí
wp_get_attachment_image_srcset(int $attachment_id, array|string $size, array $image_meta) – Devuelve el valor del atributo srcset de una imagen. wp_calculate_image_srcset(array $size_array, string $image_src, array $image_meta, int $attachment_id) – Función auxiliar para calcular los tamaños a incluir en el atributo srcset. wp_get_attachment_image_sizes(int $attachment_id, array|string $size, array $image_meta) – Devuelve el valor del atributo sizes de una imagen. wp_calculate_image_sizes(array|string $size, string $image_src, array $image_meta, int $attachment_id) – Función auxiliar para calcular los tamaños a incluir en el atributo sizes. wp_make_content_images_responsive(string $content) – Convierte las imágenes de un texto en responsive (siempre que tengan la clase wp-image-XX). wp_image_add_srcset_and_sizes(string $image, array $image_meta, int $attachment_id) – Añade los atributos srcset y sizes a una imagen. Se usa en la función anterior.
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í
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
¿Hasta aquí todo claro?
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.
<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)' />
Optimizar la entrega de CSS
¿Qué hacemos con la hoja de estilos principal?
Tendremos una hoja CSS con estilos que aplicarán en cualquier escenario. Si utilizamos el atributo media="all" o lo dejamos vacío, se detectará como un recurso que bloquea el renderizado.
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>
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
wp_enqueue_script( string $handle, string $src = '', array $deps = array(), string|bool|null $ver = false, bool $in_footer = false ); // Estableciendo el último parámetro a true, se encolará el JS en el footer.
Quitar el JavaScript que bloquea el renderizado del contenido
Forzar los scripts de otros plugins al footer
Otros plugins pueden estar cargando scripts en el <head> de tu sitio. Con esta función podemos mover todos los scripts al hook wp_footer.
// Remove scripts from head.
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.
// 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.
// 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 );
¿Cómo lo lleváis?
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
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
Ejemplo de cómo hacer preload a recursos CSS y JS
Más información en Mozilla.org
<head> <meta charset="utf-8"> <title>JS and CSS preload example</title> <link rel="preload" href="style.css" as="style"> <link rel="preload" href="main.js" as="script"> <link rel="stylesheet" href="style.css"> </head> <body> <h1>bouncing balls</h1> <canvas></canvas> <script src="main.js"></script> </body>
Resource Hints: preload
Añadir la etiqueta preload a los recursos CSS
¡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_css() { global $wp_styles; foreach ( $wp_styles->queue as $handle ) { $style = $wp_styles->registered[ $handle ]; $source = $style->src . ( $style->ver ? "?ver={$style->ver}" : "" ); echo '<link rel="preload" href="' . $source . '" as="style">'; } } add_action( 'wp_head', 'preload_css' );
Resource Hints: preload
Añadir la etiqueta preload a los recursos JS
¡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_js() { global $wp_scripts; foreach ( $wp_scripts->queue as $handle ) { $script = $wp_scripts->registered[ $handle ]; $source = $script->src . ( $script->ver ? "?ver={$script->ver}" : "" ); echo '<link rel="preload" href="' . $source . '" as="script">'; } } add_action( 'wp_head', 'preload_js' );
Resource Hints: preload
Añadir la etiqueta preload a los recursos FONTS
Quizá los preload de mayor repercusión, porque si se encuentran en dentro de hojas de estilo, se procesarán más tarde.
function preload_fonts() { echo '<link rel="preload" href="https://yourdomain.com/wp-content/themes/yourtheme/assets/fonts/yourfont.woff" as="font">'; echo '<link rel="preload" href="https://yourdomain.com/wp-content/themes/yourtheme/assets/fonts/yourfont.eot" as="font">'; } add_action( 'wp_head', 'preload_fonts' );
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( sprintf('Link: <https://yourdomain.com/yourjs.js>; rel=preload; as=script', false ); header( sprintf('Link: <https://yourdomain.com/yourfont.woff>; rel=preload; as=font; crossorigin', false ); } add_action( 'send_headers', 'preload_assets' );
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 );
Ya terminamos, lo prometo!
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.