During a normal page render, the parser runs all modules sequentially: first the router, then the header, menu, content, recommendation blocks, widgets — and only after all of them have finished does the page get sent to the browser. If one of the modules performs a heavy database query or calls an external API, it delays the delivery of the entire page.
Lazy Loading solves this problem. The idea is simple: “heavy” modules do not run together with the page — instead of their output, the parser substitutes an AJAX placeholder. The browser receives the page instantly, displays it to the user, and then fetches the content of the deferred modules in the background and inserts their results into the appropriate places without reloading the page.
This is especially useful for blocks that: - execute slow aggregating SQL queries (statistics, recommendations, “similar products”); - call external services (exchange rates, stock availability via a supplier’s API); - are personalized and cannot be cached at the page level; - are not critical to the user’s initial perception of the page.
Lazy loading is a tool that is easy to overuse. If it is enabled for most modules on a page, the browser will fire dozens of parallel AJAX requests immediately after loading — one per module. This creates a peak load on the server that is indistinguishable in nature from a DDoS attack, except it is organized by the site itself.
A practical rule: lazy loading only makes sense for modules that are noticeably slower than the rest and do not affect the primary content of the page. There are typically one or two such modules on a page, rarely more than three.
To enable lazy loading, simply set the “Lazy Loading” flag in the right panel of the IDE in the settings of the desired module.
After this, the module’s behavior changes: during page rendering,
instead of its output, the parser automatically substitutes a block of
JavaScript code that: 1. Creates a container on the page with a unique
identifier (id = md5(module_name + parameters)). 2.
Immediately after the page loads, sends an AJAX request to fetch the
module’s content. 3. Inserts the received HTML into the container and
executes all <script> tags from the response.
Browser Server (index.php)
| |
|── GET /?topic_id=5 ────────────────>|
| |── Run(melbis_base_page)
| | ├─ melbis_base_header [normal]
| | ├─ melbis_cataloge [normal]
| | ├─ melbis_store_topic [normal]
| | └─ melbis_store_random [lazy] → AJAX placeholder
|<── Page HTML (fast) ────────────────|
|
|── POST /lazy/ {mod: melbis_store_random, params: ...} ──>|
| |── Run(melbis_store_random)
|<── Recommendation block HTML ─────────────────────────────|
|
[insert into container]
The AJAX request goes to the same index.php via the
lazy/ route, which must be defined in
.htaccess:
RewriteRule ^lazy/$ index.php?lazy [L,QSA]In the root script index.php, this route is handled by a
separate branch:
if ( isset($_GET['lazy']) )
{
$entry_point = $_POST['mod'];
$entry_param = $_POST['params'];
}The module’s parameters are passed URL-encoded via POST — the parser forms them automatically from the same parameters with which the module was called in the template. The developer does not need to do anything extra: enable the checkbox and the module becomes lazy; disable it and it returns to normal mode.
A module with lazy loading enabled remains a fully functional entry point — when called lazily, it is processed in exactly the same way as during a normal call, and can use the cache, libraries, and any other platform features.