Полное руководство по созданию готового к эксплуатации приложения с использованием fastify и TypeScript.

TL; DR: репо с полным примером.

Здесь, в car2go, нет каких-либо рамок или технологических ограничений, мы всегда стараемся использовать то, что подходит и лучше всего решает конкретные проблемы вашей команды. В моей команде (серверная часть клиента) наша текущая веб-структура предпочтительна fastify. Мы очень довольны им и можем подтвердить, что это хороший выбор для микросервисных приложений. Но мы всегда верим, что все может быть еще лучше.

Проблема, с которой я, как разработчик, иногда сталкиваюсь, заключается в том, что вернуться к разработке определенного сервиса через какое-то время может быть сложно. Вы просто вне контекста, и вам часто нужно время, чтобы (снова) понять, что там происходит. Рабочее предположение - TypeScript может помочь.

Согласно недавнему обзору Лучшие языки программирования 2018 года (и не только) очевидно, что TypeScript продолжает набирать обороты. Поэтому я решил попробовать TypeScript, ускорить и создать полную интеграцию, которая удовлетворяет мои повседневные потребности:

⚙️ локальная настройка разработки
📚 интеграция с базой данных
🔍 тестирование
🐛 отладка
🤖 развертывание
📋 регистрация ошибок

В этой статье вы узнаете о результатах моих исследований. Давайте разберем эти точки одну за другой.

⚙️ Настройка локальной разработки

Что я понимаю за «настройкой локальной разработки», так это то, что я действительно могу разработать приложение на моем локальном компьютере. Это не должно быть сложно, не так ли?

Давайте запустим проект и установим все зависимости, которые нам понадобятся на этом этапе:

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

Помимо очевидных библиотек, таких как _1 _, _ 2_ и fastify-plugin. Мы также установили секретный соус ts-node. ts-node позволит нам выполнять файлы TypeScript без предварительного этапа сборки. Это как раз то, что нам нужно для развития.

Давайте укажем, как мы хотим использовать TypeScript в нашем проекте, и создадим файл tsconfig.json в корневой папке:

При этом мы, по сути, заявляем, что будем хранить наш код в папке src, при компиляции вывод должен быть помещен в папку dist. Мы хотим скомпилировать его в es2016. Пожалуйста, включите es2016 библиотек при компиляции и создании исходных карт.

Теперь давайте создадим простой fastify сервер src / index.ts:

И объявим наш первый маршрут src / modules / routes / status / index.ts:

Единственная проблема в том, что в fastify типизациях нет определения для fastify-blipp.

Этот небольшой модуль ничего не делает, но печатает конечные точки, которые мы зарегистрировали. В TypeScript мы можем дополнять существующие определения, используя функцию слияния деклараций. Сделаем это в src/@types/augmentation.ts:

Это поможет разобраться во всем. Теперь нам просто нужно настроить дополнительный скрипт в package.json, который запустит наше приложение, давайте добавим туда следующее определение:

После того, как мы сможем запустить наш проект в первый раз: npm run dev.

Мы можем попробовать конечную точку / status, если захотим: curl 0.0.0.0:3000/status.

Это подводит нас к вопросу номер один.

📘 Все изменения, которые были сделаны на этом шаге, можно найти в этом коммите.

📚 Интеграция с базой данных

В примере с базой данных мы будем использовать MongoDb. Представим, что мы хотим разработать простейшее CR приложение, которое будет хранить информацию о автомобилях Mercedes-Benz Formula One.

На этом этапе нам нужно установить несколько дополнительных библиотек:

Наша инфраструктура будет обеспечена с помощью docker compose.

Сначала создадим файл docker-compose.yaml:

С этого момента не забудьте запустить docker-compose up перед запуском нашего приложения.

Теперь давайте определим модель для нашего документа MongoDb src / db / models / vehicle.ts:

Таким образом, информация, которую мы собираемся сохранить, будет содержать year и name автомобиля, а также мы будем динамически добавлять createdDate для каждого документа.

Теперь давайте создадим плагин fastify, который предоставит доступ к нашей базе данных и список моделей через fastify экземпляр сервера src / modules / db / index.ts:

Как видите, наш плагин украшает fastify новым свойством db. Это свойство, в свою очередь, содержит все доступные модели. В верхней части файла мы объявили новые интерфейсы Db и Model. Опять же, согласно определениям по умолчанию, экземпляр сервера fastify не содержит никакого свойства с именем db, поэтому давайте снова воспользуемся расширением и обновим src/@types/augmentation.ts:

Теперь пора объявить новые маршруты, которые фактически вставят новое значение в базу данных и прочитают его оттуда, src / modules / routes / cars / index.ts:

Последний шаг - соедините все вместе с помощью `fastify` и протестируйте его вручную. В src / index.ts добавьте, пожалуйста, следующую часть:

Вот результаты, давайте запустим:

И ручной тест:

Интеграция с базой данных налажена, поехали дальше.

📘 Все изменения, которые были сделаны на этом шаге, можно найти в этом коммите.

🔍 Тестирование

В нашей команде jest - это тестовый раннер и библиотека утверждений. Заставить jest работать вместе с TypeScript относительно легко.

Установим новые зависимости:

И создайте соответствующий jest.config.js:

Наконец, обновим наш test скрипт в package.json:

Вот и все, теперь мы можем добавить простой тест, который мы также пишем с использованием TypeScript, src / __ tests __ / simple.test.ts:

Вот и все, теперь мы можем «протестировать» наши тесты с npm test.

Вот результаты:

📘 Все изменения, которые были сделаны на этом шаге, можно найти в этом коммите.

🐛 Отладка

Важно иметь возможность отлаживать свое приложение. Не та отладка, где вы (и я) поместили десятки console.log и как то на этот раз он что-то выведет. Но тот, где вы устанавливаете точку останова, и приложение останавливается на нем и подождите, пока вы не подумаете, как оно там оказалось.

Лично я использую Visual Studio Code в качестве IDE, поэтому мои примеры будут работать там.

отлаживать все приложение

Иногда нужно запустить приложение и проверить, что внутри. Вот подходящая конфигурация отладки для VS Code:

Что мне нравится в нем, так это то, что в нем используется ts-node и нет этапа сборки. Вот короткое видео, в котором показан процесс отладки:

отладить конкретный тест

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

Поэтому давайте явно добавим этап сборки в наши скрипты package.json:

Теперь мы вернулись к определению конфигурации отладки. Сначала нам нужно определить задачу в .vscode / tasks.json:

И в качестве второго шага определите новую конфигурацию отладки в VS Code, вот определение:

Как видите, сначала он соберет проект. Для успешной отладки проект, а не тесты, должен быть построен и доступен в dist.

Для этого необходимо обновить исключаемую часть tsconfig.json:

Обратите внимание, что файл, который вы собираетесь отлаживать, должен быть открыт в вашем редакторе, поскольку мы используем `$ {relativeFile}` в определении конфигурации отладки. Вот короткое видео, в котором показан процесс отладки теста:

📘 Все изменения, которые были сделаны на этом шаге, можно найти в этом коммите.

🤖 Развертывание

Я специально поставил «развертывание» перед «журналированием ошибок». Основная причина заключается в том, что при разработке мы используем ts-node, а ts-node будет создавать правильные трассировки стека .ts, как это предусмотрено. Итак, сначала давайте посмотрим, как мы можем создать наше приложение и подготовить его к производственному использованию.

Первое изменение, которое нам нужно сделать на этом этапе, - сделать наше приложение настраиваемым. В настоящее время адрес MongoDb жестко запрограммирован, но нам нужно, чтобы он был динамическим, поэтому для «локальной» разработки у нас есть один, а для «производственной» - другой.

Установим новые зависимости:

Создайте два файла конфигурации для хранения строки подключения:

config / default.yaml

config / production.yaml

Теперь нам нужно обновить src / index.ts, чтобы использовать config вместо жестко запрограммированной строки:

Поскольку мы собираемся запускать наше приложение из папки dist, давайте обновим наш package.json новым скриптом:

К счастью, в настоящее время мы не выполняем развертывание на «голом железе». Обычно мы развертываем у одного из причудливых облачных провайдеров или в Kubernetes. Итак, по сути, мы не развертываем приложения Node.js или TypeScript. Развертываем докер-контейнеры.

Давайте определим один для нашего приложения, основное отличие от обычного контейнера Node.js в том, что во время сборки образа есть дополнительный этап «сборки», Dockerfile:

Мы почти подошли к концу, давайте создадим новый файл Docker Compose для имитации производственного развертывания. Этот файл будет содержать как нашу службу, так и службу MongoDb, docker-compose.production.yaml:

Теперь давайте запустим его с docker-compose -f docker-compose.production.yaml up и проверим, что наш сервис работает.

Docker Compose может успешно запускаться:

Наш сервис жив и здоров:

Давайте перейдем к последнему пункту нашего путешествия.

📘 Все изменения, которые были сделаны на этом шаге, можно найти в этом коммите.

📋 Регистрация ошибок

Как вы знаете, с TypeScript будет выполняться не написанный вами код. Перед фактическим выполнением ваши файлы .ts компилируются в старые добрые файлы .js, и они будут выполнены Node.js. Поэтому, когда в вашем приложении возникнет ошибка времени выполнения - трассировка стека будет ссылаться на код, который выполняется. Это не очень помогает во время вашего расследования и попыток исправить эту проблему.

Давайте определим новый маршрут, который выдаст ошибку, и протестируем его с помощью нашей «производственной» docker-compose.

src / modules / routes / error-thrower / index.ts:

Зарегистрируйте этот маршрут в src / index.ts:

Давайте перестроим образы и снова запустим рабочую версию Docker Compose:

Вот часть ошибки из вывода Docker Compose после того, как мы нажали / error-thrower:

Как видите - он указывает на папку dist.

Давайте сделаем так, чтобы он ссылался на реальный код, который мы написали. Это возможно с помощью модуля под названием source-map-support.

Установите новую зависимость:

Интегрируйте его прямо в начало src / index.ts:

Протестируйте / error-thrower, как мы это делали раньше. На этот раз ошибка:

Бьюсь об заклад, вы видите разницу. Теперь вы готовы к отладке сразу после того, как увидели трассировку стека ошибок.

📘 Все изменения, которые были сделаны на этом шаге, можно найти в этом коммите.

Заключение

С моей точки зрения - в основном это было. Конечно, есть над чем работать, например, мы не собираемся разрабатывать ни одно приложение без надлежащего линтера, не так ли? Но сегодня мы заложили прочную основу для реального сервиса, готового к производству.

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

Спасибо, что терпел меня до конца! Я с нетерпением жду вашего опыта использования fastify и TypeScript. Пожалуйста, поделитесь этим в комментариях ниже.