Skip to content

core-ds/bridge-to-native

Repository files navigation

BridgeToNative

Веб-библиотека для работы в вебвью «Нашего нативного приложения».

Особенности реализации вебвью модуля нативного приложения требуют определенных действий в т.ч. на сервере. В Библиотеке реализована необходимая логика для любых веб-серверов на базе Node.js Если в вашем веб приложении нет Node.js слоя, придётся реализовать необходимую логику самостоятельно. Разобраться, что нужно от сервера можно с помощью этого документа.

  • Как использовать Библиотеку описано здесь.
  • Про особенности навигации в вебвью окружении нативного приложение можно прочитать здесь.
  • Схематичное client-server взаимодействие внутри библиотеки описано здесь.

Сокращения, используемые во всех readme и комментариях в коде

  • BBtn (BackButton) — Кнопка «Назад» в нативной части экрана, которая может работать, как «Назад» в браузере.
  • B2N (BridgeToNative) — сокращенное название данной Библиотеки.
  • NA (Native application) — нативное приложение, для WebView которого написана эта библиотека.
  • WA (Web application) — любое веб-приложение, которое открывается внутри WebView.
  • WV (WebView) — область на экране нативного приложения, которая умеет отображать веб-контент.

Зачем это нужно

WV NA окружение отличается от браузерного, есть определенные сложности при работе внутри. Главная сложность — навигация в этом окружении.

Вот несколько особенностей:

  • Экран с WV содержит как UI-элементы NA, так и область для отрисовки веб-контента;
  • WA может влиять на поведение NA;
  • Поведение WV модуля NA в iOS и WV модуля NA в Android отличается во многих сценариях;
  • Пользователи используют разные версии NA (особенно в iOS), разные версии NA имеют свои особенности.

Данная Библиотека:

  • умеет собирать данные о NA, внутри которого она запущена;
  • учитывает вышеуказанные «особенности»;
  • предоставляет единый интрефейс для работы внутри NA разных версий, разных ОС.

Структура Библиотеки

Состоит из двух частей:

  • серверная часть:
    • необходима, чтобы распарсить запрос от NA и сохранить данные в cookie для клиентской части;
    • реализована на Node.js;
      • стараемся поддерживать совместимость с различными Node.js фреймворками и веб-серверами;
      • обработку запросов с WV на других ЯП/технологиях придётся делать руками 🙂 (см. логику src/server/prepare-native-app-details-for-client.ts)
  • клиентская часть:
    • предоставляет методы для работы WA внутри WV NA.

На клиентской стороне потребителям Библиотеки нужно использовать только экземпляр класса BridgeToNative. Это фасад, который проксирует все публичные методы Библиотеки внутренних классов.

Проксируемые публичные методы не описаны по месту их реализации, описание находится в классе BridgeToNative (чтобы не повторяться). А все приватные методы описаны (если есть необходимость) в месте их реализации.


Использование

Установите:

npm i @alfalab/bridge-to-native

Используйте функции Библиотеки на стороне сервера (на примере Express)

import { isWebviewEnv, prepareNativeAppDetailsForClient } from '@alfalab/bridge-to-native/server';

//...

app.get('/my-ssr-route', (req, res) => {
    // B2N проверит, что запрос пришёл из WV окружения.
    // Можно не использовать, если обработчик обслуживает запросы только из WV.
    const isWebview = isWebviewEnv(req);

    if (isWebview) {
        // B2N соберёт из запроса детали о NA и установит cookie для клиента.
        prepareNativeAppDetailsForClient(req, (headerKey, headerValue) => {
            res.set({
                headerKey: headerValue,
            });
        });
    }

    // Что-то делаем ещё и отправляем ответ клиенту...
});

Инициализируйте основной класс B2N в клиентском коде

import { BridgeToNative } from '@alfalab/bridge-to-native/client';

// Лучше использовать один экземпляр-синглтон.
window.b2n = new BridgeToNative();

// ...

Используйте методы Библиотеки в клиентском коде

// ...
window.b2n.setTitle('Заголовок для верхней панели NA');
// ...
window.b2n.openInBrowser('https://ya.ru');
// ...

Навигация

NA при открытии экрана c WV вместе с областью для веб-контента отображает свои UI-элементы. Один из которых — кнопка «Назад» (BBtn), которая может работать, как «Назад» в Браузере, а может закрыть VW. Чтобы синхронизировать работу BBtn с историей браузера, необходимо для навигации а рамках WA использовать ТОЛЬКО следующие методы B2N:

  • navigateClientSide — soft навигация вперед (History: pushState())
  • navigateServerSide — hard навигация вперед (Location: assign())
  • goBack — soft или hard навигация назад (History: back())
  • goBackAFewSteps — навигация на несколько шагов назад (History: go(-x)); С версии 1.4.0 подходит и для hard навигации, в т.ч. в рамках разных origin (см. описание в JSDoc метода).
  • replaceHistoryState — замена history.state и/или URL текущей записи (History: replaceState())

Каждый метод содержит JSDoc c описанием назначения и ограничений.

Пример

// Только что открылось WV, находимся на /page-1,
// Если нажать BBtn, экран с WV будет закрыт.

window.b2n.navigateClientSide('/page-2');

// Находимся на /page-2,
// Если нажать на BBtn, она сработает как «Назад» в браузере, вернув на `/page-1`.

window.b2n.navigateClientSide('/page-3');

// Находимся на /page-3,
// Если нажать на BBtn, она сработает как «Назад» в браузере, вернув на `/page-2`.

window.b2n.goBack();

// Вернулись на /page-2,
// Если нажать на BBtn, она сработает как «Назад» в браузере, вернув на `/page-1`.

window.b2n.goBack();

// Вернулись на /page-1,
// Если нажать BBtn, экран с WV будет закрыт.

Проблематика hard (server side) навигации в контексте работы WV NA

  1. Особенности WV NA заставляют WA хранить состояние синхронизации с NA. При использовании server-side навигации это состояние теряется, приходиться как-то передавать его дальше. Это на себя берёт Библиотека.

  2. Внутри NA такие переходы как правило имеют плохой UX (низкая отзывчивость). WV-браузер продолжает показывать исходную страницу пока не получит ответ на запрос целевой страницы, а NA не показывает никакой индикации. После получения ответа на HTML запрос:

    • NA в iOS и дальше не показывает никакой индикации.
    • NA в Android начинает показывать нативный спиннер с фоном (полностью перекрывает веб-контент) пока грузятся «синхронные» ресурсы из HTML.
  3. Также при переходе server-side навигацией целевое WA может быть недоступно по какой-либо причине. NA никак не обрабатывает такие ошибки.

  4. BBtn никогда не блокируется, пользователь может бесконтрольно использовать её, во время процесса навигации. До версии 1.4.0 в случае, если была использована hard навигация (navigateServerSide), этот сценарий сломает синхронизацию с NA. В версии 1.4.0 эта «особенность» учитывается, но потребители B2N должны использовать метод Библиотеки replaceHistoryState вместо прямых вызовов history.replaceState (или оберток над ним, типа history.replace из ReactRouter).

Что предлагает Библиотека

Из-за «второго и третьего пунктов» использовать server-side навигацию не рекомендуется. Переход к другому WA лучше делать через открытие нового WV (см. метод openInNewWebview). Хотя делать это тоже нужно осторожно, т.к. каждое открытое WV утилизирует ресурсы устройства.

B2N предоставляет метод navigateServerSide для server-side навигации. Но WA должно учитывать «второй пункт» и показывать пользователю какую-то индикацию перехода, блокировать кнопки (BBtn заблокировать нет возможности) и т.п. При этом «Третий пункт» не решить на стороне веба и надо иметь его ввиду.

При navigateServerSide библиотека переиспользует уже существующий query device_app_version, чтобы целевое WA могло восстановить appVersion даже если на следующем HTML-запросе не будет заголовка app-version. Исторически этот query приходит из iOS, но B2N сознательно не вводит для этого отдельный B2N-специфичный параметр и использует его как transport-поле и для Android.


Процесс релиза

Для выпуска новой версии библиотеки в npm необходимо создать GitHub Release. При этом нужно:

  1. Указать semver тег (major.minor.patch).
  2. Заполнить Release notes в формате Markdown, описав изменения в разделах: Features, Bugfixes, BREAKING CHANGES (см. пример в CHANGELOG.md). Не используйте заголовки первого уровня при описании изменений, так как они используются для основных заголовков версии.

После публикации GitHub Release автоматически запускается workflow, который:

  • Обновляет версию в package.json согласно тегу;
  • Обновляет CHANGELOG.md;
  • Создает релизный Pull Request с этими изменениями со специальным тегом release.

После мержа релизного PR запустится следующий workflow, который:

  • Опубликует версию в npm;
  • Добавит архив с актуальными ассетами в созданный релиз. Таким образом ассеты с актуальным CHANGELOG.md будут лежать в архиве release-x.y.z.zip

Бета-версии

Для выпуска beta-версии достаточно добавить в сообщение коммита строку deploy_beta. Выпущенная beta-версия будет автоматически опубликована с тегом beta. Выпущенную бета-версию можно посмотреть в разделе Actions в соответствующем workflow.

About

Утилита для удобной работы веб приложения внутри нативного приложения и коммуникации с ним.

Resources

Stars

Watchers

Forks

Contributors