Optimizing for Core Web Vitals . Part 1

During the course of the year 2020, Google has announced that Core Web Vitals will be come a ranking factors. Google makes, such announcement when the company wants webmasters to prepare their website for the changes to come.

Core Web Vitals is a selection of metrics that help characterize the user experience on a page: how fast does it render? how fast is it interactive? Does the content of the page jump around when new element are loaded?

In technical terms thats gives:

Largest Contentful Paint (LCP): measures loading performance. To provide a good user experience, LCP should occur within 2.5 seconds of when the page first starts loading.

First Input Delay (FID): measures interactivity. To provide a good user experience, pages should have a FID of less than 100 milliseconds.

Cumulative Layout Shift (CLS): measures visual stability. To provide a good user experience, pages should maintain a CLS of less than 0.1.

https://web.dev/vitals/

You can find the Core Web Vitals for a page by using tools such as https://developers.google.com/speed/pagespeed/insights/ but they are also available in Google Search Console and other Google products.

As the opportunities for improvement will vary greatly from one website to another. I will develop here the one I encounter during my own optimization process, and hopefuly it will be useful to others. Let’s analyze some opportunities:

Preload keys requests:

Preloading a font to be loaded ahead of time so that when it is needed, it is already available.

https://web.dev/codelab-preload-web-fonts/

https://developer.mozilla.org/en-US/docs/Web/HTML/Preloading_content

Preloading content is also useful to help prevent blocking resource.

When preloading the font, Google Page Speed returns an error message that the font is not used:

Warnings: A preload <link> was found for “https://www.example.com/templates/horme_3/fonts/glyphicons-halflings-regular.woff” but was not used by the browser. Check that you are using the `crossorigin` attribute properly.

https://developer.mozilla.org/en-US/docs/Web/HTML/Preloading_content#Cross-origin_fetches

So preloading a font will look like:

<link rel="preload" href="https://fonts.googleapis.com/css?family=Michroma|Roboto" as="font" crossorigin >
<link rel="preload" href="/some/script.js" as = "script" />
<link rel="preload" type="text/css" href="/some/style.css" as="style" />

preload html specification

In the same vein, you can also preconnect to external resource to gain on loading time:

<link rel="preconnect" href="https://stackpath.bootstrapcdn.com" >

Cumulative Layout Shift (CLS)

The most common causes of a poor CLS are:

  • Images without dimensions
  • Ads, embeds, and iframes without dimensions
  • Dynamically injected content
  • Web Fonts causing FOIT/FOUT
  • Actions waiting for a network response before updating DOM

https://web.dev/optimize-cls/

The first suggestion apply to my case as I don’t declare any width and height in the picture element. I got used to the flexibility of responsive image (calculated according the size of the screen) and didn’t move on to the srcset method where the different image size available are listed with specification regading the screen size it should be displayed at. This method requires to carefully plan break and the various size available to fit the different screen size. Example:

< i mg srcset="elva-fairy-480w.jpg 480w,
             elva-fairy-800w.jpg 800w"
     sizes="(max-width: 600px) 480px,
            800px"
     src="elva-fairy-800w.jpg"
     alt="Elva dressed as a fairy">
The code above did not work as desired (the image loaded on mobile screen size was still the largest one.
The following code works as intended:

<picture> 
<source media="(max-width: 799px)" srcset="elva-480w-close-portrait.jpg"> 
<source media="(min-width: 800px)" srcset="elva-800w.jpg"> 
<img src="elva-800w.jpg" alt="Chris standing up holding his daughter Elva"> 
</picture>

In the article about optimizing cls cited earlier, it is specified that you need to give the image aspect ratio (actually width and height) so that the browser can calculate the size on the screen as soon at it received the css relative width, for example:

width:100%

implementing min-height for the images class solved the issue of layout shifting. The text still overlay pictures that have a height larger than the min-height but it’s due to a javascript (matchHeight.js) in my template which role is to set all div from a row to the same height. This needs to be replaced with css that performs the same action.

Avoid displaying empty font:

adding

font-display:swap;

to the @font-face in the bootstrap css glyphicon font delaration solved the issue. It tells the browser to use a build-in font to render the text while the proper font is loaded.

https://developer.mozilla.org/en-US/docs/Web/CSS/@font-face/font-display

Display pictures at the proper size

To display picture properly on high-dpi screen I use to display compressed jpeg at half their actual width. This rendered well on iPhone screen even though the quality was a bit lower on desktop compared to the same compression but at the actual size.

The issue with this method is that it requires that the browser resize the picture to the screen size and it might consume more badwidth than serving the picture at the actual screen size, although with this method you can serve picture twice the size but lighter than the actual size one because they are more compressed.

There might be an alternative that would save the computer the calulation cost and that would be to use picture at 100% their screen size but saved with higher dpi so that they look good on high-dpi screen as well.

We need to control that high-dpi picture are looking good on retina display and the like, but also that the CMS, when generating thumbnails, will also create high-dpi thumbnails.

Security

Link with target="_blank" are unsecured without rel="noopener" or rel="noreferrer". Read more:

https://web.dev/external-anchors-use-rel-noopener/

And on wether or not you should use target="_blank" at all :

Best practice:

Links do not have a discernible name

if your link doesn’t have text or a picture with an alt-tag, you can use arial-label=”link description” for people using assistive technology.

Next step: remove unused CSS and javascript!

CRON job http execution failed in zone.ee hosting

Description: http execution of CRON job fails. Error:

Timeout

The file is executed normally when run by accessing it directly by the browser without marked difference in execution time when the script is executed on a local server.

The site is running WordPress.

Solution: In that case change the https execution for a system execution in your zone.ee webserver settings.

Optimizing PHP code using ticks

https://www.php.net/manual/en/function.register-tick-function.php

You can compare two ways of coding a script for the same end result by counting the number of ticks it takes to execute each version.

For this you can use register_tick_function() that allows you to execute a certain function at each tick.

For this to work you will need to use the declare function with the tick directive.

https://www.php.net/manual/en/control-structures.declare.php

declare(ticks=1);
$c=0;
// A function called on each tick event
function tick_handler()
{
    global $c;
    $c+=1;
}

register_tick_function('tick_handler');
echo $c.'\n';

Keep in mind that some code might be more efficient than others for the same task due to their underlying C implementation. Or is it stricly equivalent (less tick== always faster)?

Persistent VS non-persistent MySQLi connection

“The idea behind persistent connections is that a connection between a client process and a database can be reused by a client process, rather than being created and destroyed multiple times. This reduces the overhead of creating fresh connections every time one is required, as unused connections are cached and ready to be reused.”

https://www.php.net/manual/en/mysqli.persistconns.php

To open a persistent connection with mysqli you must prepend p: to the hostname when connecting.

Testing performance gain by using persistent connection on a joomla site was not conclusive:

https://www.itoctopus.com/how-to-use-mysql-persistent-connections-on-joomla-sites#:~:text=A%20non%2Dpersistent%20MySQL%20is,script%20end%20and%20is%20reused.

What does the double colon (::) in PHP means?

https://www.php.net/manual/en/language.oop5.paamayim-nekudotayim.php

The double colon is called the Scope Resolution Operator and is used to ” allows access  to staticconstant, and overridden properties or methods of a class.”

//Exemple 1
class MyClass {
    const CONST_VALUE = 'A constant value';
}

$classname = 'MyClass';
echo $classname::CONST_VALUE; // As of PHP 5.3.0

echo MyClass::CONST_VALUE;
//Exemple 2
class OtherClass extends MyClass
{
    public static $my_static = 'static var';

    public static function doubleColon() {
        echo parent::CONST_VALUE . "\n";
        echo self::$my_static . "\n";
    }
}

$classname = 'OtherClass';
$classname::doubleColon(); // As of PHP 5.3.0

OtherClass::doubleColon();

WHERE clause with Special character in MySQL and PHP query and prepared statement

Special character issue in php query can be solved by using:

WHERE _utf8'string'

https://dev.mysql.com/doc/refman/8.0/en/string-literals.html

this unfortunately does not work for prepared statement.

Instead set the character set for the connection to utf-8 using

$conn->set_charset("utf8")

https://www.php.net/manual/en/mysqli.set-charset.php

if (!$conn->set_charset("utf8")) {
    printf("Error loading character set utf8: %s\n", $conn->error);
    exit();
} else {
    printf("Current character set: %s\n", $conn->character_set_name());
}

If your string might include backslash, escaping the string will do the trick:

$city = mysqli_real_escape_string($link, $city);

php.net/manual/en/mysqli.real-escape-string.php