Начало работы с Hummingbird

от автора

От автора: Я до сих пор помню конец 90-х, когда установил на свой компьютер Internet Information Services. Это позволило мне запускать страницы Classic ASP, подключенные к базе данных Microsoft SQL Server. Так я впервые познакомился с серверной разработкой.

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

За годы работы я успел познакомиться с различными серверными технологиями, включая ASP.NET Web Forms, ASP.NET MVC, ExpressJS, Flask, Vapor, а теперь и Hummingbird.

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

Что такое Hummingbird?

Hummingbird — это легковесный веб-фреймворк для создания серверных приложений на языке Swift. Он ориентирован на простоту, производительность и предоставляет полный контроль над серверным кодом. В отличие от более тяжелых фреймворков, Hummingbird не прячет многое за абстракциями. Он с самого начала поддерживает асинхронность и ожидание в Swift, благодаря чему написание параллельного кода кажется естественным и простым. Если вы уже разбираетесь в основах серверной разработки, таких как маршрутизация, обработка запросов и работа с базами данных, вам будет легко освоить Hummingbird.

Почему Hummingbird? Почему не Vapor?

Дело не в том, что один из них лучше другого. Дело в том, что для вас важнее как для разработчика.

Hummingbird — отличный выбор, если вам нужно что-то лёгкое и максимально приближенное к тому, как Swift работает сегодня. Он с самого начала поддерживает async/await и не прячет детали за множеством абстракций. Вы сами пишете большую часть кода, но взамен получаете ясность и контроль. Если вы уже разбираетесь в основах бэкенда, Hummingbird покажется вам очень естественным выбором.

С другой стороны, Vapor — более зрелый и полнофункциональный фреймворк. Он предоставляет множество готовых функций, таких как аутентификация, объектно-реляционное отображение, промежуточное ПО и хорошо развитую экосистему. Это отличный вариант, если вы хотите работать быстро или создавать производственные системы, не изобретая велосипед.

С другой стороны, иногда кажется, что Vapor работает медленнее. Он был создан до появления современной модели параллелизма в Swift, поэтому некоторые его части скорее адаптированы, чем изначально разработаны с учетом async/await.

Если вам нужен контроль, простота и фреймворк, максимально приближенный к современному Swift, выбирайте Hummingbird. Если вам нужна полноценная экосистема с готовыми библиотеками и минимальной настройкой, то Vapor — отличный выбор.

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

Создание вашего первого проекта Hummingbird

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

Для начала клонируйте репозиторий шаблонов на свой компьютер:

git clone https://github.com/hummingbird-project/template

После загрузки шаблона вы можете использовать его для создания своего проекта. Запустите скрипт установки с помощью следующей команды:

./template/configure.sh MyNewProject

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

После создания проекта перейдите в папку MyNewProject и запустите:

swift run

Это позволит собрать и запустить ваш сервер. Первая сборка может занять несколько минут, так как Swift Package Manager необходимо загрузить и скомпилировать зависимости.

Когда все будет готово, откройте браузер и перейдите по адресу 127.0.0.1:8080. Вы увидите простой ответ «Hello», подтверждающий, что ваш сервер Hummingbird запущен и работает.

Понимание начального шаблона

Вы можете открыть свой проект Hummingbird в любом удобном для вас редакторе. Если вы хотите использовать Xcode, просто запустите open Package.swift из папки проекта. Это откроет проект в Xcode и автоматически разрешит и загрузит все необходимые зависимости.

В папке Sources/App находится файл App.swift. Этот файл содержит основную функцию, которая служит точкой входа в ваше приложение. Здесь начинается выполнение вашего приложения, и эта функция отвечает за настройку конфигурации, сборку приложения и запуск сервера. Код основной функции приведен ниже:

@mainstruct App {    static func main() async throws {        // Приложение будет считывать конфигурацию из следующего списка в указанном порядке        // Командная строка, переменные среды, файл dotEnv, значения по умолчанию, указанные в памяти        let reader = try await ConfigReader(providers: [            CommandLineArgumentsProvider(),            EnvironmentVariablesProvider(),            EnvironmentVariablesProvider(environmentFilePath: ".env", allowMissing: true),            InMemoryProvider(values: [                "http.serverName": "MyNewProject"            ])        ])        let app = try await buildApplication(reader: reader)        try await app.runService()    }}

Функция main является точкой входа в ваше приложение Hummingbird и отвечает за три основные задачи: чтение конфигурации, сборку приложения и запуск сервера.  Атрибут @main сообщает Swift, где начинается программа, а сигнатура async throws позволяет приложению выполнять асинхронную работу и корректно обрабатывать ошибки, что соответствует принципам построения Hummingbird на основе модели async/await в Swift.

Первая часть функции создает ConfigReader, который используется для загрузки значений конфигурации вашего приложения.  Эти значения могут включать в себя такие параметры, как имя сервера, порт или настройки среды. Преимущество этого подхода в том, что Hummingbird считывает конфигурацию из нескольких источников в определенном порядке: аргументы командной строки, переменные среды, .env-файл и, наконец, значения по умолчанию в памяти.  Это означает, что вы можете легко переопределить значения в зависимости от того, как вы запускаете приложение.  Например, значение, указанное в командной строке, будет иметь приоритет над тем же значением, указанным в .env-файле.

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

Наконец, app.runService() запускает сервер и начинает прослушивать входящие HTTP-запросы.  Теперь ваше приложение полностью готово к работе и может обрабатывать запросы от браузера или любого другого клиента.

Следующий файл — App+Build.swift. Ниже приведен полный код:

import Configurationimport Hummingbirdimport Logging// Контекст запроса, используемый приложениемtypealias AppRequestContext = BasicRequestContext///  Build application/// - Parameter reader: configuration readerfunc buildApplication(reader: ConfigReader) async throws -> some ApplicationProtocol {    let logger = {        var logger = Logger(label: "MyNewProject")        logger.logLevel = reader.string(forKey: "log.level", as: Logger.Level.self, default: .info)        return logger    }()    let router = try buildRouter()    let app = Application(        router: router,        configuration: ApplicationConfiguration(reader: reader.scoped(to: "http")),        logger: logger    )    return app}/// Build routerfunc buildRouter() throws -> Router<AppRequestContext> {    let router = Router(context: AppRequestContext.self)    // Добавляем middleware    router.addMiddleware {        // logging middleware        LogRequestsMiddleware(.info)    }    // Добавляем стандартный endpoint    router.get("/") { _,_ in        return "Hello!"    }    return router}

Эта часть кода отвечает за создание вашего приложения и определение того, как оно обрабатывает входящие запросы. Здесь находится большая часть серверной части вашего приложения.

Функция buildApplication принимает ConfigReader в качестве входных данных и возвращает экземпляр вашего приложения.  Первое, что она делает, — настраивает логгер.  Логгер создается с использованием системы Swift Logging, а уровень ведения журнала считывается из конфигурации.  Это значит, что вы можете контролировать объем выводимой информации (отладка, информация, ошибка), не меняя код, а просто обновляя значения в конфигурации.

Далее функция вызывает buildRouter(), где определены все ваши маршруты и промежуточное ПО. Представьте, что маршрутизатор — это часть вашего приложения, которая определяет, как реагировать на запросы по разным URL. После создания маршрутизатора он передается в Application вместе с конфигурацией и логгером. Конфигурация ограничена областью "http", то есть в ней будут использоваться только настройки, связанные с HTTP, из ваших источников конфигурации.

Функция buildRouter определяет поведение вашего приложения.  Она начинается с создания маршрутизатора с контекстом запроса, в данном случае это BasicRequestContext.  Этот контекст содержит информацию о каждом входящем запросе.  Затем к маршрутизатору добавляется промежуточное ПО.  В этом примере используется промежуточное ПО для логирования, которое записывает в журнал каждый входящий запрос, что полезно для отладки и мониторинга.

Наконец, с помощью router.get("/"). определяется простой маршрут. Это означает, что при переходе пользователя по корневому URL (/), сервер ответит "Hello!". Это ваша первая конечная точка, и она показывает, насколько просто определять маршруты в Hummingbird.

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

Теперь измените маршрут так, чтобы он возвращал Hello World вместо просто Hello. Если вы обновите страницу в браузере по адресу 127.0.0.1:8080, то увидите, что вместо Hello по-прежнему отображается Hello World.

Чтобы это сработало, нужно остановить сервер Control C и снова запустить его swift run. Теперь при переходе по маршруту вы увидите обновленную информацию.

Это работает, но может сильно раздражать, если вам приходится перезапускать сервер каждый раз, когда вы вносите небольшое изменение. А что, если бы сервер запускался автоматически при обнаружении изменений в любом файле Swift?

Автоматический перезапуск сервера с помощью watchexec

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

Такого же поведения можно добиться в проектах Hummingbird с помощью инструмента под названием watchexec. Он отслеживает ваши файлы и перезапускает команду при обнаружении изменений.

Чтобы установить watchexec, выполните следующие действия:

brew install watchexec

После установки перейдите в папку с проектом Hummingbird и запустите:

watchexec -e swift --restart swift run

Эта команда указывает watchexec отслеживать изменения в файлах Swift и автоматически перезапускать сервер с помощью команды swift run.

Эта небольшая настройка может сэкономить вам много времени. Вместо того чтобы постоянно перезапускать сервер вручную, вы можете сосредоточиться на написании кода и сразу видеть, как изменения отражаются на работе. Для меня watchexec стал незаменимым инструментом при работе над бэкенд-проектами.

Заключение

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

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

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

ссылка на оригинал статьи https://habr.com/ru/articles/1024758/