Shopware 6.6 was recently released and brings numerous improvements under the hood. It is a very technical release, which on the one hand cuts out old habits, but on the other hand offers new possibilities. One of these features is equally interesting and has been the subject of much discussion in the developer community. Your JavaScript plugins can now be loaded as required.

Previously (and by previously I mean that this was already the case in Shopware 5), all JavaScript plugins that Shopware (but also the installed extensions) came with were compressed into a bundle, which was then loaded across all pages of the store. This causes several problems from a performance perspective:

  • The bundle can sometimes be very large, an empty Shopware 6.5 already comes with almost 600 KB. Fully equipped with extensions, it can easily add up to 1-2 MB.

  • Not every JavaScript plugin needs to be available on every page.

  • There is no distinction between mobile and desktop.

The new approach offers several advantages: Firstly, JavaScript plug-ins are only loaded when the DOM requests it

The second advantage is that the plugin data is loaded asynchronously. They therefore do not block the structure of the website. This is now also an important metric for performance measurement tools such as Google Lighthouse.

Sidenote:_ The approach results in a minimal overhead if you compare the pure file size of all asynchronous requests with that of the bundle. However, the advantages gained outweigh this enormously.

Registering a JavaScript plugin

Shopware has a so-called PluginManager, which can be used to register your plugins. To take advantage of the new registration approach, you should link it to an element from your DOM. This also marks the main scope of your plugin. Typically, this is implemented in Shopware using data attributes. Your template then has a dedicated attribute on an HTML tag of your choice - for example

.

Hint: All selectors work, which means you are free to choose your mounting point. However, we recommend that you follow the Shopware 6 coding conventions.

The complete template file in our example would look like this:

[pluginroot/src/Ressources/view/storefront/page/content/index.html.twig]

{% sw_extends '@Storefront/storefront/page/content/index.html.twig' %}

{% block base_main_inner %}
    {{ parent() }}

    <div data-load-me-if-needed-only="true"></div>
{% endblock %}

Once you have prepared this, the plugin is registered in main.js (this is still your entry point for writing your plugin):

[pluginroot/src/Ressources/app/storefront/src/main.js]

window.PluginManager.register('AsyncTest', () => import('./plugin/async-test.plugin'), '[data-load-me-if-needed-only="true"]');

This call hides the two components that are connected to each other: The selector '[data-load-me-if-needed-only="true"]', which corresponds to the attribute in the template, and the path './plugin/async-test.plugin', which contains your actual plugin logic. This logic is loaded asynchronously in your storefront as required.

[pluginroot/src/Ressources/app/storefront/src/plugin/async-test.plugin.js]

import Plugin from 'src/plugin-system/plugin.class';

export default class AsyncTestPlugin extends Plugin {
    init() {
        // eure Plugin-Logik sowie weitere Methoden
    }
}

The performance advantages

As delivered, your JavaScript plugin consists of several files: The entry point, which corresponds to the content of your main.js. This should not contain more than plugin registrations or overrides. Then each of your JavaScript plugins gets another file if you register the plugins as described above. These files are only loaded when the DOM needs them. In this small example, only a few KB are saved, but your extensions usually contain significantly more complexity. It also adds up, depending on the degree of customization of your store.

In your storefront you will only find this call to your entry point:

<script type="text/javascript" src="http://mystore.url/theme/140d3e1034b4bae36039a6a20638664b/js/js-async-test/js-async-test.js?1712670563" defer></script>

The 'defer' attribute is important here, which tells the browser that the script file should be loaded in parallel and executed later (after the document has been parsed). This functionality is natively available on all common browsers.

Conclusion:

This change has been long awaited and solves many performance issues of your storefront. It doesn't take much work to convert your JavaScript plugins and your store will be noticeably faster. The pure feature set of version 6.6 is inconspicuous on the outside, but a lot has happened under the hood, which definitely makes the update worthwhile!