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

На данный момент уже существуют привычные инструменты, позволяющие разным членам команды, таким как разработчики, дизайнеры и контент-менеджеры, эффективно взаимодействовать. Например, Tilda, Wordpress и множество других решений предоставляют удобные средства для работы с различными аспектами проекта. Однако возникает сложность, когда необходимо интегрировать результаты работы этих инструментов внутрь React приложения. Идеальным вариантом было бы обеспечить взаимодействие нашего приложения с контентом и возможность перехвата событий для оптимальной интеграции и гибкости.

В статье я продемонстрирую, как решить три задачи, связанные с интеграциями в React приложении:

  1. Изменять контент страницы на React без необходимости привлечения разработчика;

  2. Расширять функционал React приложения с помощью сторонних сервисов;

  3. Создавать страницы с минимальными затратами на разработку.

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

Демо | Код

Условия

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

Обычно, от сторонних решений мы ожидаем следующего:

  1. Легкость освоения: инструмент должен быть понятен и прост в освоении для всех сторон — как его внедрить и поддерживать, как управлять визуальной частью и контентом;

  2. Гибкость: хотя невозможно создать универсальное решение для всех случаев, инструмент должен выполнять свою функцию и, в идеале, предоставлять возможности для расширения функционала;

  3. Уровень взаимодействия: мы хотим предоставить пользователям насыщенные интерактивом страницы. Возможно ли динамическое отображение различных элементов в зависимости от состояния React приложения, таких как авторизация, и вызов функций из основного приложения?

  4. Легкость интеграции: насколько прост и быстр процесс первого и последующих деплоев. Можно ли автоматизировать этот процесс?

  5. Очевидность интеграции: некоторые инструменты предназначены для интеграции, в то время как другие — нет. Сколько усилий потребуется для отображения и взаимодействия с интегрированным контентом?

На примерах мы затронем следующие вопросы:

  • Как отображать результаты работы инструмента внутри нашего React приложения в специальном контейнере?

  • Как подписываться на события из React?

  • Какие возможности есть для Server Side Rendering?

Стоит отметить, что я приведу примеры решений на конкретных продуктах, таких как Tilda, Hubspot, Typeform, Contentful, Builder.io, но существуют их аналоги, работающие похожим образом. Это позволит нам наглядно рассмотреть различные подходы к интеграции и их применение в практике.

Задача: изменение контента

Страница с интеграцией Contentful
Страница с интеграцией Contentful

Если нашей целью является лишь вынос управления данными в админку, а все остальные компоненты приложения хотим “делать по-старинке” (путем написания кода и создания дизайна в редакторе), то оптимальным решением может быть использование Headless CMS. Такой подход позволяет хранить данные в SaaS решениях, получать их через SDK или напрямую и затем отрисовывать их на клиентской стороне с помощью собственных усилий.

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

В парадигме Headless CMS мы сначала настраиваем модель данных. Например, у нас может быть модель "Статья", которая имеет поля "Заголовок" и "Текст статьи". Этот этап работы может выполнять разработчик. Затем контент-менеджеры могут создавать конкретные экземпляры сущностей на основе этой модели, такие как "Статья 1", "Статья 2" и так далее.

Админка Contentful, где мы создаем новую статью
Админка Contentful, где мы создаем новую статью

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

Интеграция

В случае с Contentful, мы можем получать данные через стандартное Web API с помощью функции fetch. После добавления ключей доступа, необходимо выполнить запрос к Contentful API и сохранить полученные данные локально для дальнейшего использования:

const [page, setPage] = useState(null);

useEffect(() => {
  window
    .fetch(
      `https://graphql.contentful.com/content/v1/spaces/${process.env.REACT_APP_CONTENTFUL_SPACE}/`,
      {
        method: "POST",
        headers: {
          "Content-Type": "application/json",
          // Authenticate the request
          Authorization: `Bearer ${process.env.REACT_APP_CONTENTFUL_API_KEY}`,
        },
        // send the GraphQL query
        body: JSON.stringify({ query }),
      }
    )
    .then((response) => response.json())
    .then(({ data, errors }) => {
      if (errors) {
        console.error(errors);
      }

      // rerender the entire component with new data
      setPage(data.blogPostCollection.items[0]);
    });
}, []);

После того, как мы получили данные из Contentful и сохранили их локально, дальнейшая работа с ними становится привычной и удобной в React компонентах. Мы можем использовать данные в компонентах так же, как и с любыми другими данными, и отрисовывать их на странице с помощью JSX:

return (
  <div className={"bg-white rounded-2xl p-6"}>
    <h1 className={"text-6xl text-gray-900"}>{page.title}</h1>
    {page.body.json.content.map((item) => (
      <p className={"text-2xl m-5 p-2 text-gray-800"}>
        {item.content[0].value}
      </p>
    ))}
  </div>
);

Взаимодействие с кнопками и обработка событий в React приложении с использованием данных из Contentful не отличается от привычного паттерна React. Мы можем легко добавить кнопку и передать обработчик onClick в компоненте, чтобы реагировать на действия пользователя.

Server Side Rendering

Тут все хорошо. На этапе рендера контента на сервере мы можем выполнять запросы к Contentful и отправлять клиенту уже готовые данные. В частности, если мы используем Next.js, то можем получать данные на уровне функций getServerSideProps (для Server Side Rendering) или getStaticProps (для Static Site Generation). Это позволяет нам предоставлять пользователю быстрый и оптимизированный контент с учетом данных, полученных из Contentful.

Deploy

В этом аспекте также все идет гладко. Данные загружаются каждый раз при запросе, что позволяет избежать необходимости редеплоя приложения. Единственное, если вы используете подход с Static Site Generation, вам потребуется использовать вебхуки для наблюдения за изменениями контента. С помощью вебхуков вы будете автоматически получать уведомления о внесенных изменениях в Contentful, что позволит поддерживать актуальность контента на вашем сайте без необходимости ручного вмешательства.

Итоги

Плюсы:

  • Контент-менеджеры могут обновлять контент на страницах без необходимости привлекать разработчиков, что значительно экономит время команды;

  • Изменения происходят в реальном времени. Это особенно критично, если деплой приложения занимает значительное время, так как позволяет мгновенно обновлять контент без перезагрузки всего приложения;

  • Возможность решать задачи, связанные с meta-тегами для страницы, такие как заголовок, описание, ключевые слова и другие метаданные.

Минусы:

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

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

Здесь можно прочитать подробнее про интеграцию React и Contentful.

В заключение, подход с использованием Headless CMS, таких как Contentful, обеспечивает эффективное управление контентом, экономит время разработчиков и позволяет быстро обновлять контент на сайте. Однако, необходимо учитывать некоторые недостатки, такие как управление множеством полей и верстка, которые могут потребовать дополнительных усилий и внимания при использовании этого подхода.
Пример | Код

Задача: расширение функционала

Страница с интеграцией Typeform
Страница с интеграцией Typeform

Если у нас есть сервис, который можно отобразить внутри iframe, и у него не установлены заголовки безопасности типа x-frame-options: SAMEORIGIN или Content-Security-Policy: frame-ancestors none, то мы можем внедрить контент этого сервиса на свой сайт, отображая его внутри "окошка" iframe. Некоторые сервисы, такие как Typeform, предлагают интеграцию через iframe и предоставляют SDK для удобной работы с ними. Однако, для веб-сайтов, где отсутствует готовое SDK, если мы хотим добавить интерактивность и взаимодействие с родительским приложением, необходимо использовать механизм postMessage.

Интеграция

Рассмотрим ситуацию, когда у нас уже имеется SDK для интеграции в наше React приложение другого веб-ресурса. На примере Typeform, предоставляющего SDK для удобной интеграции, мы рассмотрим этот подход.

Возможности отображения Typeform на сайте разнообразны, такие как слайдер, всплывающее окно и многое другое. Главное, что нам потребуется сделать - это установить пакет @typeform/embed-react и добавить соответствующий виджет на страницу:

<Widget
	id="iUesUyX7"
	style={{ width: "100%" }}
	className="my-form"
	onQuestionChanged={() => {
		alert("onQuestionChanged");
	}}
/>

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

Если нам необходимо реагировать на события, происходящие в Typeform, мы можем передать обработчики событий onSubmit и onReady в Widget, как обычно мы это делаем для React компонентов. Однако, следует отметить, что при работе с SDK Typeform есть некоторые ограничения, и мы не можем добавить собственные компоненты напрямую в форму.

Server Side Rendering

У нас возникают ограничения с использованием SSR, что приводит к невозможности индексации контента, отображенного через iframe. Это ограничение распространяется на любое решение, использующее данную технологию.

Обратите внимание, что отсутствие поддержки Server Side Rendering может повлиять на SEO вашего сайта, поскольку контент, загружаемый через iframe, недоступен для поисковых роботов и поисковых систем.

Deploy

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

Итоги

Плюсы:

  • Если продукт поддерживает интеграцию, то работа через iframe позволит решить бизнес-задачу буквально за несколько строчек кода;

  • Изменения содержимого страницы автоматически появляются в iframe.

Минусы:

  • Не работает SSR;

  • Не все решения предоставляют SDK, что заставляет писать код-обертку. Это может добавить новые головные боли и увеличить затраты времени.

Пример | Код

Задача: создание страниц

1 способ: Iframe

Страница с интеграцией Hubspot
Страница с интеграцией Hubspot

Если мы хотим отобразить сайт внутри iframe и одновременно взаимодействовать с нашим React приложением, то нам придется использовать postMessage. Важно отметить, что для этого необходимо иметь возможность добавить собственный HTML на страницу, желательно в <head>.

Механизм postMessage позволяет установить безопасное взаимодействие между родительским и встроенным в iframe приложением. С помощью postMessage мы можем отправлять сообщения и передавать данные между родительским и встроенным окном, даже если они находятся на разных доменах.

Интеграция

Мы добавим код обработки запросов от родительского приложения, а также код для отправки событий со страницы Hubspot. Поскольку Hubspot не предоставляет официального SDK для интеграции, нам приходится использовать альтернативный подход. Хотя данный способ не является официальным, он представляет собой один из доступных вариантов для взаимодействия с Hubspot через iframe.

Со стороны React приложения мы добавим ссылку на Hubspot в iframe и передадим frameRef, через который будем взаимодействовать с сервисом:

<iframe
  title={"hubspot"}
  src={HUBSPOT_URL}
  className={"w-full h-full rounded-2xl"}
  ref={frameRef}
/>

В следующем примере кода мы реализовали обработку ссылок и отдельных кнопок в Hubspot, которые мы определили в hubspotConfig. Это позволяет перехватывать и обрабатывать события со стороны сервиса. Кроме того, мы можем добавить конфигурацию для управления поведением страницы Hubspot, такую как включение или отключение определенного функционала:

const hubspotConfig = useMemo(
  () => ({
    handlers: [
      {
        type: "click-button",
        name: CTA_BUTTON_NAME,
        selector: "a[href='#custom']",
      },
    ],
  }),
  []
);

Затем мы подпишемся в useEffect на событие message из iframe:

useEffect(() => {
	const handler = (event) => {
    if (!event.origin.includes("hubspot") || !event.data.type) { // #1
			return;
    }

		switch (event.data.type) {
        case "click-button": { // #2
          if (
            event.data.payload.buttonName === "link" &&
            event.data.payload.href
          ) {
            window.location.href = event.data.payload.href;
            break;
          }

          alert(`Button: ${event.data.payload.buttonName}`);
          break;
        }
        case "load": {
          if (hubspotConfig && frameRef.current?.contentWindow) {
            frameRef.current.contentWindow.postMessage(
              createAction("set-config", { config: hubspotConfig }), // #3
              "*"
            );
          }
          break;
        }
        default: {
          console.log("There is not event type");
        }
      }
  };

	window.addEventListener("message", handler, false);

	return () => {
	  window.removeEventListener("message", handler);
	};
}, [...])

Из интересного:

  1. Необходимо фильтровать события, проверяя поле origin, используя условие event.origin.includes("hubspot"). Это важно, так как событие message может приходить из различных iframe и workers, и нам нужно обрабатывать только те, которые исходят от Hubspot;

  2. Когда мы получаем действие с типом click-button, сформированное на стороне Hubspot, мы обрабатываем клик в React. Таким образом, мы можем реагировать на действия, происходящие внутри iframe, и синхронизировать их с React приложением;

  3. Мы отправляем действие set-config только после загрузки iframe (тип action load - подробности ниже). Это позволяет нам сообщить Hubspot, какие кнопки мы хотим дополнительно обрабатывать.

В админке Hubspot для страницы мы добавляем в head следующий скрипт:

(function () {
  const createAction = (type, payload) => {
    return {
      type,
      payload,
    };
  };
  const sendMessage = (action) => {
    window.parent.postMessage(action, "*");
  };

  window.addEventListener("DOMContentLoaded", () => { // #1
    window.addEventListener( // #2
      "message",
      (event) => {
        if (event.data.type === "set-config") { // #4
          const config = event.data.payload.config;

          config.handlers?.forEach((handler) => {
            const element = document.querySelector(handler.selector);

            switch (handler.type) {
              case "click-button": {
                element?.addEventListener("click", (e) => {
                  e.preventDefault();

                  sendMessage(
                    createAction("click-button", {
                      buttonName: handler.name,
                    })
                  );
                });
                break;
              }
              default: {
                // eslint-disable-next-line no-console
                console.log("There is not the event: " + handler.type);
              }
            }
          });

          const links = document.querySelectorAll("a");

          links.forEach((link) => {
            link.onclick = "event.preventDefault()";

            link.addEventListener("click", (e) => {
              e.preventDefault();

              sendMessage(
                createAction("click-button", {
                  buttonName: "link",
                  href: link.href,
                })
              );
            });
          });
        }
      },
      false
    );

    sendMessage(
      createAction("load", { // #3
        title: document.title,
        description:
          document.querySelector('meta[name="description"]')?.content || "",
      })
    );
  });
})();  

Порядок действий:

  1. iframe загружается, и событие DOMContentLoaded срабатывает;

  2. Мы подписываемся на событие message в родительском приложении;

  3. Отправляем action с типом load для сообщения React приложению о готовности этого скрипта к приему config. Здесь стоит отметить, что мы можем передать метаданные страницы, чтобы добавить их на уровне React приложения в раздел <head> для SEO;

  4. При получении set-config мы проходим по всем ссылкам и кнопкам, указанным в config, и добавляем обработчики click. Теперь при нажатии на элемент мы отправляем родительскому приложению информацию об этом событии.

Server Side Rendering

Из-за использования iframe у нас возникают проблемы с SSR, и контент не может быть проиндексирован поисковыми системами.

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

Это ограничение может негативно сказаться на SEO и влиять на индексацию контента, что делает использование iframe неподходящим при проектировании приложений с точки зрения доступности и поисковой оптимизации.

Deploy

Подобно примеру с Typeform, в данном случае также невозможно предсказать, что может быть загружено внутри iframe, так как содержимое может меняться. Контент в iframe будет всегда актуальным, и мы должны взаимодействовать с ним на основе информации, полученной через postMessage и общий config.

Однако, важно отметить, что необходимо своевременно обновлять "контракт" между родительским React приложением и iframe. Если внутри iframe происходят изменения, которые могут повлиять на обмен сообщениями или использование общего config, необходимо обеспечить синхронизацию и соответствующие обновления в обоих приложениях. Это позволит гарантировать правильное функционирование интеграции и сохранение актуальной информации.

Итоги

Плюсы:

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

  • Не требуется привлекать разработчика для изменения содержимого страницы.

Минусы:

  • Отсутствие поддержки SSR, что может негативно сказаться на SEO;

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

Подход с использованием iframe и postMessage обладает определенными преимуществами и ограничениями, и выбор данного подхода зависит от требований проекта и опыта разработчиков, которые будут работать с ним.

Пример | Код

2 способ: Экспорт HTML/CSS/JS

Страница с интеграцией Tilda
Страница с интеграцией Tilda

Иногда возникает ситуация, когда у нас имеется готовая верстка, экспортированная с другого сайта, и мы желаем ее интегрировать в наше React приложение. Однако, в данном случае использование iframe или прокси для взаимодействия со сторонним сервисом не подходит.

Когда разработчики запрещают встраивать их сайт в iframe
Когда разработчики запрещают встраивать их сайт в iframe

Если наш сайт имеет в HTTP-заголовках x-frame-options: SAMEORIGIN|DENY или Content-Security-Policy: frame-ancestors none, то нам будет невозможно отобразить его внутри iframe. В таком случае, придется решить задачу иначе - путем копирования разметки, включая все стили и скрипты, и затем попытаться вставить ее в наше React приложение.

HTTP-заголовки, которые мешают нам интегрироваться
HTTP-заголовки, которые мешают нам интегрироваться

Для демонстрации данного способа интеграции мы воспользуемся платформой Tilda. Этот сервис предоставляет возможность экспорта файлов, которые затем можно разместить на собственном хостинге. Важно отметить, что официально запрещено изменять контент, который мы экспортировали, но в данном примере мы модифицируем его исключительно в образовательных целях.

Интеграция

Tilda позволяет экспортировать файлы в настройках страницы
Tilda позволяет экспортировать файлы в настройках страницы

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

Файловая структура при интеграции с Tilda
Файловая структура при интеграции с Tilda

В данном примере Tilda содержит значительное количество скриптов, что может усложнить задачу интеграции, особенно при работе с изображениями. Проблема возникает из-за использования "магических" вызовов функций, отвечающих за lazy loading изображений. К сожалению, такой подход не совместим с React routing, так как они предполагают запуск при инициализации страницы, а не при динамическом переключении урлов. Эта проблема решается небольшим изменением скриптов.

Так же стоит позаботится о смене всех урлов для статики(картинки, скрипты, стили) с домена Tilda на свой собственный. Добавить ссылки в index.html на assets(js, css). js/lazyload-1.3.min.js превращается в %PUBLIC_URL%/tilda/js/lazyload-1.3.min.js.

Tilda использует множество скриптов для работы с events и оптимизации загрузки сайта
Tilda использует множество скриптов для работы с events и оптимизации загрузки сайта

В коде нам необходимо поместить наш html в строковую переменную:

export const TILDA_HTML = `
	<div
	  id="allrecords"
	  data-tilda-export="yes"
	  class="t-records"
	  data-hook="blocks-collection-content-node"
	  data-tilda-project-id="4457918"
	  data-tilda-page-id="33161614"
	  data-tilda-formskey="599a4bf5b358fcc8f5ce82f8419bbb21"
	  data-tilda-lazy="yes"
	>
	...
	</div>
`

И вставить его в React компоненте, используя dangerouslySetInnerHTML:

return (
  <div
    dangerouslySetInnerHTML={{ __html: TILDA_HTML }}
    className={"w-full bg-white rounded-2xl overflow-hidden"}
  />
);

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

Для добавления обработчиков событий, мы можем использовать стандартное DOM API:

useEffect(() => {
  const tildaButton = document.getElementById("tilda-button");

  const onClick = () => {
    alert("onClick tilda button");
  };

  tildaButton.addEventListener("click", onClick);

  return () => {
    tildaButton.removeEventListener("click", onClick);
  };
}, []);

Предварительно надо добавить в разметку id или нужные классы.

SSR

Здесь все прекрасно. Мы осуществляем рендеринг html внутри нашего компонента. Это позволяет web crawler'ам легко считывать контент на странице и индексировать его.

Deploy

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

Итоги

Плюс:

  • Возможность быстрой интеграции готового лендинга в свое React приложение. Оценочное время переноса - 2 часа работы.

Минусы:

  • Отсутствие возможности автоматизировать процесс интеграции, требует ручного вмешательства;

  • Неясное поведение скриптов, что может вызывать различные проблемы;

  • Официальное ограничение на изменение экспортированного контента с подобных ресурсов.

Несмотря на простоту подхода, он полезен, когда у нас есть ограниченное время и требуется быстро перенести лендинг из конструктора в React приложение. Он позволяет достичь быстрых результатов, особенно при срочных проектах.

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

Пример | Код

3 способ: Конструктор React приложений

Страница с интеграцией Builder.io
Страница с интеграцией Builder.io

Если мы хотим использовать React компоненты в привычном формате, предоставить дизайнеру возможность работать с ними в визуальном редакторе, а контент менеджеру редактировать данные отдельно от дизайна, мы можем обратить внимание на конструкторы сайтов. Существует множество интересных решений для дизайнеров и контент менеджеров, таких как Framer или Webflow. Они обладают мощными инструментами визуального редактора и CMS, либо позволяют импортировать данные извне. Однако, сегодня я рассмотрю Builder.io, так как этот инструмент позволяет работать с React компонентами.

Интеграция

Работа с данными и дизайном выходит за рамки данной статьи. Давайте перейдем к сразу к коду:

const [content, setContent] = useState(null);

useEffect(() => {
  builder
    .get(MODEL_NAME, {
      userAttributes: {
        urlPath: "/builder",
      },
    })
    .promise()
    .then(setContent);

  const clickHandler = () => {
    alert("Click button!");
  };

  document.addEventListener("click-button", clickHandler);

  return () => {
    document.removeEventListener("click-button", clickHandler);
  };
}, []);

return (
  <div className={"w-full h-full"}>
    <BuilderComponent model={MODEL_NAME} content={content} />
  </div>
);

Для интеграции этого инструмента, нам нужно отрисовать компонент BuilderComponent и передать в него данные, которые мы получили из builder.get. Это все, что требуется от разработчика для успешной интеграции.

Дополнительно, мы регистрируем событие click-button, которое будет вызываться при клике на кнопку. Конфигурация события производится в админке Builder.io. Это позволяет нам использовать событие для перехода на другие страницы или выполнения действий при нажатии на кнопку.

Builder.io позволяет определять скрипты для работы с интерактивными элементами
Builder.io позволяет определять скрипты для работы с интерактивными элементами

Кроме того, у нас есть возможность регистрировать собственные кастомные компоненты, которые станут доступны из админки Builder.io. Это позволит нам создавать и использовать настраиваемые компоненты, которые соответствуют уникальным потребностям проекта:

const CustomTicker = ({ title }) => {
	// ...
  return (
    <div>
      {title}: {count}
    </div>
  );
};

Builder.registerComponent(CustomTicker, {
  name: "Custom Ticker",
  inputs: [{ name: "title", type: "text", defaultValue: "Ticks" }],
});

После того, как мы зарегистрировали компонент, его можно легко добавить на страницу из левого меню Builder.io. Это предоставляет возможность удобно выбирать и размещать настраиваемые компоненты на странице для дальнейшего редактирования и отображения в React приложении.

В Builder.io относительно дружелюбный UX визуального редактора для разработчика. Но не дизайнера
В Builder.io относительно дружелюбный UX визуального редактора для разработчика. Но не дизайнера

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

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

Кроме того, мы можем легко прописывать собственные обработчики непосредственно в визуальном редакторе. Это позволяет подключать Headless CMS и использовать данные в наших скриптах, что дает большую гибкость и возможности при разработке и настройке компонентов.

SSR

SSR работает отлично, если мы получаем данные на сервере. В результате, мы создаем HTML, который практически неотличим от "родной" кодовой базы. Разработчики могут использовать обучающие материалы, чтобы успешно интегрировать Next.js и Builder.io, что предоставляет дополнительные возможности и преимущества при разработке и оптимизации нашего приложения.

Deploy

Мы получаем контент на этапе запроса, что гарантирует актуальность информации всегда. Нет необходимости в редеплое, если мы хотим внести изменения на странице, созданной с помощью Builder.io. Это обеспечивает быструю и удобную возможность обновления контента без необходимости полного перезапуска приложения.

Итоги

Плюсы:

  • Легкая интеграция для React разработчика. Нам просто необходимо добавить компонент на страницу и зарегистрировать свои собственные;

  • Возможность импортирования макетов из Figma. Однако, есть некоторые нюансы и требуется адаптация готовых макетов для экспорта;

  • Повышение скорости разработки. Обучив дизайнеров и контент-менеджеров данному инструменту, можно создавать страницы без необходимости вмешательства разработчика.

Минусы:

  • Визуальный редактор уступает другим инструментам для дизайнеров. Понимание CSS требуется, так как местами необходимо писать вставки на этом языке;

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

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

Пример | Код

Сравнение

При подведении субъективных итогов по решению задачи “создания страниц”, хочется основываться на личных ощущениях от опыта интеграции. Понимая, что эти инструменты изначально предназначены для разных задач, все же есть пересечения по возможностям в рамках работы внутри React приложения:

Подход

Iframe(Hubspot)

Экспорт статики(Tilda)

Конструктор(Builder.io)

Обработка событий

+

+

+

Routing

+

+

+

Визуальный редактор

+

+

+

Автоматизация деплоя новых версий

+

-

+

Отделение данных от дизайна

+

-

+

Индексация контента(SSR)

-

+

+

SDK

-

-

+

Документация по интеграции

-

-

+

Заключение

Безусловно, выбор инструмента зависит от конкретной задачи. Если ваша цель - обеспечить доставку контента, то подойдет Headless CMS. Если вам нужно добавить определенный функционал, например, формы, то использование iframe с SDK может быть подходящим решением. Целью этой статьи было вдохновить на эксперименты с различными подходами и поощрить стремление решать бизнес-задачи с помощью наиболее подходящих инструментов.

Демо | Код

Успехов в ваших экспериментах и разработке!

Комментарии (0)