Разработка PWA-приложения на базе 1С-Битрикс

Наша компания занимается разработкой, поддержкой и обслуживанием решений на Битрикс и Битрикс24 любой сложности. От простых одностраничных сайтов до сложных интернет магазинов, CRM систем с интеграцией 1С и телефонии. Опыт разработчиков подтвержден сертификатами от вендора.
Предлагаемые услуги
Показано 1 из 1 услугВсе 1626 услуг
Разработка PWA-приложения на базе 1С-Битрикс
Средняя
~1-2 недели
Часто задаваемые вопросы
Наши компетенции:
Этапы разработки
Последние работы
  • image_website-b2b-advance_0.png
    Разработка сайта компании B2B ADVANCE
    1163
  • image_bitrix-bitrix-24-1c_fixper_448_0.png
    Разработка веб-сайта для компании ФИКСПЕР
    811
  • image_bitrix-bitrix-24-1c_development_of_an_online_appointment_booking_widget_for_a_medical_center_594_0.webp
    Разработка на базе Битрикс, Битрикс24, 1С для компании Development of an Online Appointment Booking Widget for a Medical Center
    563
  • image_bitrix-bitrix-24-1c_mirsanbel_458_0.webp
    Разработка на базе 1С Предприятие для компании МИРСАНБЕЛ
    743
  • image_crm_dolbimby_434_0.webp
    Разработка сайта на CRM Битрикс24 для компании DOLBIMBY
    653
  • image_crm_technotorgcomplex_453_0.webp
    Разработка на базе Битрикс24 для компании ТЕХНОТОРГКОМПЛЕКС
    976

Разработка PWA-приложения на базе 1С-Битрикс

С версии 21.0 в Битриксе появился штатный модуль pwa — генерация manifest.json, регистрация Service Worker, базовый offline-режим. На демо выглядит убедительно: сайт добавляется на рабочий стол, работает без сети, показывает пуш-уведомления. На практике — модуль покрывает 40% задач, остальное требует ручной настройки: стратегии кеширования, взаимодействие с composite, обход ограничений iOS, тюнинг Lighthouse-метрик до зелёной зоны.

Что даёт штатный модуль pwa

Модуль включается через Административный раздел → Настройки → Настройки модулей → PWA. После активации Битрикс делает три вещи:

  1. Генерирует /manifest.json с параметрами из настроек модуля — name, short_name, start_url, display, theme_color, background_color, набор иконок из icons[]
  2. Регистрирует Service Worker /sw.js через navigator.serviceWorker.register('/sw.js') в template_styles.php или через <script> в шаблоне сайта
  3. Добавляет <link rel="manifest" href="/manifest.json"> в <head>

Параметр display по умолчанию standalone — приложение открывается без адресной строки браузера. Для сайтов, где пользователю нужна навигация назад через историю браузера, ставим minimal-ui.

Иконки — модуль требует набор: 72x72, 96x96, 128x128, 144x144, 152x152, 192x192, 384x384, 512x512. Формат PNG. Если не загрузить 512x512 — Lighthouse снимает баллы за «installability». Генерируем через CFile::ResizeImageGet() из одного исходника, но проверяем качество вручную — автоматическое сжатие иногда даёт артефакты на мелких размерах.

Service Worker: стратегии кеширования

Штатный /sw.js от Битрикса использует стратегию Cache First для статических ресурсов и Network First для HTML-страниц. Этого достаточно для базового offline, но не для реального PWA-поведения.

Cache First — Service Worker ищет ответ в CacheStorage, если находит — возвращает, не обращаясь к серверу. Работает для /bitrix/js/, /bitrix/css/, /upload/. Проблема: при обновлении JS-бандла пользователь продолжает получать старую версию, пока кеш не истечёт или не обновится через skipWaiting().

Network First — сначала запрос к серверу, если сервер недоступен — fallback из кеша. Для HTML-страниц это правильная стратегия, но есть нюанс с модулем composite. Композитный сайт отдаёт статический HTML с динамическими вставками через AJAX. Service Worker перехватывает уже готовый композитный HTML — и кеширует его. Если динамические вставки зависят от авторизации, в кеш попадает обезличенная версия, а после восстановления сети пользователь видит чужие данные. Решение — исключаем из кеширования URL с параметром sessid и запросы к bitrix/services/main/ajax.php.

Stale While Revalidate — третья стратегия, которую штатный модуль не использует, но мы добавляем для API-ответов. Отдаём из кеша мгновенно, параллельно обновляем кеш запросом к серверу. Идеально для каталога, где данные меняются раз в час, а пользователь не должен ждать.

Кастомную логику кеширования пишем в /local/templates/main/sw-custom.js и подключаем через importScripts() в основном Service Worker. Не модифицируем /sw.js напрямую — он перегенерируется модулем.

Взаимодействие с модулем composite

Модуль composite и PWA решают одну задачу — ускорить первый рендер. Но работают по-разному и могут конфликтовать.

composite генерирует статический HTML и сохраняет в файловую систему (/bitrix/html_pages/). Nginx отдаёт файл напрямую, минуя PHP. Время ответа — 5-15ms. Динамические зоны (<div id="bx-composite-...">) подгружаются отдельным AJAX-запросом после загрузки страницы.

Когда поверх composite включается Service Worker с Cache First для HTML — Nginx даже не получает запрос, ответ идёт из CacheStorage браузера. Это быстрее, но есть ловушка: если composite обновил HTML (товар закончился, поменялась цена), Service Worker продолжает отдавать старую версию.

Решение — версионирование кеша. В manifest.json добавляем кастомное поле sw_version, при каждом деплое инкрементируем. Service Worker при активации сравнивает версию и очищает старый кеш:

const CACHE_VERSION = 'v1.4';
self.addEventListener('activate', event => {
  event.waitUntil(
    caches.keys().then(keys =>
      Promise.all(keys.filter(k => k !== CACHE_VERSION).map(k => caches.delete(k)))
    )
  );
});

Push-уведомления через модуль pull

Битриксовский модуль pull (Push and Pull) обеспечивает real-time взаимодействие: чат, уведомления, обновления данных. Для PWA он же используется как транспорт пуш-уведомлений.

Архитектура: клиент подписывается через PushSubscription API → отправляет endpoint, keys.p256dh, keys.auth на сервер → сервер сохраняет подписку в b_pull_push → при наступлении события отправляет payload через \Bitrix\Pull\Push::send().

Настройка:

  1. Генерируем VAPID-ключи через web-push библиотеку или через openssl: openssl ecparam -genkey -name prime256v1 -out private.pem
  2. Публичный ключ прописываем в настройках модуля pull → «Push-уведомления» → «VAPID Public Key»
  3. В Service Worker обрабатываем событие push:
self.addEventListener('push', event => {
  const data = event.data.json();
  event.waitUntil(
    self.registration.showNotification(data.title, {
      body: data.body,
      icon: '/local/templates/main/img/icon-192.png',
      data: { url: data.url }
    })
  );
});

Ограничение iOS: Safari на iOS поддерживает Web Push только с версии 16.4, и только для сайтов, добавленных на домашний экран. PushManager.subscribe() в обычной вкладке Safari вернёт ошибку. Проверяем поддержку:

if ('PushManager' in window && 'Notification' in window) {
  // подписка возможна
}

Lighthouse PWA Audit: что проверяется

Lighthouse оценивает PWA по чек-листу. Вот что требует внимания на Битриксе:

  • Installable — корректный manifest.json, Service Worker с обработчиком fetch, иконка 512x512, start_url отвечает 200 в offline. Штатный модуль закрывает, если не забыть иконку
  • Optimized — HTTPS обязательно, <meta name="theme-color"> совпадает с theme_color в манифесте, редирект с HTTP на HTTPS. В Битриксе HTTPS настраивается через НастройкиГлавный модуль → «Работать в режиме HTTPS»
  • Offline — при отключении сети пользователь видит кастомную страницу, а не стандартный Chrome Dinosaur. Создаём /offline.html и кешируем при установке Service Worker
self.addEventListener('install', event => {
  event.waitUntil(
    caches.open(CACHE_VERSION).then(cache =>
      cache.addAll(['/', '/offline.html', '/local/templates/main/css/style.min.css'])
    )
  );
});
  • Redirectsstart_url не должен возвращать 3xx. Если Битрикс настроен на редирект //ru/ для мультиязычного сайта, то start_url в манифесте указываем /ru/, а не /

Событие beforeinstallprompt

Браузер показывает баннер установки PWA автоматически, но момент выбирает сам — обычно через 30 секунд после загрузки. Мы перехватываем событие и показываем кастомную кнопку:

let deferredPrompt;
window.addEventListener('beforeinstallprompt', e => {
  e.preventDefault();
  deferredPrompt = e;
  document.getElementById('install-btn').style.display = 'block';
});

document.getElementById('install-btn').addEventListener('click', () => {
  deferredPrompt.prompt();
});

На iOS событие beforeinstallprompt не поддерживается. Для Safari показываем инструкцию: «Нажмите Поделиться → Добавить на экран «Домой»». Определяем iOS через navigator.userAgent — не идеально, но альтернатив нет.

PWA vs нативное приложение на Битриксе

Критерий PWA Нативное (iOS/Android)
Установка Из браузера, без App Store App Store / Google Play
Обновление Автоматическое через Service Worker Через магазин, требует подтверждения
Доступ к устройству Камера, геолокация, уведомления Полный доступ к API устройства
Offline Кешированный контент Полноценная offline-логика
Размер 0 MB (кеш браузера) 20-100+ MB
Стоимость разработки 1-2 недели поверх сайта 2-4 месяца отдельный проект

Для каталога, корпоративного сайта, новостного портала — PWA достаточно. Для приложения с тяжёлой офлайн-логикой, Bluetooth, NFC — нужен нативный клиент.

Этапы работ

  1. Аудит текущего сайта (2-3 дня) — проверка совместимости шаблона с PWA, анализ Lighthouse, оценка взаимодействия с composite
  2. Настройка модуля и Service Worker (3-5 дней) — конфигурация manifest.json, стратегии кеширования, offline-страница, push-подписка
  3. Тестирование (2-3 дня) — проверка на Android (Chrome, Samsung Internet), iOS (Safari), десктоп (Chrome, Edge). Lighthouse audit на каждом этапе
  4. Запуск и мониторинг (1-2 дня) — деплой, проверка метрик, настройка алертов на ошибки Service Worker
Масштаб Сроки
PWA для существующего сайта с composite 1-2 недели
PWA + push-уведомления + offline-каталог 2-3 недели
PWA с кастомным App Shell и сложной offline-логикой 3-5 недель

Ограничения, о которых важно знать

  • iOS Safari не поддерживает Background Sync, Badge API, полноценные push без добавления на Home Screen
  • Обновление Service Worker — даже при skipWaiting() пользователь получит новую версию только при следующем открытии. Нет способа заставить обновление мгновенно
  • Размер кеша — браузеры ограничивают CacheStorage. Chrome выделяет до 80% свободного места на диске, Safari — 50MB на origin. Кешировать весь каталог на 10К товаров не получится — только критические ресурсы
  • Модуль composite при включённом CDN может отдавать HTML с абсолютными URL CDN-домена — Service Worker не перехватит запросы к другому origin. Проверяем через scope в register()