Setting up a Vue.js (Webpack/Vite) build for a 1C-Bitrix project

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 the Vue.js Build (Webpack/Vite) for a 1C-Bitrix Project

Bitrix historically lived without a bundler — PHP templates, CDN-loaded jQuery and plugins, minimal JS in template.php. Adding Vue changes all of this: you need .vue file compilation, modern JS transpilation, code splitting, and tree-shaking. A poorly configured build results in a 1 MB+ bundle on every page or conflicts with Bitrix's own scripts.

Vite for New Projects

Vite is the standard for Vue 3 projects. Key advantages in a Bitrix context: instant dev server (HMR without a full rebuild), fast production builds via Rollup, built-in TypeScript and .vue SFC support.

Base configuration for a Bitrix project:

// vite.config.js
import { defineConfig } from 'vite';
import vue from '@vitejs/plugin-vue';
import path from 'path';

export default defineConfig({
    plugins: [vue()],
    root: 'local/vue-src',
    build: {
        outDir: '../../local/dist',
        emptyOutDir: true,
        manifest: true,  // generates manifest.json for PHP
        rollupOptions: {
            input: {
                catalog: 'local/vue-src/catalog/main.js',
                cart: 'local/vue-src/cart/main.js',
                lk: 'local/vue-src/lk/main.js',
            },
        },
    },
    resolve: {
        alias: { '@': path.resolve(__dirname, 'local/vue-src') },
    },
});

manifest: true — Vite generates a manifest.json that maps entry file → hashed name. PHP reads this file and includes the current bundle:

// helpers/vite.php
function viteAsset(string $entry): string {
    $manifest = json_decode(file_get_contents($_SERVER['DOCUMENT_ROOT'] . '/local/dist/.vite/manifest.json'), true);
    return '/local/dist/' . $manifest[$entry]['file'];
}

// In the template
\Bitrix\Main\Page\Asset::getInstance()->addJs(viteAsset('catalog/main.js'));

Dev Server and Proxy

In development mode, Vite runs an HMR server on port 5173. Bitrix runs on the standard 80/443. Proxy in vite.config.js:

server: {
    proxy: {
        '/bitrix': 'http://localhost',
        '/local': 'http://localhost',
        '/api': 'http://localhost',
    },
    https: false,
},

Now the browser opens http://localhost:5173, and Vite proxies PHP requests to Bitrix. HMR works — changes to a .vue file are applied without a page reload.

Alternative: run the Bitrix site as usual (http://project.loc) and include Vite scripts from the dev server conditionally in PHP:

$isDev = getenv('APP_ENV') === 'development';
if ($isDev) {
    echo '<script type="module" src="http://localhost:5173/@vite/client"></script>';
    echo '<script type="module" src="http://localhost:5173/catalog/main.js"></script>';
} else {
    $PAGE->AddScript(viteAsset('catalog/main.js'));
}

Code Splitting and Optimisation

Vue 3 runtime is ~30 KB gzip. If multiple Vue applications on the same page share dependencies (Vue, Pinia), Rollup should extract them into a shared chunk:

rollupOptions: {
    output: {
        manualChunks: {
            'vue-vendor': ['vue', 'pinia', 'vue-router'],
        },
    },
},

vue-vendor.js is loaded once and cached. Individual applications (catalog, cart) are small chunks of 10–50 KB each.

Webpack: When It Is Justified

Webpack remains relevant when: the project already uses Laravel Mix (which Bitrix sometimes uses as a bundler), the team has deep knowledge of Webpack configuration, or specific plugins are needed that have no Vite equivalent.

// webpack.config.js for Bitrix
const { VueLoaderPlugin } = require('vue-loader');
module.exports = {
    entry: { catalog: './local/vue-src/catalog/main.js' },
    output: { path: path.resolve(__dirname, 'local/dist'), filename: '[name].[contenthash].js' },
    module: {
        rules: [
            { test: /\.vue$/, loader: 'vue-loader' },
            { test: /\.js$/, loader: 'babel-loader', exclude: /node_modules/ },
        ],
    },
    plugins: [new VueLoaderPlugin()],
};

Webpack is slower than Vite in dev mode, but production build sizes are comparable.

Conflicts with Bitrix Scripts

Bitrix loads jQuery via CJSCore; Vue must know that jQuery is an external dependency:

// vite.config.js
build: {
    rollupOptions: {
        external: ['jquery'],
        output: { globals: { jquery: 'jQuery' } },
    },
}

If Vue components do not need jQuery — external is not required; they simply do not import it.

Typical timeline: basic Vite setup with multiple entry points, PHP integration via manifest, dev server configuration — 1–2 working days. Setting up a CI/CD pipeline with automatic build before deployment — an additional 1 day.