Привет! Меня зовут Ларионова Екатерина, я фронтенд-разработчик в компании AXENIX.
В современной разработке программного обеспечения согласованность между документацией, дизайном API и его реализацией играет ключевую роль. Эффективно решить эту задачу помогает подход API-First, при котором проектирование интерфейсов становится отправной точкой всего процесса. Одним из основных инструментов, поддерживающих этот подход, является спецификация OpenAPI — мощный инструмент для описания RESTful API, который позволяет не только формализовать поведение сервисов, но и автоматизировать множество сопутствующих задач.
Мы все чаще сталкиваемся с парадоксом: с одной стороны, растут требования к скорости вывода продукта на рынок, с другой — увеличивается сложность приложений. При этом, разработчики тратят большое количество времени на рутинные задачи, такие как интеграция с API и написание boilerplate-кода. Именно здесь на помощь приходит автоматизация рутинных задач во фронтенде на основе OpenAPI-спецификаций и она может очень сильно упростить нам, фронтендерам, жизнь!
OpenAPI как рабочий инструмент
OpenAPI выходит за рамки простого описания API, становясь ключевым элементом в процессе разработки. Вот основные преимущества в использовании OpenAPI-спецификации:
Автогенерация API-клиента — исключает рутинное написание повторяющегося кода за счёт автоматической генерации клиентов, типов и моков.
Мок-серверы для разработки — позволяют фронтенду начать работу до готовности бэкенда, экономя время и упрощая параллельную разработку.
Типизация и исключение ошибок — автоматическая генерация типов для TypeScript предотвращает опечатки и несоответствия данных.
Упрощённое тестирование — генерация моков и стабов для тестов ускоряет проверку логики приложения.
Надёжность и согласованность. Документация = источник истины — все компоненты (клиент, сервер, тесты) синхронизированы с описанием API, что снижает риск расхождений. Чёткий API-контракт минимизирует ошибки взаимодействия между командами.
Генерация клиентского кода из OpenAPI-спецификации
Автоматическая генерация клиентского кода из OpenAPI-спецификации — мощный инструмент в арсенале современного разработчика. Давайте разберёмся, как это работает на практике и как можно интегрировать этот процесс в ваш проект.
Подготовка спецификации
Перед началом работы нам понадобится сама OpenAPI-спецификация, которую обычно предоставляет аналитик. Фронтенд-разработчики могут затем работать с ней следующими способами:
Локальный файл
Swagger UI — через URL документации вашего API
Git-репозиторий — например, из корпоративного GitLab
Лучше всего хранить OpenAPI-спецификацию в Git-репозитории — это обеспечивает версионность, контроль изменений и доступ для всей команды. Вот ряд плюсов:
Сохранение истории правок — если API меняется, фронтендеры могут сравнить старую и новую версии спецификации через git diff.
Синхронизация — все разработчики работают с актуальной версией, а не с локальными копиями.
CI/CD интеграция — можно генерировать из спецификации код при каждом обновлении репозитория.
В данной статье мы рассмотрим самый простой способ работы с OpenAPI-спецификацией — использование локального файла. Этот вариант идеально подходит для быстрого старта т.к. не требует настройки Git или доступа к серверу документации.
Поместите файл спецификации schema.yaml
в ваш проект. В рамках данной статьи для примера будет использоваться папка /openapi-schemas
в корне проекта.
ваш_проект/
├── openapi-schemas/ # Папка из примеров
│ └── schema.yaml # Основной файл спецификации
├── src/ # Исходный код проекта
└── ... # Остальные файлы
Теперь вы можете ссылаться на этот файл в инструментах разработки.
Настройка инструментов генерации
Для генерации кода мы будем использовать OpenAPI Generator — один из самых популярных инструментов в этой области. Он позволяет автоматически создавать клиентские и серверные SDK, документацию и другую логику, связанную с API, на основе OpenAPI-спецификации.
Перед использованием OpenAPI Generator важно знать главное техническое требование: у вас должна быть установлена Java. Скачать ее можно с официального сайта Oracle.
Установите CLI-версию генератора как dev-зависимость в ваш проект с помощью команды:
npm install @openapitools/openapi-generator-cli --save-dev
Конфигурация генератора
Создайте в корне проекта файл openapitools.json
с базовой конфигурацией:
{
"$schema": "./node_modules/@openapitools/openapi-generator-cli/config.schema.json",
"spaces": 2,
"generator-cli": {
"version": "7.13.0",
"generators": {
"api-axfood": {
"generatorName": "typescript-axios",
"output": "./src/shared/api/api-axfood",
"inputSpec": "./openapi-schemas/schema.yaml"
}
}
}
}
При необходимости добавьте дополнительные настройки для кастомизации в поле additionalProperties
:
{
"$schema": "./node_modules/@openapitools/openapi-generator-cli/config.schema.json",
"spaces": 2,
"generator-cli": {
"version": "7.13.0",
"generators": {
"api-axfood": {
"generatorName": "typescript-axios",
"output": "./src/shared/api/api-axfood",
"inputSpec": "./openapi-schemas/schema.yaml",
"additionalProperties": {
"apiPackage": "api",
"modelPackage": "models",
"withSeparateModelsAndApi": true,
"withInterfaces": true,
"supportsES6": true
}
}
}
}
}
Ключевые параметры:
• generatorName
: используемый генератор (typescript-axios, typescript-angular, typescript-fetch и др.)
• output
: путь для сгенерированных файлов
• inputSpec
: путь к OpenAPI-спецификации
• additionalProperties
: дополнительные настройки генерации
Популярные дополнительные свойства:
• withSeparateModelsAndApi
: флаг разделения API и моделей по папкам. По дефолту модели и API генерируются в один большой файл
• apiPackage/modelPackage
: название папок для файлов API и моделей
• withInterfaces
: генерация интерфейсов
• supportsES6
: использование ES6-синтаксиса
С полным списком параметров вы можете ознакомиться в официальной документации для генератора typescript-axios.
Интеграция в процесс разработки
Для удобства добавьте команду в раздел scripts файла package.json
:
"scripts": {
"api:generate": "openapi-generator-cli generate"
}
Теперь генерация кода выполняется одной командой: npm run api:generate
Проверка результатов
После выполнения команды откройте папку ./src/shared/api/api-axfood
. Убедитесь, что:
• Контроллеры находятся в папке /api
• Модели — в папке /models
Создание API-клиента
Для работы со сгенерированным API создайте клиентский файл. Например, ./src/shared/api/client.ts
:
import { Configuration, DefaultApi as AxFoodApi } from './api-axfood';
const apiConfig = new Configuration({
basePath: '',
});
export const apiAxFood = new AxFoodApi(apiConfig);
Далее объект apiAxFood
можно будет использовать в вашем проекте для доступа к методам API.
Генерация моков для API
Я достаточно часто сталкивалась с ситуацией, когда API ещё не было готово, но фронтенд уже нужно было разрабатывать. В таких случаях на помощь приходят моки — имитации реальных API-ответов. Далее мы рассмотрим, как автоматизировать процесс создания моков на основе OpenAPI-спецификации
Для генерации ответов будем использовать библиотеку msw-auto-mock, которая является расширением библиотеки MSW (Mock Service Worker).
Установите необходимые библиотеки, выполнив следующую команду:
npm install --dev msw msw-auto-mock @faker-js/faker
После установки инициализируйте MSW в нашем проекте:
msw init public/ --save
Эта команда создаст необходимые файлы для работы Service Worker в указанной директории public/
.
Генерация моков
Основная магия происходит при выполнении следующей команды. С помощью нее будут сгенерированы моки по нашей спецификации:
msw-auto-mock ./openapi-schemas/schema.yaml -o ./mock --typescript
Параметры:
• ./openapi-schemas/schema.yaml
— путь к файлу спецификации
• -o ./mock
— директория для выходных файлов
• --typescript
— генерация TypeScript-кода
Интеграция моков в приложение
Для подключения сгенерированных моков достаточно добавить следующие строки кода в точку входа вашего приложения (обычно main.ts
или index.ts
):
import { worker } from "../mock/browser";
await worker.start();
Вот и все! Всего три команды и пара строк кода — и моки, сгенерированные по OpenAPI-спецификации, готовы к использованию.
Генерация UI-прототипов по OpenAPI с помощью ИИ
В качестве эксперимента я решила проверить, насколько современные ИИ-инструменты способны генерировать рабочие интерфейсы на основе OpenAPI-спецификаций. Для быстрого прототипирования этот метод показал себя неожиданно полезным, однако требовал небольшие доработки и ручную адаптацию. Важно понимать, что это скорее любопытная альтернатива традиционному подходу, а не готовое решение для production.
Можно использовать любой ИИ-инструмент для разработчиков.
Ключевой момент — формулировка задачи. Пример рабочего промпта:
Сгенерируй компоненты для прототипа на React и Antd по спецификации openapi.
Используй все параметры из спецификации.
Воспользуйся сгенерированными с помощью openapi-generator-cli typescript-axios моделями и контроллерами.
Сделай интерфейс адаптивным.
Что мы конкретно указали:
• Технологический стек (React + Ant Design)
• Источник данных (OpenAPI + сгенерированные модели)
• Требования к адаптивности
И вот такой компонент у нас был сгенерирован.
import axios from 'axios';
import React, {useState} from 'react';
import {Form, Input, Select, Button, message} from 'antd';
import type {CreateOrderRequest, ModelError} from "../shared/api/api-axfood";
import {apiAxFood} from "../shared/api/client.ts";
const OrderForm: React.FC = () => {
const [form] = Form.useForm();
const [loading, setLoading] = useState(false);
const [messageApi, context] = message.useMessage();
const onFinish = async (values: CreateOrderRequest) => {
setLoading(true);
try {
const response = await apiAxFood.createOrder(values);
messageApi.success(`Заказ успешно оформлен! Номер заказа: ${response.data.orderId}`);
form.resetFields();
} catch (error) {
if (axios.isAxiosError<ModelError>(error)) {
if (error.response && error.response.data) {
const { code, message: errorMessage } = error.response.data;
messageApi.error(`Ошибка (${code}): ${errorMessage}`);
} else {
messageApi.error('Произошла ошибка при оформлении заказа.');
}
} else {
messageApi.error('Неизвестная ошибка.');
}
} finally {
setLoading(false);
}
};
return (
<Form
form={form}
name="order_form"
layout="vertical"
onFinish={onFinish}
initialValues={{paymentMethod: 'картой'}}
>
{context}
<Form.Item
label="Идентификатор корзины с товарами"
name="cartId"
rules={[{required: true, message: 'Пожалуйста, введите идентификатор корзины!'}]}
>
<Input type="number"/>
</Form.Item>
<Form.Item
label="Адрес доставки заказа"
name="deliveryAddress"
rules={[{required: true, message: 'Пожалуйста, введите адрес доставки!'}]}
>
<Input.TextArea rows={4}/>
</Form.Item>
<Form.Item
label="Способ оплаты"
name="paymentMethod"
rules={[{required: true, message: 'Пожалуйста, выберите способ оплаты!'}]}
>
<Select>
<Select.Option value="картой">Картой</Select.Option>
<Select.Option value="наличными">Наличными</Select.Option>
</Select>
</Form.Item>
<Form.Item>
<Button type="primary" htmlType="submit" loading={loading}>
Оформить заказ
</Button>
</Form.Item>
</Form>
);
};
export default OrderForm;
Итог
Впервые попробовав такой подход на реальном проекте, я заметила, что использование OpenAPI-спецификации действительно упрощает разработку на начальных этапах. Из неоспоримых преимуществ стоит отметить экономию времени – пара часов на настройку генератора экономит десятки часов разработки за счёт автоматической генерации типов для API и моков на основе спецификации. При этом значительно сокращается количество ошибок из-за строгой типизации. Кроме того, такой подход улучшает командное взаимодействие и уменьшает количество ошибок при интеграции, поскольку фронтенд- и бэкенд-разработчики начинают работать с единой спецификацией.
Однако, существуют и минусы. Например, плохо составленная OpenAPI-схема может привести к некорректно сгенерированным типам или неполным мокам. Также можно столкнуться с ограничениями самого генератора, особенно при работе со сложными сценариями или нестандартными форматами данных. В этом случае требуется ручная доработка и написание собственных шаблонов.
Все методы, описанные в статье, я разберу на бесплатном воркшопе «Работа с OpenAPI: от спецификации до готового решения». Присоединяйтесь, чтобы увидеть реальные примеры, задать вопросы и глубже погрузиться в тему. Подробности и регистрация по ссылке.
Как и любой инструмент, метод требует настройки под ваш проект. Но при грамотном внедрении он становится мощным конкурентным преимуществом для вашей команды. Стоит попробовать!
nin-jin
А где там REST? Там даже ресурсов в спецификации нет - только имена функций, их параметры и возвращаемые значения. Понятное дело, что при должной сноровке можно реализовать REST через RPC, но сама спецификация не про REST вообще.