Defer JS, it means that you should load all of your js after the page dom is rendered. you can do it by Event and Observer in Magento 2.
Let me explain how you can create Event and Observer for that.
Create events.xml inside etc folder in your custom module, Like-
/app/code/Vishal/DeferJS/etc/frontend/events.xml
and paste the below code
<?xml version="1.0"?>
<config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:framework:Event/etc/events.xsd">
<event name="controller_front_send_response_before">
<observer name="vishal_deferjs" instance="Vishal\DeferJS\Model\Observer" shared="false" />
</event>
</config>
Now create Observer for that. Like-
/app/code/Vishal/DeferJS/Model/Observer.php
and paste the below code
<?php
namespace Vishal\DeferJS\Model;
use Magento\Framework\Event\ObserverInterface;
class Observer implements ObserverInterface
{
public function execute(\Magento\Framework\Event\Observer $observer)
{
$response = $observer->getEvent()->getData('response');
if (!$response)
return;
$html = $response->getBody();
if ($html == '')
return;
$conditionalJsPattern = '@(?:<script type="text/javascript"|<script)(.*)</script>@msU';
preg_match_all($conditionalJsPattern, $html, $_matches);
$if_js = implode('', $_matches[0]);
$html = preg_replace($conditionalJsPattern, '', $html);
$html .= $if_js;
$response->setBody($html);
}
}
That's it... Now Clear/Flush the cache and refresh your page. you can check the source code of that page by (ctrl + U). and you will see all your JS file/code will be placed at the bottom of body.