Справочник разработчика

Освоение Stubby: исчерпывающее пошаговое руководство по легкому макетированию бэкенда

Раскрытие секретов разработки: пошаговое руководство по освоению Stubby

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

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

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

Сегодня в этом посте мы установим и реализуем stubby4node в проекте ReactJS и NextJS и REST API максимально простым и пошаговым способом. От установки до создания сервисов до инициализации всего проекта с помощью тупиковых команд.

P.S. Вы также можете проверить репозиторий GitHub, где доступен весь код, упомянутый в этом посте.



№1 Установка

Чтобы установить библиотеку Stubby в свой проект, вам нужно перейти на официальную страницу и скопировать команду npm. Эта команда добавит пакет stubby в качестве devDependency в ваш файл package.json.

npm install --save-dev stubby

Вы можете найти больше информации о библиотеке Stubby на странице npm.



#2 Конфигурация

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

Вот пример файловой структуры:

.
├── src
│   ├── components
│   ├── pages
│   └── styles
├── stubby
│   └── index.yaml
├── README.md
├── jsconfig.json
├── next.config.js
├── package-lock.json
└── package.json

Вы можете проверить документацию по конфигурации репозитория Stubby для получения более подробной информации.



#3 Создайте конечные точки и ответы

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

Например, если у вас есть конечная точка GET для получения данных пользователя и конечная точка POST для создания нового пользователя, вы можете создать папку с именем user и вложенные папки с именами get-user и create-new-user для представления этих конечных точек. .

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

Вот пример файловой структуры:

.
├── src
│   ├── components
│   ├── pages
│   └── styles
├── stubby
│   ├── create-new-user
│   │   └── data.json
│   ├── get-user
│   │   └── data.json
│   └── index.yaml
├── README.md
├── jsconfig.json
├── next.config.js
├── package-lock.json
└── package.json

В каждый файл data.json вы можете добавить фактические данные ответа, которые вы ожидаете от серверной части. Например:

// get-user/data.json
{
    "name": "Anita",
		"email": "Smith"
}
// create-new-user/data.json
{
    "status": 200,
    "message": "User created successfully!",
    "user": {
        "id": 111,
        "name": "Anita",
        "email": "Smith"
    }
}

‹в сторону› 💡 Обратите внимание, что эти конечные точки и ответы будут работать только локально, а не в производственной среде. Обязательно используйте соответствующие конечные точки и ответы при связывании серверной части с внешней частью проекта.

После создания папок, файлов и ответов необходимо указать конечные точки и соответствующие им пути к файлам в файле index.yaml. Убедитесь, что каждая конечная точка начинается с ^/, чтобы указать начало URL-адреса конечной точки. Используйте тот же маршрут и имена файлов, которые вы определили в каталоге stubby.

Вот пример файла index.yaml:

- request:
    method: GET
    url: ^/user/get-user
  response:
    headers:
      content-type: application/json
    file: ./get-user/data.json
- request:
    method: POST
    url: ^/user/create-new-user
    headers:
      content-type: application/json
  response:
    headers:
      content-type: application/json
    status: 200
    file: ./create-new-user/data.json

#4 Создание сервисов

Теперь нам нужно вызвать эти конечные точки и использовать их в проекте. Если вы уже выполнили эту часть, вы можете пропустить ее и перейти к следующему шагу.

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

Вот пример структуры каталогов:

.
├── src
│   ├── components
│   ├── pages
│   ├── services
│   │   └── user
│   │       └── index.js
│   └── styles
├── stubby
│   ├── create-new-user
│   │   └── data.json
│   ├── get-user
│   │   └── data.json
│   └── index.yaml
├── README.md
├── jsconfig.json
├── next.config.js
├── package-lock.json
└── package.json

Затем создайте файл services/user/index.js и определите функции, которые вызывают конечные точки. Эти функции должны соответствовать конечным точкам, определенным как на тупиковом сервере, так и на бэкенде.

export const getUser = async (idUser) => {
    try {
      const url = `/user/get-user?id=${idUser}`;
      const response = await fetch(url);
      const data = await response.json();
      return data;
    } catch (error) {
      console.error(error.message);
    }
  };
  
  export const createNewUser = async (userData) => {
    try {
      const url = "/user/create-new-user";
      const response = await fetch(url, {
        method: "POST",
        headers: {
          "Content-Type": "application/json",
        },
        body: JSON.stringify(userData),
      });
      const data = await response.json();
      return data;
    } catch (error) {
      console.error(error.message);
    }
  };

В этом примере мы будем использовать эти функции в форме. Когда форма будет отправлена, мы вызовем конечную точку, которая создаст нового пользователя в базе данных (user/create-new-user). Если ответ имеет код состояния 200, мы отобразим сообщение с информацией о новом пользователе, использующем конечную точку /user/get-user.

Вот пример использования этих функций в компоненте Home:

import { createNewUser, getUser } from '@/services/user';
import Head from 'next/head'
import { useState } from 'react';

const Home = () => {
  const [form, setForm] = useState({});

  const handleChangeInput = (e) => {
    setForm({...form, [e.target.name]: e.target.value});
  };

  const createMessage = (isError, user) => {
    return isError ? 'The user was succesfully created' :
      `Hi! ${user.name} your user was succesfully created`
  };

  const getNewUser = async (idUser) => {
    try {
      const newUser = await getUser(idUser);
      alert(createMessage(false, newUser));
    }
    catch (error) {
      console.error(error.message);
      return alert(createMessage(true, {}));
    }

  };

  const handleRegisterSubmit = async (e) => {
    e.preventDefault();
    try {
      const responseRegister = await createNewUser(form);
      if(responseRegister.status == 200) getNewUser(responseRegister.user.id);
    } catch {
      alert('Something happened, please try again')
    }
  };

  return (
    <>
      <Head>
        <title>Create Next App</title>
        <meta name="description" content="Generated by create next app" />
        <meta name="viewport" content="width=device-width, initial-scale=1" />
        <link rel="icon" href="/favicon.ico" />
      </Head>
      <main>
        <form onSubmit={e => handleRegisterSubmit(e)}>
          <div>
            <label>Your name</label>
            <input name='name' placeholder="John Smith" onChange={e => handleChangeInput(e)} />
          </div>
          <div>
            <label>Your email</label>
            <input name='email' placeholder="[email protected]" onChange={e => handleChangeInput(e)} />
          </div>

          <button type='submit'>Register</button>
        </form>
      </main>
    </>
  )
};

export default Home;

# 5 Инициализировать заглушку

Теперь, когда все создано и использовано, давайте настроим файл проекта package.json для его интеграции с stubby.

Во-первых, нам нужно установить зависимость concurrently. Этот пакет позволяет нам управлять и запускать несколько процессов одновременно без необходимости в отдельных окнах терминала. Это поможет нам запустить как тупиковый сервер для имитации API, так и сервер Next.js для нашего внешнего кода в одной команде.

Чтобы установить concurrently как devDependency, выполните следующую команду:

npm install concurrently --save-dev

Для получения более подробной информации вы можете проверить их собственную документацию.



Теперь давайте обновим файл package.json. Добавьте сценарии dev:stubby и stubby рядом с существующими сценариями Next.js. Сценарий dev:stubby будет одновременно запускать и тупиковый сервер, и сервер разработки Next.js, а скрипт stubby запустит только тупиковый сервер.

Вот пример обновленного package.json:

{
  "name": "example-stubby",
  "version": "0.1.0",
  "private": true,
  "scripts": {
    "dev": "next dev",
    "build": "next build",
    "start": "next start",
    "lint": "next lint",
    "dev:stubby": "concurrently --kill-others \\"npm run stubby\\" \\"npm run dev\\"",
    "stubby": "stubby -w -d ./stubby/index.yaml -s 8815 -a 8816 -t 8817"
  },
  "dependencies": {
    "next": "13.4.4",
    "react": "18.2.0",
    "react-dom": "18.2.0"
  },
  "devDependencies": {
    "concurrently": "^8.2.0"
  }
}

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

dev:stubby: этот сценарий используется для одновременного запуска как сервера-заглушки, так и сервера разработки Next.js. Он использует пакет concurrently для параллельного запуска нескольких команд в одном окне терминала.

npm run stubby: Эта команда запускает сценарий stubby, который запускает тупиковый сервер для имитации API на основе конфигураций, указанных в файле index.yaml.

npm run dev: Эта команда запускает сервер разработки Next.js, на котором выполняется ваше приложение Next.js.

Объединение этих двух команд с использованием concurrently позволяет вам одновременно запускать и сервер-заглушку, и сервер Next.js, что позволяет использовать имитацию API при разработке внешнего приложения.

stubby: Этот сценарий запускает тупиковый сервер независимо, не запуская сервер Next.js.

stubby -w -d ./stubby/index.yaml -s 8815 -a 8816 -t 8817: Эта команда запускает тупиковый сервер со следующими конфигурациями:

  • -w: отслеживает изменения в файле index.yaml и автоматически перезагружает сервер при возникновении изменений.
  • -d ./stubby/index.yaml: указывает расположение файла YAML, содержащего конфигурации тупиковых серверов.
  • -s 8815: Устанавливает HTTP-порт для сервера-заглушки.
  • -a 8816: Устанавливает порт HTTPS для тупикового сервера.
  • -t 8817: Устанавливает тупиковый порт портала администрирования.

Запуск сценария stubby в одиночку запускает тупиковый сервер, что позволяет использовать его для имитации API независимо от сервера Next.js.

Эти скрипты обеспечивают удобство и гибкость при запуске сервера-заглушки и сервера Next.js в зависимости от ваших конкретных потребностей во время разработки.

Если вы хотите проверить правильность инициализации stubby, вы можете использовать npm run stubby. В терминале вы должны увидеть что-то вроде этого:

> [email protected] stubby
> stubby -w -d ./stubby/index.yaml -s 8815 -a 8816 -t 8817
Loaded: GET ^/user/get-user
Loaded: POST ^/user/create-new-user
Watching for changes in ./stubby/index.yaml...
Quit: ctrl-c
Stubs portal running at <https://0.0.0.0:8817>
Stubs portal running at <http://0.0.0.0:8815>
Admin portal running at <http://0.0.0.0:8816>

Это означает, что stubby работает на портале http://0.0.0.0:8815. Если вы хотите вызвать конечную точку, которая предоставляет информацию о пользователе, вы можете проверить URL-адрес http://0.0.0.0:8815/user/get-user. Он должен вернуть следующий ответ и быть напечатанным на странице:

{
    "name": "Anita",
    "email": "Smith"
}

Самое приятное то, что теперь вы можете использовать npm run dev:stubby для одновременного запуска как сервера-обрубка, так и сервера разработки Next.js, что позволяет вам тестировать конечные точки API во время работы над проектом Next.js.

Но чего-то не хватает! Если вы запустите решение, заполните форму и нажмете кнопку Зарегистрироваться, появится предупреждающее сообщение о том, что что-то пошло не так. Если вы проверите вкладку сети в Dev Console браузера, вы увидите код состояния 404 (не найдено) для конечной точки create-new-user. Причина в том, что мы вызываем конечную точку http://localhost:3000/user/create-new-user, но на самом деле наша конечная точка использует порт 8815. Таким образом, правильный URL-адрес конечной точки должен быть http://0.0.0.0:8815/user/create-new-user.

Чтобы решить эту проблему, нам нужно добавить переменную среды в файл .env и включить ее в конфигурацию Next.js.

Обновите файл .env следующим содержимым:

DEPLOY_ENVIRONMENT=local
BASE_URL=http://localhost:3000
LOCAL_PORT_BFF=8815

Затем обновите файл next.config.js. Эта конфигурация работает как с локальной, так и с производственной средой.

/** @type {import('next').NextConfig} */
const ENV = process.env.DEPLOY_ENVIRONMENT || 'local';
const LOCAL_PORT_BFF = process.env.LOCAL_PORT_BFF || 8080;
const getUrlsByEnvironment = {
  local: {
    BFF: `http://localhost:${LOCAL_PORT_BFF}`,
  },
  prod: {
    BFF: '<https://www.url-backend.com>',
  },
};
const nextConfig = {
  reactStrictMode: true,
  publicRuntimeConfig: {
    ...getUrlsByEnvironment[ENV]
  }
}
module.exports = nextConfig

С этими настройками снова запустите команду npm run dev:stubby, и вы увидите, что конечные точки теперь вызываются правильно.

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

Для получения дополнительной информации о переменных среды вы можете обратиться к документации Vercel по переменным среды.



P.S. Если вы являетесь носителем испанского языка или изучаете этот прекрасный язык, вы можете проверить двойной пост, который будет на испанском языке. Одна и та же концепция и объяснения, но на другом языке 😉 каждую неделю.