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:upgradecommand 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.jsas 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
lazysizesloader to your module. - Adding the
lazyloadclass to yourmaster.htmlandpreview.htmltemplates. - 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.htmlandpreview.htmltemplates. - Change the
desktop_imageandmobile_imageelements to usedata-srcrather 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.jsfile 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-srcinstead ofsrcfor 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.