Vue Router Setup for SPA on 1C-Bitrix
A user account area, multi-step checkout, filterable catalog — situations where navigation within an interface should not reload the page. Vue Router integrated with Bitrix requires careful configuration: Vue routes must not conflict with Bitrix's URL structure, and the server side must correctly handle direct navigation to SPA links.
History Modes: hash vs history
Hash mode (createWebHashHistory) — URL looks like /lk/#/orders. Advantage: no server configuration required; Bitrix receives a request to /lk/ and never sees the hash. Disadvantage: ugly URLs, bad for SEO (though an account area isn't indexed anyway).
History mode (createWebHistory) — URL like /lk/orders/. Clean URLs, but the server must return the same HTML for all SPA routes. In Bitrix this is solved via urlrewrite.php or .htaccess:
# .htaccess for SPA section /lk/
<IfModule mod_rewrite.c>
RewriteEngine On
RewriteBase /lk/
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule ^ /lk/ [L]
</IfModule>
A rule is added to Bitrix's urlrewrite.php to direct all requests inside /lk/ to a single PHP file — the SPA entry point. That file mounts the Vue application.
Route Structure for an Account Area
const routes = [
{
path: '/',
component: LkLayout,
children: [
{ path: '', redirect: 'orders' },
{ path: 'orders', component: OrdersList,
meta: { title: 'My Orders' } },
{ path: 'orders/:id', component: OrderDetail,
meta: { title: 'Order' } },
{ path: 'profile', component: ProfileEdit,
meta: { title: 'Profile' } },
{ path: 'addresses', component: AddressList,
meta: { title: 'Delivery Addresses' } },
]
},
{ path: '/:pathMatch(.*)*', component: NotFound }
];
const router = createRouter({
history: createWebHistory('/lk/'),
routes
});
base: '/lk/' in createWebHistory — so Vue Router doesn't get confused with Bitrix URLs higher in the tree.
Guards: Authorization Check
router.beforeEach((to, from, next) => {
const userStore = useUserStore();
if (!userStore.isAuthorized) {
// Redirect to the Bitrix authentication page
window.location.href = '/auth/?backurl=' + encodeURIComponent(to.fullPath);
return;
}
next();
});
Bitrix manages authentication at the PHP level — if the session has expired, the controller returns 401, the Vue application catches this in an axios interceptor and performs the redirect.
Lazy Route Loading
const OrderDetail = () => import('./pages/OrderDetail.vue');
Each route is a separate chunk. Vite splits the build; the order detail page loads only on first navigation. For an account area with 5–8 pages this reduces the initial load.
Preserving State Between Routes
keep-alive for components that shouldn't be recreated on return — for example, filters in the order list:
<RouterView v-slot="{ Component }">
<KeepAlive include="OrdersList">
<component :is="Component" />
</KeepAlive>
</RouterView>
When returning to the order list — filter state and scroll position are preserved. Data is refreshed via the onActivated hook.
Integration with Bitrix SEO Tools
For SPA pages that need to be indexed (catalog with filters), Vue Router runs in hash mode or Prerender.io / server-side pre-rendering is used. For closed sections (account area) — indexing is not needed, history mode with no restrictions.
Page meta tags on Vue Router navigation — via vue-meta or natively:
router.afterEach((to) => {
document.title = to.meta.title + ' — My Account';
});
Typical timeline: setting up Vue Router for an account area with 5–7 routes, including guards, lazy loading, and server configuration — 2–3 business days. For complex SPAs with nested routes and multiple authorization levels — 4–6 days.







