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>

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

Онлайн-курс Recruiter від Mate academy.
Обирайте курс Recruiter з гнучким графіком та ставайте спеціалістом у новій сфері! Допоможемо опанувати усі необхідні навички та стати профі!
Отримати знижку на курс

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

Но не все так хорошо, как кажется. Из-за того, что 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-скрипте и распарсить уже известным нам методом, предложенным в видео.

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

Онлайн курс з промт інжинірингу та ефективної роботи з ШІ від Powercode academy.
Курс-інтенсив для отримання навичок роботи з ChatGPT та іншими інструментами ШІ для професійних та особистих задач, котрі допоможуть як новачку, так і професіоналу.
Записатися на курс
<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-событие.

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

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

Курс Full-stack developer від Mate academy.
Опануйте нову професію завдяки курсу Full-stack developer! Ви отримаєте необхідні навички та допомогу у працевлаштуванні! .
Отримати знижку на курс

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

Онлайн-курс DevOps engineer від Mate academy.
DevOps інженери відповідають за автоматизацію процесів розробки, тестування та випуску продукту. Завдяки цьому курсу ви швидко станете високооплачуваним спеціалістом.
Отримати знижку на курс

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

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

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

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