Magento 2 Javascript Bundling - Group/Combine JS files

This article explores Magento 2 JavaScript Bundling, focusing on how it groups and combines JS files.

Covering key aspects like why JavaScript bundling is useful, adjusting bundle size, creating exclusion lists, enabling bundling, and checking performance, this guide aims to help you better optimize your Magento 2 stores.

Table of Contents

What is Javascript bundling?

Javascript bundling is an optimization technique that is used in today’s module-based development to group individual files to decrease the number of HTTP requests which are needed to load a page. This is acquired by merging multiple JavaScript files together into one file. Besides, it denies the main advantage of using module loaders such as RequireJS which is loading files asynchronously.

Why use Javascript bundling?

Before explaining why bundling should be used, let’s have a glance at the two ways in which assets are loaded in Magento 2.

In this following image, you will see the way assets are loaded on two different pages in Magento which are Homepage and Product page.

js

With requireJS, different assets are loaded through different pages while all bundles are loaded even if they are not needed. In other words, you are able to reduce the number of requests by only loading necessary assets. However, there are still a huge number of JS files being loaded. If these assets could be merged into just a few files, the performance could be improved even more.

This is where Bundling comes in. It is a great solution to merge modules and their dependencies into individual files. Therefore, you could decide the place to load a specific bundle. For instance, you can put all checkout-related files into a bundle and load that bundle on the checkout page. Besides, if you want to merge JS modules, you will have to use bundling, as, without it, you can only merge Javascript files which are not being loaded via RequireJS.

Despite the fact that bundling is missing key features, you can still change a couple of things to organize your bundles better.

How bundling works

The Magento 2 JS Bundling mechanism functions by consolidating all JavaScript bundles into a limited number of bundles, which are then loaded for all pages. During page rendering, the browser synchronously downloads all the bundles, and it adheres to the Magento Standard, requiring each bundle to be at least 100KB. For convenience, exclusions of specific files that cannot be processed in bundling can be implemented using the etc/view.xml configuration. Below is a code snippet from the Luma theme, illustrating the types of files that should be excluded from the bundling process.

<exclude>
    <item type="file">Lib::jquery/jquery.min.js</item>
    <item type="file">Lib::jquery/jquery-ui-1.9.2.js</item>
    <item type="file">Lib::jquery/jquery.ba-hashchange.min.js</item>
    <item type="file">Lib::jquery/jquery.details.js</item>
    <item type="file">Lib::jquery/jquery.details.min.js</item>
    <item type="file">Lib::jquery/jquery.hoverIntent.js</item>
    <item type="file">Lib::jquery/colorpicker/js/colorpicker.js</item>
    <item type="file">Lib::requirejs/require.js</item>
    <item type="file">Lib::requirejs/text.js</item>
    <item type="file">Lib::date-format-normalizer.js</item>
    <item type="file">Lib::legacy-build.min.js</item>
    <item type="file">Lib::mage/captcha.js</item>
    <item type="file">Lib::mage/dropdown_old.js</item>
    <item type="file">Lib::mage/list.js</item>
    <item type="file">Lib::mage/loader_old.js</item>
    <item type="file">Lib::mage/webapi.js</item>
    <item type="file">Lib::mage/zoom.js</item>
    <item type="file">Lib::mage/translate-inline-vde.js</item>
    <item type="file">Lib::mage/requirejs/mixins.js</item>
    <item type="file">Lib::mage/requirejs/static.js</item>
    <item type="file">Magento_Customer::js/zxcvbn.js</item>
    <item type="file">Magento_Catalog::js/zoom.js</item>
    <item type="file">Magento_Ui::js/lib/step-wizard.js</item>
    <item type="file">Magento_Ui::js/form/element/ui-select.js</item>
    <item type="file">Magento_Ui::js/form/element/file-uploader.js</item>
    <item type="file">Magento_Ui::js/form/components/insert.js</item>
    <item type="file">Magento_Ui::js/form/components/insert-listing.js</item>
    <item type="directory">Magento_Ui::js/timeline</item>
    <item type="directory">Magento_Ui::js/grid</item>
    <item type="directory">Magento_Ui::js/dynamic-rows</item>
    <item type="directory">Magento_Ui::templates/timeline</item>
    <item type="directory">Magento_Ui::templates/grid</item>
    <item type="directory">Magento_Ui::templates/dynamic-rows</item>
    <item type="directory">Magento_Swagger::swagger-ui</item>
    <item type="directory">Lib::modernizr</item>
    <item type="directory">Lib::tiny_mce</item>
    <item type="directory">Lib::varien</item>
    <item type="directory">Lib::jquery/editableMultiselect</item>
    <item type="directory">Lib::jquery/jstree</item>
    <item type="directory">Lib::jquery/fileUploader</item>
    <item type="directory">Lib::css</item>
    <item type="directory">Lib::lib</item>
    <item type="directory">Lib::extjs</item>
    <item type="directory">Lib::prototype</item>
    <item type="directory">Lib::scriptaculous</item>
    <item type="directory">Lib::less</item>
    <item type="directory">Lib::mage/adminhtml</item>
    <item type="directory">Lib::mage/backend</item>
</exclude>

In this approach, although we have the ability to exclude certain scripts from the bundle, we face a limitation in loading only page-specific bundles. This limitation contributes to delays in loading data related to elements like the mini-cart or other checkout-related information after the initial page load. Furthermore, this approach has an impact on increasing the file size of the bundle, especially when enabling the Minify/Merge JS option in the backend. Enabling the Minify JS option results in the file (bundle0.min.js) reaching a substantial size, such as 8 MB. Magento JS Bundling, by default, leads to an increase in the file size of the bundle, prompting consideration of alternative options like Advanced JS Bundling. Logically, loading all JS, much of which is not necessary for specific pages, may contribute to these challenges.

Configure Bundle size and exclude list

The bundle size can be changed as well as several scripts can be excluded from the bundle in Vendor/Theme/etc/view.xml.

bundle size

1MB is the default size for a bundle. Please remember that the number of bundles that will be created are determined by bundle size. For instance, four bundles will be created if you have 4MB of script files and set the bundle size to 1MB.

However, you need to be really careful cause if the number is too low, 10 or more small bundles will be created and block each other during rendering.

Please keep in mind that bundles are loaded synchronously.

Excluding files

Besides, certain scripts can also be excluded from bundles. You can use RequireJS to load them if you need to.

Remember that two themes which are Luma and Blank have their own exclude lists, so if you do not fall back properly as well as do not have an exclude list for your own, all JS modules would be bundled even if you do not need them. This would make the bundles become huge.

The handle <exclude> will deal with all the files which should be excluded from the bundle. In Magento 2, bundle content on each page cannot be decided, however, the assets that will not be required through the whole site can be excluded. Because of that, bundles will only consist of the files that are required.

Activate Javascript bundling

Once the bundle size and exclude list have been configured, now you can enable it.

To turn it on, please follow this: Stores > Configuration > Advanced > Developer

Activate Javascript bundling

Because the bundling only works in Production mode, after turning it on, you need to clear cache and switch the mode from Developer to Production. After doing the above steps, the static files will be deployed and your bundles will be loaded on the Frontend.

Check Performance

After activating the bundling, the number of requests through the site has reduced significantly. However, there is still one problem with performance. You will see it when comparing the performance before and after turning on the Javascript bundling.

The following picture is the Luma theme’s Homepage. The testing was completed on the 2.2.0 “dev” version of Magento. The following setting is in the Dev console (Chrome):

check performance

Before activating the bundling, the number of JS requests is 137, the size is 2.0MB and the load time is 9.46sec

performance checking

Meanwhile, if you turn on the Javascript bundling, the number of JS requests are cut down dramatically to 8 requests, but the total file size of generated bundles is becoming even larger than the file size of all non-bundled JavaScript files on the frontend in total. Also, the load time is also increased from 9.46 to 20.12sec. This is mainly because while the RequireJS helps you load only necessary JS files on a specific page, bundling merges all JS assets and serves them on all pages.

Advanced bundling Javascript

Advanced Bundling consolidates all packages and delivers them as a single unit, enhancing speed performance while decreasing server requests and bundle size for every loaded browser page.

To implement Advanced Bundling for JavaScript, it’s essential to create specific bundles for each page, focusing on those that are crucial, such as the Home page, Category Page, Product Page, Cart, and Checkout Page.

For instance, you could create bundles like one for dependencies shared across all pages, another for CMS-only pages, a separate bundle for Catalog-only pages, an additional one for Search-only pages, and a specific bundle for Checkout pages.

Required tools

Requirejs Node.js PhantomJS (optional)

Conclusion

In conclusion, you can see the biggest benefit you will get when using Javascript bundling is that this tool helps you bundle multiple files into single files. However, the drawbacks outweigh the advantages. More specifically:

  • It negates the benefits when using a module loader.
  • Bundles’ file size is much larger than all non-bundled javascript files sizes in total.
  • You will not be able to define bundle content accurately.
  • The pages and the bundle which will be loaded cannot be decided.

I hope this post can provide you with the basic knowledge about Javascript Bundling and how you can use it to better your Magento 2 performance.

Thank you for reading! I’m pleased to see your discussion in the comment section.

Image Description
Hello, I'm the Chief Technology Officer of Mageplaza, and I am thrilled to share my story with you. My deep love and passion for technology have fueled my journey as a professional coder and an ultra-marathon runner. Over the past decade, I have accumulated extensive experience and honed my expertise in PHP development.
x