For the complete documentation index, see llms.txt. This page is also available as Markdown.

Вставки HTML, CSS и JS

Пользовательские вставки позволяют подключать к пользовательской части обменника сторонние виджеты, чаты, системы аналитики, коды подтверждения, дополнительные стили и другие интеграции без изменения исходного кода и повторной сборки Frontend.

На новых серверах вставки хранятся в отдельном общем каталоге:

/var/www/iexexchanger/shared/frontend/ng-custom

Работа с файлами выполняется на сервере Frontend через SSH. Отдельного редактора пользовательских вставок в административной панели нет.

Старая схема с FastPanel, созданием public/ng-custom внутри проекта и ручным добавлением location в Nginx больше не используется. Каталог, права доступа и конфигурацию Nginx создаёт установщик iEXExchanger.

Как устроена система на новых серверах

Каталог ng-custom находится в общей директории shared, а не внутри конкретного релиза Frontend. Благодаря этому пользовательские файлы не заменяются при штатном обновлении или откате приложения.

Файлы доступны через основной домен Frontend:

https://ваш_домен/ng-custom/имя-файла

Домен Backend https://app.ваш_домен для пользовательских вставок не используется.

Установщик автоматически:

  • создаёт общий каталог ng-custom;

  • добавляет пять базовых файлов;

  • назначает безопасные права доступа;

  • подключает каталог к Nginx;

  • отключает просмотр содержимого каталога;

  • блокирует скрытые и PHP-подобные файлы;

  • добавляет заголовки, запрещающие сохранение устаревшей версии в кеше;

  • сохраняет каталог при обновлении Frontend.

Если штатное резервное копирование сервера включено, каталог входит в резервную копию общей директории /var/www/iexexchanger/shared.

Файлы пользовательских вставок

В каталоге находятся следующие базовые файлы:

Файл
Режим
Назначение

client-scripts.js

Браузерный

Произвольный JavaScript и подключение внешних скриптов после запуска Frontend

client-snippets.html

Браузерный

HTML, CSS, теги <script>, <meta>, <link> и другие готовые фрагменты

ssr-head.html

SSR

Вставка перед закрывающим тегом </head>

ssr-body-start.html

SSR

Вставка сразу после открывающего тега <body>

ssr-body-end.html

SSR

Вставка перед закрывающим тегом </body>

Допускается создавать дополнительные статические файлы, например:

Они также будут доступны через /ng-custom/.

Режимы работы

Браузерный режим и SSR работают независимо. Можно включить один режим или оба одновременно.

Режим
Переменная
Когда применяется

Браузерный

CLIENT_CUSTOM_SCRIPTS_ENABLED

После первого отображения Angular-приложения в браузере

SSR

CLIENT_CUSTOM_SSR_ENABLED

При формировании исходного HTML на сервере

Браузерный режим

Браузерный режим загружает:

Особенности режима:

  • файлы загружаются только в браузере;

  • пользовательский код не выполняется во время серверного рендеринга;

  • загрузка начинается после первого отображения Angular-приложения;

  • оба файла загружаются независимо и параллельно;

  • ошибка пользовательского файла записывается в консоль и не должна останавливать основную загрузку Frontend;

  • для работы после переходов между страницами доступен route-aware API;

  • локализованные варианты браузерных файлов автоматически не выбираются.

Не полагайтесь на порядок выполнения client-scripts.js и client-snippets.html. Если фрагменты зависят друг от друга, разместите зависимый код в одном файле или используйте событие iex:custom:ready.

SSR-режим

SSR-режим добавляет содержимое файлов непосредственно в исходный HTML-ответ.

JavaScript из SSR-файлов не выполняется процессом Node.js. Frontend только добавляет соответствующую разметку в HTML, после чего теги <script> выполняются браузером обычным способом.

SSR подходит для:

  • стилей, которые должны присутствовать уже в первом HTML;

  • кодов подтверждения сторонних сервисов;

  • элементов <noscript>;

  • тегов <meta> и <link>;

  • скриптов, которые должны находиться в определённой части документа.

SSR-вставки выполняются при полной загрузке страницы. Они не запускаются повторно при внутренних переходах Angular. Для личного кабинета и других CSR-страниц используйте браузерный режим и onPageReady().

Как выбрать режим для CSS

Разместите CSS в client-snippets.html, если стиль можно применить после первого отображения страницы.

Разместите CSS в ssr-head.html, если он должен находиться в исходном <head> и применяться как можно раньше.

Для большого объёма CSS создайте отдельный файл custom.css и подключите его через:

Включение при новой установке

До запуска новой установки режимы можно включить в /home/installer/install.yaml:

Если нужен только один режим, оставьте второе значение false.

Изменение install.yaml на уже установленном сервере само по себе не меняет работающий Frontend. На завершённой установке используются параметры из /etc/iexexchanger/frontend.env.

Включение на установленном сервере

Для работы потребуются SSH-доступ и возможность выполнять команды через sudo.

1

Проверьте каталог

Выполните:

В каталоге должны находиться пять базовых файлов.

Не создавайте новый ng-custom внутри current, releases, dist, Backend или другого каталога приложения.

2

Откройте настройки Frontend

Выполните:

Для включения обоих режимов должны использоваться значения:

Для отключения отдельного режима укажите "false".

Не изменяйте CLIENT_CUSTOM_DIR, если сервер установлен штатным установщиком iEXExchanger.

3

Перезапустите Frontend

После изменения frontend.env выполните:

4

Проверьте службу

Выполните:

Ожидаемый результат:

Если служба не запустилась, проверьте её состояние и журнал:

Перезапуск требуется после изменения переменных в frontend.env. После обычного изменения содержимого HTML, CSS или JavaScript повторная сборка и перезапуск Frontend не требуются.

Редактирование пользовательских файлов

Для редактирования используйте sudoedit:

Перед значительным изменением сохраните копию файла в защищённом каталоге вне /var/www/iexexchanger/shared/frontend/ng-custom.

Не храните резервные копии с расширениями .bak, .old или .copy внутри публичного каталога: такие файлы также могут стать доступными через сайт.

Не используйте права 777 и не меняйте владельца базовых файлов без необходимости. Установщик ожидает обычные файлы без символических ссылок и дополнительных жёстких ссылок.

Работа с JavaScript в браузерном режиме

JavaScript размещается в:

Код верхнего уровня выполняется сразу после загрузки файла. Рекомендуемая точка входа — функция window.IEX_CUSTOM_INIT.

Базовый шаблон:

Замените адрес сервиса и публичный идентификатор значениями, предоставленными поставщиком интеграции.

Параметр id предотвращает повторное добавление одного и того же <script> при переходах между страницами.

Пользовательский callback должен быть идемпотентным: повторное выполнение не должно создавать дублирующиеся кнопки, виджеты или обработчики событий.

Проверка синтаксиса JavaScript

Перед публикацией можно проверить синтаксис:

Эта команда проверяет синтаксис, но не подтверждает работу браузерного API или стороннего сервиса.

Работа с HTML и CSS в браузерном режиме

Готовые HTML-фрагменты размещаются в:

Файл может содержать:

Frontend обрабатывает верхнеуровневые элементы следующим образом:

  • <meta>, <link>, <style> и <title> перемещаются в document.head;

  • обычная HTML-разметка добавляется в body;

  • теги <script> пересоздаются и выполняются;

  • скрипты внутри файла обрабатываются последовательно;

  • пустые текстовые узлы и HTML-комментарии пропускаются;

  • тег <base> игнорируется.

Файл не проходит HTML-санитизацию. Его содержимое считается доверенным кодом владельца сервера.

Создание отдельного CSS-файла

Создайте файл:

Для нового файла скопируйте владельца и права с базового файла:

Подключите его в client-snippets.html или ssr-head.html:

Проверьте доступность:

API браузерного режима

При включённом браузерном режиме Frontend создаёт:

Текущая версия API:

API также передаётся аргументом в window.IEX_CUSTOM_INIT.

Свойство или метод
Назначение
Основные параметры

version

Версия API

Строка

readyState

Значение document.readyState в момент установки API

Без параметров

currentRoute()

Возвращает текущий адрес внутри Frontend

Без параметров

loadScript()

Загружает дополнительный JavaScript

URL и объект настроек

injectHtml()

Добавляет HTML и выполняет содержащиеся в нём скрипты

HTML и объект настроек

onReady()

Выполняет callback после готовности DOM

Функция

onRouteChange()

Подписывает callback на текущий маршрут и Angular-навигации

Функция и immediate

onPageReady()

Вызывает callback после отрисовки DOM текущей страницы

Функция и immediate

mount()

Возвращает или создаёт контейнер для интеграции

ID и объект настроек

safeRun()

Выполняет callback через защитный try/catch

Функция и подпись ошибки

Объект текущего маршрута

currentRoute(), onRouteChange() и onPageReady() используют объект:

Поле
Содержимое

url

Путь, параметры запроса и хеш

path

Только путь

search

Строка параметров запроса

hash

Хеш страницы

Пример результата:

Метод loadScript

Сигнатура:

Поддерживаемые настройки:

Параметр
Назначение

id

Предотвращает повторную загрузку скрипта с тем же ID

async

Управляет свойством script.async; по умолчанию true

defer

Управляет свойством script.defer; по умолчанию true

attributes

Добавляет data-*, integrity, crossorigin и другие атрибуты

Метод не ограничивает домены внешних скриптов. Пустые адреса и адреса с управляющими символами отклоняются.

Метод injectHtml

Сигнатура:

Параметр target принимает:

  • body;

  • head;

  • CSS-селектор существующего элемента.

Если элемент по CSS-селектору не найден, используется body.

Параметр wrapperId создаёт или повторно использует контейнер с указанным ID.

Методы onRouteChange и onPageReady

Оба метода возвращают функцию отписки:

По умолчанию immediate равен true, поэтому callback планируется сразу после регистрации. Затем callback вызывается при первоначальном route-ready событии и после Angular-навигаций.

Логика callback должна выдерживать повторные вызовы. Если подписка создаётся внутри IEX_CUSTOM_INIT и нужен только объединённый первоначальный сигнал после загрузки обоих пользовательских файлов, укажите:

Callbacks выполняются после двух кадров браузерной отрисовки, чтобы DOM личного кабинета и других CSR-страниц успел обновиться.

Метод mount

Метод создаёт постоянный контейнер для виджета:

Если элемент с таким ID уже существует, API возвращает его повторно.

Если target не найден, используется системный контейнер #iex-custom-root, а при его отсутствии — body.

Параметр clear: true очищает существующий контейнер перед повторным использованием.

События браузерного режима

Помимо API, Frontend отправляет браузерные события:

Событие

Когда отправляется

Содержимое event.detail

iex:custom:ready

После завершения попыток загрузки обоих пользовательских файлов

route

iex:route-ready

После первой загрузки и каждой Angular-навигации

reason и route

Подписка:

Для iex:route-ready поле reason содержит:

или:

Работа с SSR-вставками

SSR-файлы содержат готовые фрагменты HTML.

Вставка в head

Файл:

Содержимое добавляется перед </head>.

Подходящий формат:

Вставка в начало body

Файл:

Содержимое добавляется сразу после открывающего тега <body>.

Подходящий формат:

Вставка в конец body

Файл:

Содержимое добавляется перед </body>.

Подходящий формат:

Frontend автоматически оборачивает добавленное содержимое служебными комментариями:

Добавлять эти комментарии вручную не требуется. Они также защищают HTML от повторной вставки одного слота.

Файл, содержащий только пробелы или HTML-комментарии, считается пустым и не добавляется в страницу.

Мультиязычные SSR-вставки

Для разных языков можно создать подкаталоги внутри ng-custom:

В каждом подкаталоге можно разместить собственные версии:

Для SSR Frontend проверяет файлы в следующем порядке:

  1. Подкаталог языка текущей страницы.

  2. Подкаталог языка Frontend по умолчанию.

  3. Корень общего каталога ng-custom.

Например, для английской страницы и языка по умолчанию ru порядок будет следующим:

Используется первый существующий файл.

Если языковой файл существует, но содержит только пробелы или HTML-комментарии, слот для этого языка останется пустым. Переход к следующему файлу не выполняется. Это позволяет намеренно отключить отдельную SSR-вставку для конкретного языка.

Чтобы использовать общий вариант, удалите соответствующий языковой файл или не создавайте его.

Автоматическая локализация применяется только к SSR-файлам. Браузерный режим всегда загружает корневые client-scripts.js и client-snippets.html.

Применение изменений

После сохранения client-scripts.js или client-snippets.html обновите страницу в браузере.

После сохранения SSR-файла откройте страницу заново. Frontend проверяет время изменения файла и использует новое содержимое без пересборки и перезапуска службы.

Перезапуск iex-frontend.service требуется только после изменения:

Nginx отправляет пользовательские файлы с заголовками, запрещающими хранение устаревшей копии:

Кеширование собственных файлов стороннего сервиса при этом регулируется самим сторонним сервисом.

Проверка браузерного режима

Проверьте доступность файлов

Выполните:

Ожидается успешный HTTP-ответ и заголовки, запрещающие кеширование.

Проверьте runtime-флаг

Откройте сайт, затем инструменты разработчика и вкладку Console.

Выполните:

Ожидаемый результат при включённом браузерном режиме:

Проверьте API

Выполните:

Ожидаемый результат:

Проверьте текущий маршрут:

Проверьте загрузку файлов

Во вкладке Network найдите:

Во вкладке Console проверьте отсутствие сообщений с префиксом:

Проверка SSR-режима

Запросите исходный HTML страницы:

Для страницы с языковым префиксом используйте её фактический адрес:

Также можно открыть в браузере исходный код страницы и найти:

Маркер появляется только для непустого слота.

Безопасность

Пользовательские вставки являются доверенным кодом и не работают в изолированной среде.

JavaScript получает доступ к странице с теми же возможностями, что и основной клиентский код. Он может изменять DOM, читать доступные браузеру данные, отправлять сетевые запросы и влиять на интерфейс обменника.

Соблюдайте следующие правила:

  • добавляйте код только из доверенного источника;

  • используйте только HTTPS-адреса внешних ресурсов;

  • не вставляйте приватные ключи и секретные токены;

  • не предоставляйте доступ к файлам непроверенным пользователям;

  • проверяйте код поставщика перед публикацией;

  • используйте уникальный id для внешних скриптов;

  • не отключайте Content Security Policy полностью;

  • не используйте chmod 777;

  • не создавайте символические ссылки вместо базовых файлов;

  • не вставляйте полный HTML-документ;

  • не используйте <base>.

Если внешний ресурс блокируется Content Security Policy, разрешите только необходимый домен в соответствующей директиве:

Набор директив зависит от того, какие ресурсы загружает интеграция. Не добавляйте широкие разрешения без необходимости.

Если браузерный код не выполняется

Проверьте значения:

После изменения frontend.env перезапустите Frontend:

Проверьте runtime-флаг в браузере:

Если значение отсутствует или равно false, браузерный режим не включён в HTML текущего процесса Frontend.

Если код работает только после полной загрузки

SSR-скрипты запускаются только при полной загрузке документа.

Для повторной работы после Angular-навигаций перенесите логику в client-scripts.js и используйте:

Не используйте фиксированные задержки в несколько секунд, если достаточно onPageReady().

Если виджет появляется несколько раз

Используйте уникальный id при загрузке:

Для HTML-контейнера используйте mount():

Не создавайте новую подписку на каждом переходе без удаления предыдущей. Сохраните функцию отписки и вызовите её, когда подписка больше не нужна.

Если SSR-маркеры отсутствуют

Проверьте:

  • значение CLIENT_CUSTOM_SSR_ENABLED;

  • содержимое соответствующего SSR-файла;

  • языковой подкаталог текущей страницы;

  • наличие только комментариев или пробелов;

  • состояние службы iex-frontend.service.

После изменения только содержимого SSR-файла перезапуск не требуется.

Если используется неправильный язык

Проверьте наличие файла в каталоге текущего языка.

Помните, что существующий пустой языковой файл останавливает поиск и отключает этот слот. Чтобы использовать общий файл, не создавайте языковую версию или удалите ненужный языковой файл после сохранения резервной копии.

Если файл возвращает 403 или 404

Проверьте точный путь:

Проверьте права всех компонентов пути:

Не используйте:

  • скрытые имена, начинающиеся с точки;

  • PHP-подобные расширения;

  • символические ссылки;

  • каталог текущего релиза вместо shared/frontend/ng-custom.

Не добавляйте вручную новый блок Nginx. Конфигурация /ng-custom/ управляется установщиком и может быть восстановлена из шаблона при следующей серверной операции.

Если изменения исчезли после обновления

Штатное обновление сохраняет:

Если изменения исчезли, вероятнее всего редактировался файл внутри активного релиза, например current, releases, dist или public.

Перенесите актуальный код в общий каталог shared/frontend/ng-custom. Не редактируйте собранные файлы Frontend.

Если Frontend не запускается после изменения настроек

Проверьте службу:

Проверьте последние записи журнала:

Проверьте синтаксис и значения в:

Убедитесь, что CLIENT_CUSTOM_DIR содержит абсолютный штатный путь:

Отключение пользовательских вставок

Откройте:

Для полного отключения установите:

Перезапустите Frontend:

Отключение режима не удаляет содержимое файлов.

Откат содержимого

Для отката верните предыдущую проверенную версию соответствующего файла в:

После восстановления HTML, CSS или JavaScript перезапуск Frontend не требуется.

Проверьте:

После этого повторите проверку в браузере на первой странице, при переходе между разделами и в личном кабинете.

Последнее обновление

Это было полезно?