Resource Hints or: how to Speed Up Magento 2 using Preconnect

A few months ago I showed how using preconnect resource hints can severely speed up your website. I found out that for Magento 2 there are no ready-to-use solutions to integrate preload, preconnect or prefetch headers into your store. So today I’ll show you how to add preload, preconnect and prefetch resource hints to Magento 2’s head.

What are Resource Hints?

Resource hints are various link relationship elements that give website owners more control over the timing and when and how of used resources:

  • <link rel="preconnect" /> being very useful e.g. to speed up loading 3rd party scripts and resources.
  • <link rel="prefetch /> could come in handy once a visitor enters the shopping cart, to prepare the resources used for navigation through the checkout.
  • <link rel="preload /> is often used e.g. for webfonts to make sure the display of text isn’t changed while loading.

How Preconnect speeds up your Magento 2 Store

While preload and prefetch are features which make your site feel faster, preconnect actually speeds up your store. Here’s how it works:

Preconnect establishes a connection to the source at pageload. DNS Lookup, Initial Connection and SSL negotiation happen asynchronously. When the browser needs the actual file, it can start downloading immediately without having to wait. Without preconnect this entire handshake process happens one after another, slowing down the loading of the page.

Add Resource Hints to your Store’s Head

Since Resource Hints are link relationship elements (like stylesheets) they need to be defined in <head>. Sadly, Magento doesn’t offer an easy way to add resource hints to its head. So in order to this, we need to build a simply module consisting of two things:

  1. An observer,
  2. A list of elements we want to add.

Hint: if you don’t want or can’t build a module for Magento 2. No worries, I’ve created and expanded this extension with a very easy-to-use configuration. Scroll to the bottom of this post for a link. :)

Creating the Magento 2 module

Building a Magento 2 extension always starts with two things:

  1. registration.php
  2. etc/module.xml

These files should be added inside the folder [magento 2-root]/app/code/Dan0sz/ResourceHints.

app/code/Dan0sz/ResourceHints/registration.php

<?php
/**
* @author : Daan van den Bergh
* @url : https://daan.dev
* @package : Dan0sz/ResourceHints
* @copyright: (c) 2019 Daan van den Bergh
*/
\Magento\Framework\Component\ComponentRegistrar::register(
\Magento\Framework\Component\ComponentRegistrar::MODULE,
'Dan0sz_ResourceHints',
__DIR__
);
view raw registration.php hosted with ❤ by GitHub

app/code/Dan0sz/ResourceHints/etc/module.xml

<?xml version="1.0" encoding="UTF-8"?>
<!--
/**
* @author : Daan van den Bergh
* @url : https://daan.dev
* @package : Dan0sz/ResourceHints
* @copyright: (c) 2019 Daan van den Bergh
*/
-->
<config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:framework:Module/etc/module.xsd">
<module name="Dan0sz_ResourceHints" setup_version="1.0.0">
<sequence>
<module name="Magento_Catalog" />
</sequence>
</module>
</config>
view raw etc-module.xml hosted with ❤ by GitHub

Adding an Observer

At certain (many) points in Magento 2’s code, events are triggered — or dispatched. This allows us to hook into these events and execute code. This is achieved using an observer. E.g. in an earlier post I’ve shown how to use an observer to add a product to Magento 2’s topmenu.

To hook into an observer, we need two things:

  1. Register the observer to the event,
  2. An observer-class, containing (at least) an execute()-method.

The event we will be hooking into is called layout_generate_blocks_after which allows us to add resource hints to Magento 2’s head, after Magento is done generate the other blocks within the layout. Since it is considered a frontend-event, the below file needs to be placed inside the etc/frontend-folder.

app/code/Dan0sz/ResourceHints/etc/frontend/events.xml

<?xml version="1.0" encoding="UTF-8"?>
<!--
/**
* @author : Daan van den Bergh
* @url : https://daan.dev
* @package : Dan0sz/ResourceHints
* @copyright: (c) 2019 Daan van den Bergh
*/
-->
<config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:framework:Event/etc/events.xsd">
<event name="layout_generate_blocks_after">
<observer name="dan0sz_resource_hints_framework_view_layout_builder" instance="Dan0sz\ResourceHints\Observer\Framework\View\Layout\Builder" />
</event>
</config>

app/code/Dan0sz/ResourceHints/Observer/Framework/View/Layout/Builder.php

<?php
/**
* @author : Daan van den Bergh
* @url : https://daan.dev
* @package : Dan0sz/ResourceHints
* @copyright: (c) 2019 Daan van den Bergh
*/
namespace Dan0sz\ResourceHints\Observer\Framework\View\Layout;
use Magento\Framework\Event\Observer;
use Magento\Framework\Event\ObserverInterface;
use Magento\Framework\View\Page\Config as PageConfig;
class Builder implements ObserverInterface
{
/** @var PageConfig $pageConfig */
private $pageConfig;
/**
* Builder constructor.
*
* @param PageConfig $pageConfig
*/
public function __construct(
PageConfig $pageConfig
) {
$this->pageConfig = $pageConfig;
}
/**
* @param Observer $observer
*
* @return $this
*/
public function execute(Observer $observer)
{
$resourceHints = [
'google' => [
'resource' => 'https://www.google-analytics.com',
'type' => 'preconnect',
],
'next-page' => [
'resource' => 'https://example.com/next-page',
'type' => 'prefetch'
],
'stylesheet' => [
'resource' => 'styles.css',
'type' => 'preload',
'as' => 'stylesheet'
]
];
foreach ($resourceHints as $resource) {
$this->pageConfig->addRemotePageAsset(
$resource['resource'],
'link_rel',
[
'attributes' => ['rel' => $resource['type']
]
);
}
return $this;
}
}

Registering the Magento 2 Extension

That’s it. You’re done coding! :) All you need to do now is register your extension following the conventional method:

  1. bin/magento setup:upgrade
    and if you’re in production mode:
  2. bin/magento setup:di:compile (or rm -rf generated/*)
  3. bin/magento setup:static-content:deploy [nl_NL en_US xx_XX]
  4. bin/magento cache:flush

Easily Configure Preconnect, Preload and Prefetch with Resource Hints for Magento 2

In this post I’ve discussed the basics of how to add resource hints — such as (DNS) preconnect, preload and prefetch — to Magento 2’s head in order to improve pageload times.

If you’re looking for a fast and easily configurable way to add Resource Hints to Magento 2, consider downloading Resource Hints for Magento 2. A Magento 2 extension created by me and freely available on Github. :)