ru:https://highload.today/blogs/konfiguratsiya-iz-bekenda-na-frontend/ ua:https://highload.today/uk/blogs/konfiguratsiya-iz-bekenda-na-frontend/
logo
Решения      03/11/2021

Как передать конфигурацию из бэкенда на фронтенд: почему мой подход сработает лучше остальных

Николай Коваленко BLOG

Backend Developer в Ronis Business Tools

Часто для реализации какого-либо конфигурируемого функционала на фронтенде необходимо передать параметры конфигурации из бэкенда на фронтенд. Для этого используется множество неоптимальных подходов.

Простой подход

Как это обычно делают? Подключают вот такой вот js-скрипт в head-блок:

<html>
  <head>
    <!-- блокировка рендеринга страницы на время выполнения скрипта -->
    <script>
      const configuration = <?php echo json_encode($configuration) ?>;
    </script>

    <!-- блокировка рендеринга страницы на время выполнения скрипта -->
    <script>
      //какое-то использование конфигурации в head
      window.console.log(configuration);
    </script>

    <!-- блокировка рендеринга страницы на время загрузки и выполнения скрипта -->
    <script src="/app-configuration-initialization.js"></script>
  <body>
    <!-- блокировка рендеринга страницы на время выполнения скрипта -->
    <script>
      //какое-то использование конфигурации в body
      window.console.log(configuration);
   </script>
  </body>
</html>

Дальше глобальную константу configuration можно будет использовать как в подключаемых js-файлах, так и в js-коде в теле самой страницы, на которой мы подключили этот блок.

Казалось бы, все хорошо. Удобно конфигурировать и удобно использовать. Но есть в таком подходе ряд проблем с производительностью.

Браузер выполняет отрисовку страницы и скрипты в одном потоке. То есть встретив в теле страницы js-код, браузер переключается на его выполнение и только после этого продолжает отрисовывать страницу. Этот эффект легко заметить на медленных устройствах — контент отрисовывается частями от скрипта к скрипту.

Часто используемый подход

Что же можно улучшить в этой ситуации? Итак:

  • во-первых, подключить внешний js-скрипт без блокировки рендеринга страницы;
  • во-вторых, опустить конфигурацию и весь js-код, использующий ее, как можно ниже.

Давайте посмотрим, как это будет выглядеть:

<html>
  <head>
    <!-- загрузка скрипта теперь не блокирует рендеринг страницы -->
    <!-- скрипт будет выполнен после инициализации всей страницы -->
    <!-- не страница ждет скрипт, а скрипт страницу -->
    <script defer src="/app-configuration-initialization.js"></script>
  <body>
    <!-- блокировка рендеринга страницы на время выполнения скрипта --> 
    <script> 
      const configuration = <?php echo json_encode($configuration) ?>;
    </script> 

    <!-- блокировка рендеринга страницы на время выполнения скрипта --> 
    <script> 
      //какое-то использование конфигурации в head 
      window.console.log(configuration); 
    </script>
    <!-- блокировка рендеринга страницы на время выполнения скрипта -->
    <script>
      //какое-то использование конфигурации в body
      window.console.log(configuration);
   </script>
  </body>
</html>

Казалось бы, все стало идеально. Рендеринг страницы ничего не блокирует. Она полностью отрисовывается, потом происходит инициализация конфигурации и выполняются все скрипты, использующие ее.

Курс QA Manual (Тестування ПЗ мануальне).
Навчіться знаходити помилки та контролювати якість сайтів та додатків.
Записатися на курс

Каждому свое место

Но не все так хорошо, как кажется. Из-за того, что js-код присутствует в коде страницы, не происходит событие onLoad, до которого желательно никакие скрипты не выполнять. Js-код нужно писать в js-файлах и подключать как внешний ресурс.

Итак, выносим весь js-код, который можем, во внешние скрипты:

<html>
  <head>
    <!-- загрузка скрипта теперь не блокирует рендеринг страницы -->
    <!-- скрипт будет выполнен после инициализации всей страницы -->
    <!-- не страница ждет скрипт, а скрипт страницу -->
    <!-- в этом же скрипте теперь находится весь код использующий конфигурацию -->
    <script defer src="/app-configuration-initialization.js"></script>
  <body>
    <!-- блокировка рендеринга страницы на время выполнения скрипта --> 
    <script> 
      const configuration = <?php echo json_encode($configuration) ?>;
    </script> 
  </body>
</html>

Стало намного лучше, js-код инициализации конфигурации все еще блокирует окончание загрузки страницы.

Отложить на потом не так уж и плохо

Как оказалось, использовать JSON-объект для инициализации конфигурации очень дорого и лучше использовать для этого JSON-строку, которую можно будет распарсить при инициализации нашего внешнего js-скрипта, используя нативный метод JSON.parse().

Подробнее и с примерами можно посмотреть в видео:

Совет от Google, конечно, интересный и хороший, но всегда же можно сделать лучше.

Есть у тега скрипт — возможность задать его тип. И есть такой тип как application/JSON. Его особенность в том, что браузер не парсит его содержимое во время рендеринга страницы и попросту пропускает такие теги, как вроде бы их и нет вовсе. Но при этом мы можем получить содержимое этих тегов в виде текста в нашем js-скрипте и распарсить уже известным нам методом, предложенным в видео.

В итоге у нас получается вот такой код:

<html>
  <head>
    <!-- загрузка скрипта теперь не блокирует рендеринг страницы -->
    <!-- скрипт будет выполнен после инициализации всей страницы -->
    <!-- не страница ждет скрипт, а скрипт страницу -->
    <!-- в этом же скрипте теперь находится весь код использующий конфигурацию -->
    <!-- в этом же скрипте теперь происходит инициализация конфигурации-->
    <script defer src="/app-configuration-initialization.js"></script>
  <body>
    <!-- скрипт не блокирует рендеринг страницы и не выполняется --> 
    <script type="application/json" id="app-configuration-json"> 
      <?php echo json_encode($configuration) ?>;
    </script> 
  </body>
</html>

Получаем страницу, на которой отсутствует js-код, блокирующий отрисовку и полную загрузку страницы. То, чего нужно было добиться. При этом весь js-код, в том числе и инициализацию конфигурации, мы можем написать во внешнем js-скрипте, где ему и место.

Итоги

Используя описанный подход, мы экономим трафик (внешние скрипты кешируются, а код страницы стал на много меньше), не блокируем рендеринг страницы, не блокируем onLoad-событие, экономим ресурсы процессора, так как используем JSON.parse вместо JSON-объекта конфигурации, улучшаем организационную структуру и читабельность кода.

Повторим принципы, которые были реализованы этим подходом:

  • внешние ресурсы нужно подключать асинхронно, чтобы не блокировать рендеринг страницы;
  • использовать js-скрипты в теле страницы нельзя, чтобы не блокировать рендеринг страницы;
  • передавать конфигурацию лучше всего через script-тег с типом application/JSON и парсить ее при инициализации с помощью JSON.parse, чтобы не блокировать рендеринг страницы и onLoad-событие.

Как по мне, не так уж и сложно реализовать правильное взаимодействие бэкенда и фронтенда, если понимать, какой подход для этого правильно использовать.

Это текст из личного блога, опубликованный с разрешения автора.

If you have found a spelling error, please, notify us by selecting that text and pressing Ctrl+Enter.

Онлайн курс з промт інжинірингу та ефективної роботи з ШІ.
Курс-інтенсив для отримання навичок роботи з ChatGPT та іншими інструментами ШІ для професійних та особистих задач, котрі допоможуть як новачку, так і професіоналу.
Записатися на курс

Этот материал – не редакционный, это – личное мнение его автора. Редакция может не разделять это мнение.

Топ-5 самых популярных блогеров февраля

Всего просмотровВсего просмотров
229
#1
Всего просмотровВсего просмотров
229
Всего просмотровВсего просмотров
209
#2
Всего просмотровВсего просмотров
209
QA в CodeGeeks Solutions
Всего просмотровВсего просмотров
156
#3
Всего просмотровВсего просмотров
156
Senior Project Manager at Nemesis
Всего просмотровВсего просмотров
99
#4
Всего просмотровВсего просмотров
99
Software Architect at Devlify
Всего просмотровВсего просмотров
95
#5
Всего просмотровВсего просмотров
95
Рейтинг блогеров

Ваша жалоба отправлена модератору

Сообщить об опечатке

Текст, который будет отправлен нашим редакторам: