Setting up Vue.js SSR (server-side rendering) for 1C-Bitrix

Our company is engaged in the development, support and maintenance of Bitrix and Bitrix24 solutions of any complexity. From simple one-page sites to complex online stores, CRM systems with 1C and telephony integration. The experience of developers is confirmed by certificates from the vendor.
Our competencies:
Development stages
Latest works
  • image_website-b2b-advance_0.png
    B2B ADVANCE company website development
    1175
  • image_bitrix-bitrix-24-1c_fixper_448_0.png
    Website development for FIXPER company
    811
  • image_bitrix-bitrix-24-1c_development_of_an_online_appointment_booking_widget_for_a_medical_center_594_0.webp
    Development based on Bitrix, Bitrix24, 1C for the company Development of an Online Appointment Booking Widget for a Medical Center
    564
  • image_bitrix-bitrix-24-1c_mirsanbel_458_0.webp
    Development based on 1C Enterprise for MIRSANBEL
    747
  • image_crm_dolbimby_434_0.webp
    Website development on CRM Bitrix24 for DOLBIMBY
    655
  • image_crm_technotorgcomplex_453_0.webp
    Development based on Bitrix24 for the company TECHNOTORGKOMPLEKS
    976

Configuring SSR (Server-Side Rendering) for Vue.js with 1C-Bitrix

SSR on Bitrix is rarely requested — and usually for one reason: SEO for Vue components with dynamic content. When a search bot receives a catalog page with a Vue filter, it sees an empty <div id="app"> instead of products. A traditional Bitrix template renders HTML on the server; a Vue component layered on top of it does not. SSR solves this problem but adds infrastructure complexity.

Architectural Options

Hybrid rendering (most practical for Bitrix): SEO-critical content (product listings, prices, specifications) is rendered via Bitrix's PHP in template.php. Vue mounts on top of the existing HTML and "hydrates" it — adding interactivity without re-rendering. This approach is called progressive hydration and does not require Node.js.

// template.php of the catalog component
echo '<div id="catalog-vue" data-items="' . htmlspecialchars(json_encode($arResult['ITEMS'])) . '">';
foreach ($arResult['ITEMS'] as $item) {
    // Server-rendered HTML for bots and initial load
    echo '<div class="catalog-item" data-id="' . $item['ID'] . '">' . $item['NAME'] . '</div>';
}
echo '</div>';

Vue mounts with app.mount('#catalog-vue') and adds interactivity: fast add-to-cart, view switching, comparison.

Nuxt.js as a middleware layer: a separate Nuxt server (Node.js) renders the Vue application and proxies data from Bitrix via REST API. Bitrix becomes a headless CMS. Full SSR, but effectively two separate applications. Justified for large projects with a substantial Vue frontend.

Vue SSR via @vue/server-renderer: rendering on Node.js, the result is embedded into the Bitrix template. Complex integration, high infrastructure requirements, rarely used in practice.

When SSR Is and Is Not Needed

SSR is needed if: Vue components generate content that must be indexed by search engines — product descriptions from an API, dynamic lists, infoblocks content loaded via AJAX.

SSR is not needed if: Vue is used only for interactive elements (cart, filters, forms) on top of already-rendered Bitrix content — the hybrid approach is sufficient.

Hydrating Vue on Bitrix Server-Rendered HTML

// The app uses data from data-attributes, does not make AJAX requests on mount
const mountEl = document.getElementById('catalog-vue');
const app = createApp(CatalogApp, {
    initialItems: JSON.parse(mountEl.dataset.items),
});
app.mount(mountEl);

createSSRApp instead of createApp activates hydration mode — Vue does not re-render the existing DOM but attaches event handlers to the already-present nodes. Requirement: the server-rendered HTML must exactly match what Vue would have generated itself. Mismatches cause "hydration mismatches" and trigger a full re-render.

Prerender as an Alternative

For pages with relatively static content (landing pages, category pages without personalisation) — prerendering via prerender-spa-plugin or a third-party service (Prerender.io). A crawler (headless Chrome) traverses the SPA, saves the HTML, and serves it to bots. No Node.js required in production.

Nginx configuration for prerendering:

location / {
    if ($http_user_agent ~* "googlebot|bingbot|yandex") {
        proxy_pass http://prerender-service:3000;
    }
}

Technical Requirements and Limitations

Node.js SSR requires: hosting that supports Node.js processes (not shared hosting), a process manager (PM2), a reverse proxy (Nginx → Node.js), and Node service monitoring.

Known limitations of SSR in a Bitrix context: Bitrix JS helpers (BX, BX.ajax) are unavailable on the server (Node.js) — all API calls must go directly through fetch/axios, not through the Bitrix SDK. The user session is passed via cookie, which requires CORS configuration between Node and PHP.

Typical timeline: setting up hybrid rendering (PHP + Vue hydration) for an existing component — 2–4 days. Deploying a full Nuxt SSR setup with Bitrix as a headless backend — 3–6 weeks including infrastructure.