Пример Duck Duck Go

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

  • Можно ли его использовать повторно в других проектах или он будет одноразовым? Повторное использование — это здорово, но это увеличит сложность API, поскольку вы представляете себе другие случаи использования, а не только то, что является внутренним для данного сайта.
  • Это визуальная или не визуальная реализация? Визуальная реализация должна состоять из нескольких невизуальных реализаций, чтобы избежать слишком тесной связи.
  • Принимает ли это пользовательский ввод или отвечает на вопрос машины? Должны ли мы удовлетворить запрос пользователя или это скорее кнопка, которую он нажимает, а текущая страница выполняет перебор данных для формирования ответа.
  • Является ли это критически важной услугой или просто приятной мелочью? Критические сервисы (кнопка входа) или приятные (PDF на этой странице), в любом случае должен быть запасной план на случай, если микросервис не ответит.

Duck Duck Go

  • живой пример в сборнике рассказов
  • фронтенд, то есть чисто пример
  • код бэкенда для vercel

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

<div>
        <label>Duck duck go</label>
        <input type="text" id="search" />
        <button id="searchbtn">Search</button>
        <div id="ddgresult"></div>
      </div>
Вход в полноэкранный режим Выйти из полноэкранного режима

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

      this.shadowRoot
        .querySelector("#searchbtn")
        .addEventListener("click", () => {
          const params = {
            q: this.shadowRoot.querySelector("#search").value,
          };
          MicroFrontendRegistry.call("@core/duckDuckGo", params, this.ddgCallback.bind(this));
        });
Вход в полноэкранный режим Выход из полноэкранного режима

и затем вызываем наш класс абстракции / frontend middleware под названием MicroFrontendRegistry. Я напишу другую статью о том, как я создавал API для этого, но идея в том, что вместо вызова конечной точки, мы хотим вызвать имя разработчика для функции и позволить среде выяснить фактический полный адрес.

После того, как параметр q передан микросервису, выполняется ddgCallback с данными ответа от конечной точки.

Микросервис

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

// duckduckgo.js
// this is an example to fork from that uses common, simple conventions
// for getting data, validating data, and responding in a consistent way.
import { stdPostBody, stdResponse, invalidRequest } from "../../../utilities/requestHelpers.js";
import fetch from "node-fetch";
export default async function handler(req, res) {
  // destructing GET params after ? available in this object
  var { q } = req.query;
  // use this if POST data is what's being sent
  const body = stdPostBody(req);
  // fallback support for post
  if (!q && body && body.q) {
    q = body.q;
  }
  // need to know what we're searching for otherwise bail
  if (q) {
    // we import fetch just to simplify endpoint creation but its just node-fetch
    const searchResults = await fetch(`http://api.duckduckgo.com/?q=${q}&format=json`).then((d) => d.ok ? d.json(): {});
    // standard response is how all transactions end
    // this will assume 200 response code unless defined otherwise
    // response data is passed in as searchResults here
    // if type is not set in the options, then it is assumed JSON response
    // and is added to a data param
    res = stdResponse(res, searchResults, {cache: 86400, methods: "OPTIONS, POST" });
  }
  else {
    // invalidate the response and provide a reason
    // this optionally takes in a status code otherwise default is 400
    // vercel will through a 500 if there was any bricking issue so we don't
    // need to throw that most likely
    res = invalidRequest(res, 'missing `q` param');
  }
}
Вход в полноэкранный режим Выход из полноэкранного режима

Здесь мы можем видеть, что перед отправкой в API duck duck go мы проводим простую валидацию вводимых данных. stdResponse затем принимает данные JSON и просто устанавливает соответствующий ответ перед отправкой обратно на фронт-энд. Вышеизложенное хорошо документировано, так что прочитайте, что там происходит, но это довольно просто с небольшими абстракциями для работы с res и req.

Время показа результатов

Итак, как только бэкенд отправит этот JSON-блок обратно, Promise фронтенда будет разрешен в ddgCallback и запущен с data, который был возвращен.

ddgCallback(data) {
    console.log(data.data.RelatedTopics);
    this.shadowRoot.querySelector("#ddgresult").innerHTML = 
    `<code><pre>
    ${JSON.stringify(data.data.RelatedTopics, null, 4)}
    </pre></code>`;
  }
Вход в полноэкранный режим Выход из полноэкранного режима

Здесь мы видим, что это простая распечатка строгированной версии на страницу.

Это довольно простой паттерн, который возникает с микрофронтендами из моих построений нескольких.

  • Имеем ввод
  • сделать вызов стандартным способом (Promise, поэтому async/await по желанию)
  • получить вызов стандартным способом, вернуть данные стандартным способом (json с параметром data)
  • отображение / реакция на ввод

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

Оцените статью
devanswers.ru
Добавить комментарий