Назад в блог

~7–8 минут

Backend еще не готов? Как не остановить фронтенд и быстро поднять тестовое API

96

20.12.2025

AI может написать код API за пару секунд, но фронтенду важнее понять, какие данные, ошибки и состояния нужно проверить. Разбираемся, как быстро поднять тестовое API на Express и не зависнуть в разработке.

Вадим Пашаев

Вадим Пашаев

Инженер, веб-разработчик, путешественник

Backend еще не готов? Как не остановить фронтенд и быстро поднять тестовое API

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

Находишь какой-нибудь сервис с пользователями, постами, товарами, картинками или погодой. Кстати, если нужен стартовый список, я уже собирал 15 бесплатных API для тестовых приложений. Подключаешь fetch, получаешь данные и вроде бы можно спокойно верстать дальше.

Но сейчас появился еще один вариант: просто спросить AI.

Написать в ChatGPT, Codex или любой другой инструмент что-то вроде:

Сделай мне простое API на Express с пользователями

И он действительно выдаст рабочий код.

Тут как будто возникает вопрос: а зачем тогда вообще читать статью?

И вот здесь важный момент.

Проблема обычно не в том, чтобы получить 30 строк JavaScript. Это AI сейчас делает довольно неплохо. Проблема в другом: понять, какие данные нужны интерфейсу, какие состояния надо проверить и где заканчивается тестовое API, а начинается нормальная backend-разработка.

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

Он ломается, когда:

  • данных нет;
  • запрос идет слишком долго;
  • сервер вернул 400;
  • пользователь не найден;
  • форма отправилась два раза;
  • CORS решил напомнить о себе;
  • структура ответа не совпала с тем, что ожидает UI.

Вот об этом и поговорим.

Не просто "как написать API на Express", а как быстро сделать себе рабочий инструмент, чтобы не ждать backend и нормально проверять фронтенд.

Когда вообще нужен свой тестовый API

Я бы смотрел на это не как на "давайте напишем backend", а как на способ не остановить разработку.

Свой временный API полезен, если:

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

Например, ты делаешь CRM. В интерфейсе есть клиенты, сделки, статусы, менеджеры, фильтры и карточка клиента. Бесплатный API с постами и пользователями тут может помочь только на самом старте. Дальше все равно придется подгонять данные под продукт.

А если ты сам делаешь тестовое API, то можешь сразу вернуть такие поля, которые реально нужны интерфейсу:

{
  id: 1,
  name: 'Алиса',
  email: 'alice@mail.ru',
  role: 'designer',
  status: 'active'
}

И фронтенд начинает работать с нормальной структурой, а не с чужим форматом, который ты потом героически преобразуешь на клиенте.

Почему не всегда достаточно AI

AI отлично помогает быстро сгенерировать основу.

Но он не всегда знает контекст твоего проекта:

  • какие поля реально есть в макете;
  • какие состояния должен показывать интерфейс;
  • как backend будет устроен потом;
  • какие ошибки важно протестировать;
  • какие ограничения есть у команды;
  • что нужно показать клиенту уже завтра.

Поэтому я бы использовал AI как ускоритель, а не как замену мышления.

Можно попросить его сгенерировать код, но перед этим самому ответить на несколько вопросов:

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

Вот тогда AI становится реально полезным. Он пишет быстрее, а ты понимаешь, что именно он должен написать.

Какие есть варианты, если backend еще не готов

Обычно вариантов несколько.

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

Можно использовать json-server. Это крутой вариант, когда хочется почти моментально получить REST API из одного JSON-файла. Очень удобно для прототипов.

Можно генерировать данные через Faker. Например, пользователей, emails, адреса, товары, компании. Это помогает, когда нужно много похожих тестовых данных.

Можно взять Strapi, если уже нужна админка, коллекции, роли и управление контентом. Я отдельно разбирал создание проекта на Strapi - для MVP и контентных проектов это часто прям хороший путь.

А можно написать маленький Express-сервер.

И вот Express удобен, когда хочется контролировать не только данные, но и поведение API: статусы, задержки, ошибки, разные сценарии.

Что мы будем делать

Давайте соберем простой тестовый API на Express.

Без базы данных, Docker, авторизации и сложной архитектуры.

Нам понадобится:

  • Node.js LTS;
  • Express;
  • пакет cors, если фронтенд и API работают на разных портах;
  • обычный массив с данными;
  • 10-15 минут времени.

Наша цель - не сделать production backend. Наша цель - получить инструмент, который поможет фронтенду двигаться дальше.

Быстро поднимаем проект

Проверяем, что Node.js и npm установлены:

node -v
npm -v

Создаем папку:

mkdir test-api
cd test-api
npm init -y

Ставим Express и CORS:

npm install express cors

В package.json добавим scripts:

{
  "scripts": {
    "start": "node index.js",
    "dev": "node --watch index.js"
  }
}

node --watch удобен тем, что сервер сам перезапускается после изменений. Не главная магия в мире, но в работе приятно.

Пишем основу сервера

Создаем файл index.js:

const express = require('express')
const cors = require('cors')

const app = express()
const PORT = 3000

app.use(cors())
app.use(express.json())

Что здесь происходит:

  • express() создает приложение;
  • cors() помогает фронтенду обращаться к API с другого origin, например с localhost:5173;
  • express.json() позволяет серверу читать JSON из тела запроса.

Для локального тестового API можно включить CORS широко через app.use(cors()). Для production так лучше не делать бездумно, но сейчас мы решаем задачу разработки.

Добавим данные:

let users = [
  {
    id: 1,
    name: 'Алиса',
    email: 'alice@mail.ru',
    role: 'designer',
    status: 'active'
  },
  {
    id: 2,
    name: 'Максим',
    email: 'max@mail.ru',
    role: 'frontend',
    status: 'blocked'
  }
]

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

Первый endpoint - список пользователей

Endpoint - это точка входа в API. Клиент отправляет запрос на конкретный путь, а сервер понимает, какую функцию выполнить.

В Express это выглядит так:

app.get('/users', (req, res) => {
  res.json(users)
})

Добавим запуск сервера:

app.listen(PORT, () => {
  console.log(`API is running on http://localhost:${PORT}`)
})

Запускаем:

npm run dev

Проверяем:

GET http://localhost:3000/users

Все. У нас уже есть API, которое возвращает список пользователей.

Но самое полезное начинается дальше.

Не только happy path

Многие тестовые API показывают только идеальный сценарий: запросили список - получили список.

Но в реальном интерфейсе этого мало.

Если мы хотим нормально проверить фронтенд, нам нужны разные сценарии:

  • пользователь найден;
  • пользователь не найден;
  • форма отправлена успешно;
  • форма отправлена с ошибкой;
  • список пустой;
  • запрос идет долго;
  • сервер временно упал.

Вот это уже похоже на настоящую работу.

Получение пользователя по id

Добавим endpoint для детальной страницы:

app.get('/users/:id', (req, res) => {
  const id = Number(req.params.id)
  const user = users.find(item => item.id === id)

  if (!user) {
    return res.status(404).json({
      message: 'Пользователь не найден'
    })
  }

  res.json(user)
})

Теперь можно запросить:

GET http://localhost:3000/users/1

А можно специально открыть несуществующего пользователя и проверить, как интерфейс показывает 404.

Это маленькая вещь, но она сразу делает UI крепче.

Создание пользователя

Теперь добавим POST.

Во фронтенде это обычно нужно для форм: регистрация, заявка, комментарий, создание товара, новая задача.

app.post('/users', (req, res) => {
  const { name, email, role = 'user', status = 'active' } = req.body

  if (!name || !email) {
    return res.status(400).json({
      message: 'Поля name и email обязательны'
    })
  }

  const user = {
    id: Date.now(),
    name,
    email,
    role,
    status
  }

  users.push(user)

  res.status(201).json(user)
})

Здесь важно не только то, что мы создаем пользователя.

Важно, что мы сразу добавили ошибку 400, если не пришли обязательные поля. Потому что форма должна уметь показать не только "успешно сохранено", но и "заполни имя и email".

В документации Express отдельно напоминают: req.body приходит от пользователя, поэтому ему нельзя слепо доверять. Даже в тестовом API полезно привыкать проверять входные данные.

Пример JSON:

{
  "name": "Ирина",
  "email": "irina@mail.ru",
  "role": "manager"
}

Удаление пользователя

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

Добавим DELETE:

app.delete('/users/:id', (req, res) => {
  const id = Number(req.params.id)
  const userExists = users.some(item => item.id === id)

  if (!userExists) {
    return res.status(404).json({
      message: 'Пользователь не найден'
    })
  }

  users = users.filter(item => item.id !== id)

  res.status(204).send()
})

204 означает, что запрос прошел успешно, но тела ответа нет. Для удаления это нормальный сценарий.

Задержка, пустой список и ошибка

Вот этот блок я бы вообще не пропускал.

Потому что именно такие состояния часто забывают проверить.

Задержка:

app.get('/slow-users', (req, res) => {
  setTimeout(() => {
    res.json(users)
  }, 1200)
})

Теперь можно увидеть loader, skeleton или disabled-состояние кнопки.

Пустой список:

app.get('/empty-users', (req, res) => {
  res.json([])
})

Ошибка сервера:

app.get('/error', (req, res) => {
  res.status(500).json({
    message: 'Что-то пошло не так'
  })
})

Вроде мелочи, но именно они помогают сделать интерфейс нормальным, а не только красивым на одном идеальном скриншоте.

Полный пример index.js

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

const express = require('express')
const cors = require('cors')

const app = express()
const PORT = 3000

app.use(cors())
app.use(express.json())

let users = [
  {
    id: 1,
    name: 'Алиса',
    email: 'alice@mail.ru',
    role: 'designer',
    status: 'active'
  },
  {
    id: 2,
    name: 'Максим',
    email: 'max@mail.ru',
    role: 'frontend',
    status: 'blocked'
  }
]

app.get('/users', (req, res) => {
  res.json(users)
})

app.get('/users/:id', (req, res) => {
  const id = Number(req.params.id)
  const user = users.find(item => item.id === id)

  if (!user) {
    return res.status(404).json({
      message: 'Пользователь не найден'
    })
  }

  res.json(user)
})

app.post('/users', (req, res) => {
  const { name, email, role = 'user', status = 'active' } = req.body

  if (!name || !email) {
    return res.status(400).json({
      message: 'Поля name и email обязательны'
    })
  }

  const user = {
    id: Date.now(),
    name,
    email,
    role,
    status
  }

  users.push(user)

  res.status(201).json(user)
})

app.delete('/users/:id', (req, res) => {
  const id = Number(req.params.id)
  const userExists = users.some(item => item.id === id)

  if (!userExists) {
    return res.status(404).json({
      message: 'Пользователь не найден'
    })
  }

  users = users.filter(item => item.id !== id)

  res.status(204).send()
})

app.get('/slow-users', (req, res) => {
  setTimeout(() => {
    res.json(users)
  }, 1200)
})

app.get('/empty-users', (req, res) => {
  res.json([])
})

app.get('/error', (req, res) => {
  res.status(500).json({
    message: 'Что-то пошло не так'
  })
})

app.listen(PORT, () => {
  console.log(`API is running on http://localhost:${PORT}`)
})

Для тестового API этого уже достаточно, чтобы нормально двигаться по фронтенду.

Как использовать на фронтенде

Самый простой вариант:

fetch('http://localhost:3000/users')
  .then(res => res.json())
  .then(data => {
    console.log(data)
  })

Но я бы все-таки сразу проверял response.ok.

Почему? Потому что fetch не считает HTTP-статусы вроде 404 или 500 ошибкой на уровне Promise. Сервер ответил - значит Promise выполнился. А успешный это ответ или нет, нужно проверять самому.

Например:

async function loadUsers() {
  const response = await fetch('http://localhost:3000/users')

  if (!response.ok) {
    throw new Error(`Ошибка запроса: ${response.status}`)
  }

  return response.json()
}

Для отправки формы:

async function createUser(user) {
  const response = await fetch('http://localhost:3000/users', {
    method: 'POST',
    headers: {
      'Content-Type': 'application/json'
    },
    body: JSON.stringify(user)
  })

  const data = await response.json()

  if (!response.ok) {
    throw new Error(data.message || 'Не удалось создать пользователя')
  }

  return data
}

React, Vue, Next.js, обычный HTML - разницы почти нет. Для клиента это обычный backend, который отвечает по HTTP.

Что важно решить до кода

Вот здесь как раз тот момент, который AI за тебя не всегда решит.

Перед тем как писать или генерировать API, стоит набросать простую карту:

  • какие экраны есть в интерфейсе;
  • какие сущности нужны каждому экрану;
  • какие поля нужны компонентам;
  • какие действия делает пользователь;
  • какие ошибки могут произойти;
  • какие состояния нужно проверить.

Например:

  • экран списка пользователей - нужен GET /users;
  • страница пользователя - нужен GET /users/:id;
  • форма создания - нужен POST /users;
  • удаление - нужен DELETE /users/:id;
  • loader - нужен /slow-users;
  • empty state - нужен /empty-users;
  • error state - нужен /error.

После такой карты даже AI начинает давать намного более полезный код, потому что ты задаешь ему нормальную задачу, а не просто "сделай API".

Когда Express лучше, чем готовый mock-сервис

Готовые mock-сервисы удобны, когда нужно совсем быстро.

Но Express лучше подходит, если ты хочешь:

  • самостоятельно описывать логику ответов;
  • возвращать разные статусы;
  • проверять валидацию;
  • имитировать задержки;
  • готовить данные под конкретный UI;
  • сделать несколько связанных сущностей;
  • быстро показать команде, как примерно должен работать будущий API.

Например, можно сделать так: фронтенд работает с твоим Express API, а потом настоящий backend повторяет похожие endpoints. И переход получается намного спокойнее.

Не всегда идеально, конечно. Но для MVP и разработки интерфейса это очень рабочий подход.

Полезные источники

Если хочется копнуть глубже и не опираться только на эту статью, вот нормальные первоисточники:

Где границы такого подхода

Важно не переоценивать тестовое API.

У такого решения быстро появляются ограничения:

  • данные не сохраняются после перезапуска сервера;
  • нет ролей и прав доступа;
  • нет нормальной админки;
  • нет базы данных;
  • нет полноценной backend-валидации;
  • нет логирования;
  • нет масштабирования.

И это нормально.

Тестовое API - это не фундамент большой системы. Это временный инструмент, который помогает быстрее проверить идею, собрать интерфейс и не зависнуть на этапе "а где взять данные?".

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

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

Но на старте маленький Express-сервер на 50-100 строк может сэкономить очень много времени.

В итоге

Сейчас действительно проще спросить AI, чем искать старый туториал в поиске.

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

Сильная разработка - понять, что именно нужно проверить: какие данные, какие ошибки, какие состояния, какие сценарии пользователя.

Свое тестовое API помогает:

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

Бесплатные API - хороший старт.

AI - отличный ускоритель.

А понимание того, что именно нужно интерфейсу, - это уже следующий уровень.

Так что если backend еще не готов, не обязательно останавливать фронтенд. Иногда достаточно открыть терминал, написать npm install express cors и собрать свое маленькое API под конкретную задачу.

Хорошего кодинга 👌

Читать далее

15 бесплатных API для написания тестовых приложений | PXSTUDIO
15 бесплатных API для написания тестовых приложений

Мы обнаружили, что многие из тестовых API являются платными, что может немного затруднить обучение работе с API. К счастью для это...

Создание проекта на Strapi | PXSTUDIO
Создание проекта на Strapi

Strapi - это headless (буквально "безголовая") полностью кастомизируемая CMS с открытым исходным кодом. Написана на 100% Javascrip...

Стартовый шаблон Next.js + MUI5 + TypeScript | PXSTUDIO
Стартовый шаблон Next.js + MUI5 + TypeScript

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

Удаление цвета фона ввода для автозаполнения Chrome? | PXSTUDIO
Удаление цвета фона ввода для автозаполнения Chrome?

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

Подписаться на рассылку

Получите интересные новости по веб-разработке и AI

Этот сайт защищен reCAPTCHA, применяются Политика конфиденциальности и Условия использования Google.

Подписаться на рассылку

Получите интересные новости по веб-разработке и AI

Этот сайт защищен reCAPTCHA, применяются Политика конфиденциальности и Условия использования Google.

Расскажите, что нужно сделать

Разберем задачу и предложим следующий шаг

Contact to pxstudio

Сайт, сервис, Telegram-бот, AI-интеграция или оптимизация текущего проекта — опишите ситуацию, а мы подскажем нормальный технический путь.

Этот сайт защищен reCAPTCHA, применяются Политика конфиденциальности и Условия использования Google.

Есть интересная идея?

И вы очень хотите ее реализовать, пишите нам и получите подробное коммерческое предложение и быструю реализацию