Создание VueJS компонента
Введение
Мне очень нравится идея маленьких переиспользуемых компонент. Если передо мной встаёт задача добавить какой-нибудь функционал, я прежде всего трачу некоторое время на поиск уже существующего решения. Так и в этот раз. Немногие знают, что r2cloud - это полноценный REST сервер. А значит им можно управлять программно. Сейчас существует только один клиент для него - r2cloud-ui. Это приложение VueJS, которое предоставляет UI для управления. Однако, вся мощь REST сервисов заключается в том, что с ними можно взаимодействовать программно с помощью различных языков программирования. Это позволяет построить достаточно интересные интеграции и более сложные системы. Чтобы рассказать всему миру о том, как можно управлять r2cloud, я решил создать API документацию.
Самый простой создания документации - это записать все REST методы в html файл и добавить на сайт. Однако, за последние десятки лет, инженерная мысль шагнула дальше. Если описать REST API с помощью специальной схемы OpenAPI, то на её основе можно:
- Сгенерировать документацию
- Сгенерировать клиентскую библиотеку под различные языки программирования
- Сгенерировать заглушку для серверного кода
Второй и третий пункт у меня уже есть, а вот первый пункт мне как раз и нужен. Таким образом передо мной встала задача отрисовать спецификацию OpenAPI в VueJS.
{
"/health": {
"get": {
"tags": [
"System"
],
"summary": "Check if r2cloud is up",
"responses": {
"200": {
"description": "If r2cloud is up"
}
}
}
}
}
Покопавшись немного в интернете я нашёл следующие наиболее близкие решения:
- swagger-ui. Стандартная библиотека, позволяющая отрисовать спецификацию OpenAPI с помощью собственных стилей и Javascript.
- vue-openapi. Позволяет отрисовать спецификацию OpenAPI с помощью библиотеки стилей vue-material.
В обоих случаях используются собственные стили компонентов. Эти стили не сочетаются с bootstrap, поэтому я решил написать небольшой компонент - vue-openapi-bootstrap. Он позволяет:
- отрисовывать спецификацию OpenAPI 3.x
- UI максимально близко повторяет стандартный swagger-ui
- использует нативные компоненты из bootstrap 4.x и динамические компоненты из bootstrap-vue
- отображает запросы и ответы API в формате json
- улучшенное отображение доменных моделей
Создание компонента
Создание однофайлового компонента очень хорошо описано в официальной документации. В этой статье предлагается делать сборку компонента с помощью rollup. Насколько я понял, это ещё один способ сборки javascript кода, более легковесный, чем webpack. Из недостатков следует отметить отсутствие dev сервера и горячей перезагрузки модулей.
После того как написан весь boilerplate код и конфигурация сборки, написание компонента не представляет сложности. В случае моего компонента, мне удалось найти практически все стандартные компоненты bootstrap, которые позволили отобразить UI, похожий на swagger-ui.
<b-card-body>
<p v-if="method.deprecated" class="text-muted">Warning: Deprecated</p>
<p v-if="method.description">{{ method.description }}</p>
<div v-if="method.parameters && method.parameters.length > 0">
<h4>Parameters</h4>
Почему я выбрал UI совместимый со swagger-ui? Во-первых, у меня нет мнения о том, как должен выглядеть правильный UX для описания документации к API. А во-вторых, swagger-ui - это наиболее распространённый компонент для отображения OpenAPI документации.
Наибольшая сложность была с описанием того, что есть в стандарте OpenAPI 3.x. Дело в том, что стандарт позволяет достаточно гибко описывать различные REST API. А это значит, что он достаточно обширен и многословен. Чтобы всё это описать, я взял стандартный openapi.json из petstore и отрисовал всевозможные варианты конфигурации.
Финальный результат
Готовый компонент можно подключить следующим образом:
npm install vue-openapi-bootstrap
Использовать на странице:
<template>
<vue-openapi-bootstrap :openapi="openapi"></vue-openapi-bootstrap>
</template>
<script>
import vueOpenapiBootstrap from 'vue-openapi-bootstrap/src/vue-openapi-bootstrap'
export default {
components: {vueOpenapiBootstrap},
data () {
return {
openapi: {}
}
}
}
</script>
В результате получаются такие страницы:
А вот так выглядит отображение документации в r2cloud-ui:
Сразу после публикации в npmjs.com в первые несколько дней, мой компонент был скачан 66 раз. Это лишний раз подтвердило мою мысль о том, что я на правильном пути и небольшой компонент востребован сообществом.
Выводы
- VueJS продвигает создание небольших переиспользуемых компонент. Это очень мощная и правильная идея, которая позволяет собирать достаточно большие проекты из маленьких кусочков. Правильная реализация этой идеи делает создание компонентов действительно простым делом.
- npmjs продвигает переиспользование кода. Как ещё объяснить те 66 скачиваний моего компонента, если я не давал рекламы и никому о нём не рассказывал?
- Компонент есть куда улучшать: можно добавить поддержку отрисовки описаний с помощью markdown, задание доменной модели с помощью xml.