This module shows how to add lazy loading behavior to the Image content type. For this example, we use the lazysizes loader. The module also supports native lazy loading using the lazysizes native-loading plugin. But, as of this writing, the nativeLoading
plugin (v 5.1.1) seems to mess with the lazysizes loader, so I commented it out.
These steps assume you have already cloned the pagebuilder-examples
repo to the root of your Magento instance, as described in Installing the example modules:
-
Navigate to to the
app/code/
directory and create a symlink using the following command:ln -s ../../pagebuilder-examples/Image
-
From the Magento root directory, run the
setup:upgrade
command to install and enable the module:bin/magento setup:upgrade
-
Drag and drop several Image content types onto the stage, upload images to each, and Save.
-
Open the Network tab in Chrome's devtools and watch the magic (you should see
lazysizes.js
as the initiator for your images).
Adding lazy loading (using lazysizes) to the Page Builder Image content type turns out to be fairly simple. There's very little coding involved and only a few small changes to the native Image content type configuration and HTML templates.
There are three main tasks:
- Adding the
lazysizes
loader to your module. - Adding the
lazyload
class to yourmaster.html
andpreview.html
templates. - Overriding Page Builder's native Image config (
image.xml
).
First, we add the lazysizes
loader to our module in the base
directory. By adding it to the base directory, Magento makes the loader available within the admin on the Page Builder stage and on the storefront where it really matters.
There are several approaches you could take to adding the lazysizes
loader to your own module. But the approach that seems easiest is to include it within the <head>
of both admin and frontend pages using the default.xml
layout, as shown here:
<page xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" layout="admin-1column" xsi:noNamespaceSchemaLocation="urn:magento:framework:View/Layout/etc/page_configuration.xsd">
<head>
<script src="Image_LazyLoading/js/resource/lazysizes/lazySizesConfig.js"></script>
<script src="Image_LazyLoading/js/resource/lazysizes/lazysizes.min.js"></script>
<script src="Image_LazyLoading/js/resource/lazysizes/ls.attrchange.min.js"></script>
<!-- CDN -->
<!--<script src="https://cdnjs.cloudflare.com/ajax/libs/lazysizes/5.1.1/lazysizes.min.js" src_type="url"></script>-->
<!--<script src="https://cdnjs.cloudflare.com/ajax/libs/lazysizes/5.1.1/plugins/attrchange/ls.attrchange.min.js" src_type="url"></script>-->
</head>
</page>
This example uses local copies of the lazysizes loader (lazysizes.min.js
) and plugin (ls.attrchange.min.js
). However, CDN versions of lazysizes and all its plugins are also available.
The lazySizesConfig.js
file is optional, but if you use it, you must load it before you load the lazysizes loader. Here is the recommended way of making custom configurations:
(function () {
window.lazySizesConfig = window.lazySizesConfig || {};
window.lazySizesConfig.loadMode = 1;
window.lazySizesConfig.expand = 0;
})();
To learn more about configuring the lazysizes loader, see: https://github.com/aFarkas/lazysizes#js-api.
Copy the master.html
and preview.html
templates from Page Builder's native Image content type. Then add the lazyload
class to the existing classes on the <img>
tags, as shown in the snippet here:
<img attr="data.desktop_image.attributes"
class="lazyload pagebuilder-mobile-hidden"
css="data.desktop_image.css"
ko-style="data.desktop_image.style" />
<img attr="data.mobile_image.attributes"
class="lazyload pagebuilder-mobile-only"
Here we want to override the Page Builder's native Image configuration (image.xml
) with our own image.xml
. And because of Magento's XML merging, we only have to make two minor configuration changes:
- Change the HTML template references to point to our module's
master.html
andpreview.html
templates. - Change the
desktop_image
andmobile_image
elements to usedata-src
rather thansrc
(as most lazy loaders require).
We show both changes in our example module's image.xml
config file:
<config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:module:Magento_PageBuilder:etc/content_type.xsd">
<type name="image">
<appearances>
<appearance default="true"
name="full-width"
preview_template="Image_LazyLoading/content-type/image/full-width/preview"
master_template="Image_LazyLoading/content-type/image/full-width/master">
<elements>
<element name="desktop_image">
<attribute name="image" source="data-src" converter="Magento_PageBuilder/js/converter/attribute/src" preview_converter="Magento_PageBuilder/js/converter/attribute/preview/src"/>
</element>
<element name="mobile_image">
<attribute name="mobile_image" source="data-src" converter="Magento_PageBuilder/js/converter/attribute/src" preview_converter="Magento_PageBuilder/js/converter/attribute/preview/src"/>
</element>
</elements>
</appearance>
</appearances>
</type>
</config>
That's all there is to it!
Instead of using lazysizes
, you can use other lazyloaders (like lozad) using a similar approach:
- Add
lozad.js
file to your module or use a CDN. - Add the 'lozad' class to your template
<img>
tags. - Override the native Image configuration to point to your templates and use
data-src
instead ofsrc
for you desktop and mobile image sources.
Bruce Denham. Contact us on the Slack #pagebuilder channel for questions specific to this example.
We encourage and welcome you to help us keep these examples current by submitting Issues and Pull Requests. We also welcome your feedback and ideas on other code examples you would like to see added to this repo.