Прежде чем перейти к статье, хочу вам представить, экономическую онлайн игру Brave Knights, в которой вы можете играть и зарабатывать. Регистируйтесь, играйте и зарабатывайте!
В этой статье я постараюсь ознакомить вас с возможностями веб разработки на языке программирования Nim.
На данный момент в Nim можно выделить 2 основных веб-фреймворка: Jester и Karax. Однако Jester используется только для серверной разработки, а Karax для клиентской. Поэтому рассказывать о них я не стану, однако я расскажу о другом замечательном фреймворке - HappyX.
Что Такое HappyX?
По своей сути HappyX это macro-oriented full-stack веб фреймворк. И главной его особенностью является как раз "макро-ориентированность", то есть он ориентирован на метапрограммирование (как в C++ или Rust, но лучше). Это означает, что выполнение большинства вещей происходит на этапе компиляции.
Как же выглядит банальный "Hello, world" в HappyX? Вот пример того, как это выглядит на серверной части:
import happyx
serve("127.0.0.1", 5000):
"/":
"Hello, world!"
Довольно просто, да?
Благодаря метапрограммированию HappyX предоставляет разработчику DSL (Domain-specific language). Это позволяет не тратить лишнее время на написание бойлерплейта.
Я показал этот пример для серверной части, но как же "Hello, world" выглядит в клиентской части? Это выглядит следующим образом:
import happyx
appRoutes("app"):
"/":
"Hello, world!"
Напоминает предыдущий пример, не так ли? Единственное отличие от предыдущего примера - третья строка.
И что же теперь, мы можем просто поменять эту самую третью строчку и поменять весь код с условного бекенда на условный фронтенд?
Да. Почти. Помимо этого вам придется использовать немного другую команду для запуска приложения.
Однако здесь не все так просто, ведь некоторые вещи серверной части не могут работать на клиентской. Также и наоборот.
Установка
Для того, чтобы работать с HappyX вам необходимо установить Nim и, собственно, сам HappyX.
После установки Nim можно установить HappyX с помощью пакетного менеджера nimble (поставляется вместе с Nim).
nimble install happyx@#head
Вот и все, теперь мы можем переходить непосредственно к самой разработке.
Разработка TODO Приложения
Разрабатывать TODO list будем на клиентской стороне. И так, создадим сам проект
hpx create --name todo_app --kind SPA --use-tailwind
Этой командой мы создали проект todo_app
типа single page application. Флаг --use-tailwind
указывает на то, что мы будем использовать Tailwind CSS (через cdn).
В файле todo_app/src/main.nim
можем видеть следующий код:
# Import HappyX
import
happyx,
components/[hello_world]
# Declare application with ID "app"
appRoutes("app"):
"/":
# Component usage
component HelloWorld
Здесь мы импортируем сам фреймворк, затем компонент HelloWorld
. Далее объявляем наше одностраничное приложение и указываем на то, что оно будет рендериться в элементе с ID = "app"
. Далее, по пути нашсайт/#/
мы будем видеть содержимое компонента HelloWorld.
В файле todo_app/src/components/hello_world.nim
видим следующее:
# Import HappyX
import happyx
# Declare component
component HelloWorld:
# Declare HTML template
`template`:
tDiv(class = "someClass"):
"Hello, world!"
`script`:
echo "Start coding!"
Здесь мы также импортируем фреймворк. Это необходимо для работы с ним. Затем объявляем компонент HelloWorld
, а также указываем в его шаблоне псевдо-HTML.
В скрипте мы можем использовать обычный Nim код. Он будет срабатывать при каждом изменении компонента.
Переименуем наш компонент в TodoItem
, а файл в todo_app/src/components/todo_item.nim
:
# Import HappyX
import happyx
# Declare component
component TodoItem:
Теперь поменяем содержимое компонента. Результат у меня получился такой:
# Import HappyX
import happyx
# Declare component
component TodoItem:
checked: bool = false
# Declare HTML template
`template`:
if self.checked:
tDiv(class = "flex items-center bg-green-200 rounded-md px-4 py-1 cursor-pointer select-none"):
slot
@click:
self.checked = not self.checked
else:
tDiv(class = "flex items-center bg-red-200 rounded-md px-4 py-1 cursor-pointer select-none"):
slot
@click:
self.checked = not self.checked
`script`:
echo "Start coding!"
Здесь мы добавили поле checked
, которое отвечает за то, выполнена задача или нет. Также мы поменяли шаблон на основе этого поля, а еще мы обрабатываем нажатие, которое меняет значение компонента и перерисовывает его.
Теперь поменяем todo_app/src/main.nim
следующим образом:
# Import HappyX
import
happyx,
components/[todo_app]
var tasks = remember @[
"Написать статью на Хабре",
"Поделиться ей с друзьями"
]
# Declare application with ID "app"
appRoutes("app"):
"/":
tDiv(class = "flex flex-col p-8 w-fit gap-2"):
tDiv(class = "flex rounded-md bg-gray-200 gap-2"):
tInput(id = "taskName", class = "px-2 bg-transparent", placeholder = "Напишите что-нибудь")
tButton:
"+"
@click:
var data = document.getElementById("taskName").value
if ($data).len > 0:
tasks->add($data)
app.router()
for task in tasks:
# Component usage
component TodoItem:
{task}
Здесь мы импортировали переименованный компонент, далее создали список из задач, затем поменяли шаблон.
В шаблоне к кнопке привязали изменение списка и перерисовку.
Конечный результат можете увидеть ниже:
Дополнительные Ссылки
Репозиторий HappyX
Туториал по написанию RestAPI на HappyX
Документация HappyX