Performance
Non-blocking styles
Only use this in conjunction with Critical Path CSS — web.dev reference.
<!-- resources/views/partials/head.blade.php -->
<link rel="preload" href="@asset('styles/main.css')" as="style" onload="this.onload=null;this.rel='stylesheet'">
<noscript><link rel="stylesheet" href="@asset('styles/main.css')"></noscript>
Note: this is untested and relies on Contact Form 7 not changing path to CSS.
// app/setup.php
add_action('wp_enqueue_scripts', function () {
wp_dequeue_style('contact-form-7');
}, 100);
<link rel="preload" href="/wp-content/plugins/contact-form-7/includes/css/styles.css" as="style" onload="this.onload=null;this.rel='stylesheet'">
<noscript><link rel="stylesheet" href="/wp-content/plugins/contact-form-7/includes/css/styles.css"></noscript>
Critical Path CSS
yarn add html-critical-webpack-plugin@1.1.0 -D
// resources/assets/build/webpack.config.optimize.js
const HtmlCriticalWebpackPlugin = require('html-critical-webpack-plugin');
// in plugins: []
new HtmlCriticalWebpackPlugin({
base: config.paths.dist,
src: config.devUrl,
dest: 'styles/critical.css',
ignore: ['@font-face', /url\(/, /wpcf7/, /swiper/],
inline: false,
minify: true,
extract: false,
dimensions: [
{
width: 640,
height: 640,
},
{
width: 1500,
height: 1080,
},
],
penthouse: {
blockJSRequests: false,
},
}),
// app/helpers.php
function locate_asset($asset): string
{
return trailingslashit(config('assets.path')) . sage('assets')->get($asset);
}
function get_file_contents($asset): string
{
global $wp_filesystem;
if (empty($wp_filesystem)) {
require_once ABSPATH . '/wp-admin/includes/file.php';
}
\WP_Filesystem();
$asset_path = locate_asset($asset);
if ($wp_filesystem->is_readable($asset_path)) {
return $wp_filesystem->get_contents($asset_path);
}
return '';
}
// config/assets.php
'path' => get_theme_file_path().'/dist',
// config/assets.php
'path' => get_theme_file_path().'/dist',
// app/setup.php
// NOTE: comment out the loading of the main.css file in enqueue scripts function
add_action('wp_head', function (): void {
$critical_CSS = 'styles/critical.css';
if (file_exists(locate_asset($critical_CSS))) {
echo '<style id="critical-css">' . get_file_contents($critical_CSS) . '</style>';
}
}, 1);
Async gtag.js
<!-- <head> -->
<script>
window.ga=window.ga||function(){(ga.q=ga.q||[]).push(arguments)};ga.l=+new Date;
ga('create', '{GA_PROPERTY_ID}, 'auto');
ga('send', 'pageview');
</script>
<script async src="https://www.google-analytics.com/analytics.js"></script>
Lazy load iframes using AlpineJS 3
It is best practice to apply an overlaying image (poster).
<!-- add intersect plugin to <head>, before alpinejs script tag -->
<script defer src="https://unpkg.com/@alpinejs/intersect@3.x.x/dist/cdn.min.js"></script>
<!-- Basic HTML for loading iframe from WordPress -->
<iframe x-data="lazyiframes" x-intersect="load($el)" title="YouTube video" class="lazyframe" loading="lazy" width="560" height="315" data-src="{YOUTUBE_EMBED_URL}" frameborder="0" allowfullscreen x-cloak></iframe>
// initiate the x-data function
document.addEventListener('alpine:init', () => {
Alpine.data('lazyiframes', () => ({
// using x-intersect, switch the data-src to the src tag when user arrives at iframe
load(el) {
el.setAttribute('src', el.getAttribute('data-src'));
},
}))
});