How Does Magento's JavaScript Block Loader Work?

How Does Magento's JavaScript Block Loader Work?

Magento is a popular e-commerce platform because it is flexible and powerful in terms of optimizing the loading of the site and presenting content to users. Among many of the most important tenets of Magento architecture is the JavaScript Block Loader, which is responsible for loading dynamic blocks of content on a webpage.

What Are Block Loaders?

Block loaders are small animations, spinning wheels, for example, that would appear in a place on the website where something was loading. They help inform users that the site is still working on a request, like updating the cart or calculating totals.

These can range from product listings and promotional banners to search boxes. JavaScript Block Loader is a mechanism that allows Magento to load such blocks dynamically using JavaScript. Allowing Magento to load these blocks on-demand with JavaScript enhances overall performance for eCommerce sites, improves user experience, and optimizes resource management.

Why Does Magento Use a JavaScript Block Loader?

Dynamically loading content with JavaScript has a beneficial feature, especially in the ecommerce context.

  1. Faster Page Load Times: This will increase the page's speed because the browser loads only the main content to start and defers the other elements until needed.
  2. Better User Experience: It's the best possible method by which the key content would be visible to the users, and the secondary or dynamic content would be loaded in the background.
  3. Increased Flexibility: This will also allow developers to determine what parts of the page load immediately and what parts can load a bit later, allowing a more tailored experience for the customer.

How Magento’s JavaScript Block Loader Works

The Magento's JavaScript Block Loader is designed to run in concert with other Magento core components, notably its layout and rendering systems. Here overview of the process.

  1. Definition of Blocks in Layout XML Files:

The general structure of Magento pages is based on XML files. These files indicate the different blocks of content to be included and displayed on certain pages. For example, a product page may contain some blocks: product image, product description, price, related products, etc. Those blocks are defined in an XML layout file and it describes where and how each block should be displayed within the structure.

  1. Using Knockout.js for Binding and Rendering:

Magento uses the JavaScript module loader RequireJS for loading JavaScript modules, or blocks, asynchronously. As a consequence, only those scripts that are loaded and actually are needed at any given moment; might help improve page speed.

  1. RequireJS for Module Loading:

Magento uses the JavaScript module loader RequireJS for loading JavaScript modules, or blocks, asynchronously. As a consequence, only those scripts that are loaded which are actually needed at any given moment; might help improve page speed.

  1. Defining Blocks to Load Dynamically:

In the XML layout, developers can specify certain blocks to load with AJAX (Asynchronous JavaScript and XML) requests instead of loading them along with the main page. This is where Magento’s JavaScript Block Loader becomes essential.

  1. The AJAX Request:

When a block is configured to load dynamically, Magento triggers an AJAX request to the server that retrieves the block content after the page finishes loading. When the response comes back, JavaScript is invoked to display that block in its destination on the page.

  1. Rendering and Binding:

After the block content is loaded, Knockout.js binds the data to the HTML template, and the content appears on the page without requiring a full page reload.

Key Points

  1. Custom Knockout Binding:

    • The binding checks if a condition (likeisLoadin) is true or false.
    • If true, it shows the loader; if false, it hides it.
// Path: app/code/Mageleven/Loading/Ui/view/base/web/js/block-loader.js
ko.bindingHandlers.blockLoader = {
    /**
     * Process loader for block
     * @param {String} element
     * @param {Boolean} displayBlockLoader
     */
    update: function (element, displayBlockLoader) {
        element = $(element);

        if (ko.unwrap(displayBlockLoader())) {
            blockLoaderElement.done(addBlockLoader(element));
        } else {
            blockLoaderElement.done(removeBlockLoader(element));
        }
    }
};
Copy code
New tab
  1. Usage in Cart Totals:

    • In Mageleven_Loading/js/view/cart/totals, there's an isLoading property that controls the loader.
    • This property is mapped to an observable in the totals model, initially set to false.
// Path: app/code/Mageleven/Loading/view/frontend/web/js/view/cart/totals.js
define([
    'jquery',
    'uiComponent',
    'Magento_Checkout/js/model/totals',
    'Magento_Checkout/js/model/shipping-service'
], function ($, Component, totalsService, shippingService) {
    'use strict';

    return Component.extend({
        isLoading: totalsService.isLoading,

        /**
         * @override
         */
        initialize: function () {
            this._super();
            totalsService.totals.subscribe(function () {
                $(window).trigger('resize');
            });
            shippingService.getShippingRates().subscribe(function () {
                $(window).trigger('resize');
            });
        }
    });
});
Copy code
New tab
  1. Template Binding:

    • In the template file (Mageleven_Loading/template/cart/totals.html), the loader is applied to a wrapper div using the custom binding.
<div class="table-wrapper" data-bind="blockLoader: isLoading">
    <table class="data table totals">
        <caption class="table-caption" data-bind="text: $t('Total')"></caption>
        <tbody>
        <!-- ko foreach: elems() -->
            <!-- ko template: getTemplate() --><!-- /ko -->
        <!-- /ko -->
        </tbody>
    </table>
</div>  
Copy code
New tab
  1. Toggling Loaders:

    • The isLoading value is toggled in various parts of the code, causing the loader to show or hide.
define([
    'ko',
    'Magento_Checkout/js/model/quote',
    'Magento_Customer/js/customer-data'
], function (ko, quote, customerData) {
    'use strict';

    var quoteItems = ko.observable(quote.totals().items),
        cartData = customerData.get('cart'),
        quoteSubtotal = parseFloat(quote.totals().subtotal),
        subtotalAmount = parseFloat(cartData().subtotalAmount);

    quote.totals.subscribe(function (newValue) {
        quoteItems(newValue.items);
    });

    if (!isNaN(subtotalAmount) && quoteSubtotal !== subtotalAmount && quoteSubtotal !== 0) {
        customerData.reload(['cart'], false);
    }

    return {
        totals: quote.totals,
        isLoading: ko.observable(false),

        /**
         * @return {Function}
         */
        getItems: function () {
            return quoteItems;
        },

        /**
         * @param {*} code
         * @return {*}
         */
        getSegment: function (code) {
            var i, total;

            if (!this.totals()) {
                return null;
            }

            for (i in this.totals()['total_segments']) { //eslint-disable-line guard-for-in
                total = this.totals()['total_segments'][i];

                if (total.code == code) { //eslint-disable-line eqeqeq
                    return total;
                }
            }

            return null;
        }
    };
});
Copy code
New tab
  1. Monitoring Loaders:

    • To track how long users see the loaders, you could modify the addBlockLoader and removeBlockLoader functions to log the visibility times.
define([
    'jquery',
    '../model/quote',
    'Magento_Checkout/js/model/resource-url-manager',
    'Magento_Checkout/js/model/error-processor',
    'mage/storage',
    'Magento_Checkout/js/model/totals'
], function ($, quote, resourceUrlManager, errorProcessor, storage, totals) {
    'use strict';

    return function (callbacks, deferred) {
        deferred = deferred || $.Deferred();
        totals.isLoading(true);

        return storage.get(
            resourceUrlManager.getUrlForCartTotals(quote),
            false
        ).done(function (response) {
            var proceed = true;

            totals.isLoading(false);

            if (callbacks.length > 0) {
                $.each(callbacks, function (index, callback) {
                    proceed = proceed && callback();
                });
            }

            if (proceed) {
                quote.setTotals(response);
                deferred.resolve();
            }
        }).fail(function (response) {
            totals.isLoading(false);
            deferred.reject();
            errorProcessor.process(response);
        }).always(function () {
            totals.isLoading(false);
        });
    };
});
 
Copy code
New tab

Advantages of Using Magento's JavaScript Block Loader

  1. Improved Site Performance: Improvement in general page performance is achieved by dynamic loading of non-critical blocks. This works especially well for heavy content pages, like product pages with plenty of images and reviews.
  2. Enhanced User Experience: This will provide a better user experience, as the user will be able to view the main content while waiting for the secondary elements of the website to load.
  3. Better SEO Performance: While some dynamically loaded content does not directly impact SEO, on many other occasions, faster load indirectly creates a positive effect on SEO.
  4. Efficient Resource Use: Since it only blocks data when it needs to be loaded, the browser doesn’t have to spend the overhead of loading everything at once. It also saves bandwidth, which, in turn, can increase performance on a mobile device.

Key Points to Consider When Using JavaScript Block Loader

While Magento's JavaScript Block Loader is an excellent feature, it should also be used judiciously. Here are a few pointers for you to use it to its best use.

  1. Avoid Overloading Pages with AJAX Requests: With each AJAX request, it opens another call to the server, and too many of those will start to lag performance. Balance the quantity of blocks that you load dynamically, without overloading the page with requests.
  2. Prioritize Key Content: Save the JavaScript Block Loader for non-vital content like related products, reviews, or suggestions; header-load the crucial ones like product details and images.
  3. Monitor Server Load: Since AJAX requests call the server, it can greatly increase the number of calls to the server. Make sure your server can handle this without incident and prevent any downtime or slow response time.
  4. Optimize for SEO: Although most AJAX-loaded content is not indexed by search engines, with Magento's SEO you can make sure all the essential content is available for search engines.

Final Thoughts

The JavaScript block loader is a Magento Development valuable feature designed to load content as fast as possible through page speed improvements and user experience. It helps clear server resources for critical elements by allowing non-critical content to load asynchronously, thereby improving site performance. Whether you are running a small online store or perhaps a large-scale e-commerce platform, using a JavaScript block loader will have a huge impact on the effectiveness and usability of your site.

Understanding how the JavaScript block loader works gives you the possibility to implement it in the places where it really should be implemented so that your customers get a faster, more dynamic Magento store for a better experience. Remember the balance: load important content directly, where AJAX loading will make the process easier for users.

 

Need Assistance? Click Here for Support