Setting up preload/prefetch resources for 1C-Bitrix
The browser loads HTML, parses it, finds <link rel="stylesheet"> on the 5th line, goes for CSS, waits, parses CSS, finds fonts in @font-face, goes for fonts — this is a critical request chain that blocks rendering. preload tells the browser about needed resources in advance, before the parser discovers them. prefetch loads resources needed on the next page.
Difference between preload and prefetch
<link rel="preload"> — high priority, the resource is needed on the current page immediately. The browser starts loading before processing the main HTML. If the resource is not used within 3 seconds after loading — the browser will issue a warning in the console.
<link rel="prefetch"> — low priority, the resource will be needed on the next page. Loads in the background, placed in the cache. Works great for loading JS of the next catalog section while the user is reading the current page.
<link rel="preconnect"> — establishes TCP connection and TLS handshake before the resource is requested. Useful for external domains: CDN, Google Fonts, Yandex.Metrica.
Adding preload to Bitrix template
The site template in Bitrix is /bitrix/templates/[template_name]/header.php. Add to <head> before main tags:
<?php
// Get file hash version for cache busting
$cssVersion = filemtime($_SERVER['DOCUMENT_ROOT'] . '/bitrix/templates/.default/styles.css');
$jsVersion = filemtime($_SERVER['DOCUMENT_ROOT'] . '/bitrix/js/main/core/core.js');
?>
<head>
<meta charset="utf-8">
<!-- Preload critical CSS (rendering blocked without it) -->
<link rel="preload" href="/bitrix/templates/.default/styles.css?v=<?=$cssVersion?>"
as="style" onload="this.onload=null;this.rel='stylesheet'">
<noscript>
<link rel="stylesheet" href="/bitrix/templates/.default/styles.css?v=<?=$cssVersion?>">
</noscript>
<!-- Preload font (as="font" is mandatory, otherwise priority is incorrect) -->
<link rel="preload" href="/bitrix/templates/.default/fonts/roboto.woff2"
as="font" type="font/woff2" crossorigin>
<!-- Preconnect to external resources -->
<link rel="preconnect" href="https://mc.yandex.ru">
<link rel="preconnect" href="https://www.googletagmanager.com">
<!-- DNS-prefetch as fallback for old browsers -->
<link rel="dns-prefetch" href="//mc.yandex.ru">
</head>
Programmatic preload via Bitrix API
Bitrix provides methods for managing Link headers through the \Bitrix\Main\Page\Asset class:
// In a component or template
$asset = \Bitrix\Main\Page\Asset::getInstance();
// Preload JS file
$asset->addJs('/bitrix/js/ui/ui.js', [
'rel' => 'preload',
'as' => 'script'
]);
// Preload CSS
$asset->addCss('/bitrix/templates/.default/critical.css', [
'rel' => 'preload'
]);
Via HTTP header from OnPageStart event handler:
AddEventHandler('main', 'OnPageStart', function() {
header('Link: </bitrix/templates/.default/styles.css>; rel=preload; as=style', false);
header('Link: </bitrix/templates/.default/fonts/roboto.woff2>; rel=preload; as=font; crossorigin', false);
});
Prefetch for catalog
If the user is on the main page, there's a high probability of navigating to the catalog. Prefetch the main catalog JS:
<?php
// In footer.php of main page
if (defined('IS_INDEX_PAGE') && IS_INDEX_PAGE):
?>
<link rel="prefetch" href="/bitrix/js/catalog/catalog.js">
<link rel="prefetch" href="/catalog/">
<?php endif; ?>
Prefetch HTML page (/catalog/) places it in the browser cache — navigation will be instant. But this only works if the page has proper cache headers.
Critical CSS for Bitrix
The most significant gain comes from inline critical CSS — styles necessary for rendering the visible part of the page, embedded directly in HTML. This eliminates the blocking CSS request entirely.
Tool for extracting critical CSS:
npm install -g critical
critical --base /var/www/bitrix/public_html \
--src index.html \
--css bitrix/templates/.default/styles.css \
--width 1300 --height 900 \
--inline --extract
Insert the resulting critical CSS in the Bitrix template in a <style> tag in <head>, load the main CSS asynchronously via preload with onload as shown above.
Common mistakes
Preload without as — browser doesn't know the resource type, loads with incorrect priority and caches separately. Resource is loaded twice: once via preload, second — when the parser finds the <script> or <link> tag.
Preload fonts without crossorigin — CORS request to the same domain requires crossorigin for fonts. Without it the browser loads the font twice.
Too many preload — priority for everyone = priority for no one. Maximum 3–5 preload per page for truly critical resources.







