Magento 2 Optimization Advanced Javascript Merging in Magento
Most people double take when I tell them that simply merging all of your Javascript files (even if Google and Yahoo tell you too) is not a good idea but honestly, it's really not a good idea if you want a fast Magento site.
Javascript Merging is bad, you say?
Yes I really said it. Merging Javascript files into a single file will not make your website faster (although the online speed reports might tell you otherwise) and will actually force your customer's into downloading the same JS content multiple times.
Let's say on your homepage you have file1.js and file2.js. These files are merged into file1-2.js and the customer - let's call him John - downloads this and his browser caches it. If he tries to download this file again, the browser will skip the download and load the cached copy. This is great because John only had to download a single file, which is definitely going to be quicker than downloading the two files separately.
After visiting the homepage, John clicks on a link that takes him to a product page. On this product page, the same two files from the homepage are included (file1.js and file2.js) but there is also a third (file3.js) and fourth (file4.js) file that are included that handle product javascript and are only ever included on the product page. Your website combines these four files into a new file called file1-2-3-4.js and John downloads this file. Do you see what has happened there? This new file contains file1.js and file2.js, which John has already downloaded and cached in his browser. As a result, John wastes time downloading content that he already has.
This is a common example that is happening on every single Magento website that uses Magento's Javascript Merging feature. Fortunately it's quite easy to fix this issue.
Advanced Javascript Merging
Javascript merging isn't bad but merging all Javascript into a single file is bad. A better way to merge your JS files is to merge them based on their usage. All JS files that are included on every page should be merged into a single file. You can then start merging the rest of your files based on where they are included. For example, you could merge all of the JS files that are on every product page into a single JS file and include that. Let's try that logic looking at our example with John.
Just like last time John downloads file1-2.js (which is made up of file1.js and file2.js) while visting the homepage of our site. This is cached and if he comes across this specific file again, his browser will skip the download and use the cached copy.
John then heads over to the product page where he finds two Javascript files: file1-2.js and file3-4.js. The first file (file1-2.js) has already been downloaded and cached so his browser skips this download and saves time. The second file (file3-4.js) is a new file which John hasn't seen before so his browser downloads and caches this file.
Using this approach each item of Javascript is only ever downloaded a single time and John never wastes time downloading content is already on his computer.
Implementing Advanced Javascript Merging in Magento
Clever Javascript merging is possible in Magento and quite easy. To do it, we create new block of type 'page/html_head'. This can be position anywhere in your layout (even in the footer if you want to put the JS at the bottom of your page) but I'm going to add it as a child of the existing 'head' block.
<reference name="head"> <block type="page/html_head" name="custom.js" template="page/html/head/js-merge.phtml" /> </reference>
Next we need to create the page/html/head/js-merge.phtml template in our custom theme.
<?php echo $this->getCssJsHtml() ?>
This template need only contain the single line above.
Finally we can start adding JS files to it using the usual XML layout method.
<reference name="custom.js"> <action method="addJs"><script>varien/product.js</script></action> </reference>
Separate Magento Product JS
Let's take a look at a real world example. The following XML shows how to set this up for a Magento product using a default Magento installation with the default Magento JS files loaded. If you have custom JS files loaded on your product page, you would need to adjust accordingly.
You should notice that as the JS files I'm adding to the custom block have already been added to the default Head block, they must first be removed. If we don't remove them, the files will be included twice.
<catalog_product_view> <reference name="head"> <!-- /** * We first remove the JS from the default 'head' block **/ --> <action method="removeItem"> <type>js</type> <script>varien/product.js</script> </action> <action method="removeItem"> <type>js</type> <script>varien/configurable.js</script> </action> <action method="removeItem"> <type>js</type> <name>calendar/calendar.js</name> </action> <action method="removeItem"> <type>js</type> <name>calendar/calendar-setup.js</name> </action> <!-- /** * We then define the new block as a child of 'head' * This doesn't have to be as a child of head. It can be included anywhere */ --> <block type="page/html_head" name="head.product_js" template="page/html/head/js-merge.phtml"> <!-- /** * We then add the JS back but into our new block * This could be done elsewhere using <reference name="head.product_js"> **/ --> <action method="addJs"> <script>varien/product.js</script> </action> <action method="addJs"> <script>varien/configurable.js</script> </action> <action method="addItem"> <type>js</type> <name>calendar/calendar.js</name> </action> <action method="addItem"> <type>js</type> <name>calendar/calendar-setup.js</name> </action> </block> </reference>
After this, you need to ensure that you have created the page/html/head/js-merge.phtml template (the single line of code you need for this file can be found above). If you enable merging in Magento, the two sets of JS files will now be merged separately and you will be only asking customers to download each piece os Javascript code a single time.
As a side note, you can remove the calendar.js and calendar-setup.js files completely as they are rarely required for a Magento installation.