JavaScript Deferral v25.1+
Maho includes a JavaScript deferral system that improves page load performance by controlling how <script> tags are loaded on frontend pages. Instead of blocking the initial render, scripts can be deferred or loaded only when a user interacts with the page.
Configuration
Navigate to System > Configuration > Developer > JavaScript Settings in the admin panel. The JavaScript Defer Mode setting (dev/js/defer_mode) offers three modes:
| Mode | Value | Description |
|---|---|---|
| Disabled | 0 | Default behavior, scripts load normally |
| Defer Only | 1 | Moves all scripts to the bottom of <body> |
| Load on Intent | 2 | Scripts are neutralized and only activated on first user interaction |
Defer Only Mode
The simplest and safest option. All <script> tags are extracted from their original positions in the HTML and moved to the bottom of <body>, just before the closing </body> tag. This allows the browser to parse and render the page content before downloading and executing JavaScript.
This mode preserves the original execution order of scripts and should be compatible with virtually all themes and extensions.
Load on Intent Mode
A more aggressive optimization that delays JavaScript execution until the user actually interacts with the page.
How it works
-
Neutralization — All
<script>tags have theirtypeattribute changed totext/plainand receive adata-maho-scriptindex attribute. This prevents the browser from executing them. -
Intent detection — The loader script (
maho-load-on-intent.js) listens for the first user interaction via any of these events:click,keydown,mousemove,mouseover,touchstart,scroll,wheel,focusin,change
-
Parallel preload — When an interaction is detected, all external scripts are immediately preloaded in parallel using
<link rel="preload" as="script">tags. -
Sequential execution — Scripts are then executed one by one in their original order. External scripts wait for their
onloadevent before the next script runs, ensuring dependency order is preserved. -
Synthetic lifecycle events — After all scripts have executed, the loader fires synthetic
DOMContentLoadedandloadevents, and setsdocument.readyStateto"complete". This ensures scripts that rely on these lifecycle signals still work correctly.
Experimental
Load on Intent mode is designed for pages with vanilla JavaScript. It may not work correctly with legacy libraries or complex third-party scripts that make assumptions about load timing. Test thoroughly before enabling in production.
Excluding Scripts from Deferral
Add the data-maho-nodefer attribute to any <script> tag that must execute immediately, regardless of the defer mode.
<script data-maho-nodefer>
// This script will execute immediately, even in Load on Intent mode
window.criticalConfig = { storeId: 1 };
</script>
In a .phtml template:
Common use cases for data-maho-nodefer:
- Consent management / cookie banners
- Critical analytics or tracking pixels
- Essential inline configuration that other deferred scripts depend on
Automatic Exclusions
The deferral system is automatically skipped in the following cases:
- Admin panel — All admin pages load scripts normally
- Checkout pages — The
checkoutmodule is excluded to avoid breaking payment flows - Non-HTML responses — JSON, XML, and other non-HTML content types are not processed
- Speculation rules — Scripts with
type="speculationrules"are never deferred - Already processed — Pages that have already been processed are not processed again
Programmatic Configuration
The defer mode is stored at config path dev/js/defer_mode. Mode constants are defined in Mage_Core_Model_Source_Js_Defer:
Mage_Core_Model_Source_Js_Defer::MODE_DISABLED // 0
Mage_Core_Model_Source_Js_Defer::MODE_DEFER_ONLY // 1
Mage_Core_Model_Source_Js_Defer::MODE_LOAD_ON_INTENT // 2
To check the current mode programmatically: