В этой статье я постараюсь ознакомить вас с возможностями веб разработки на языке программирования 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}

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

В шаблоне к кнопке привязали изменение списка и перерисовку.

Конечный результат можете увидеть ниже:

Конечный результат TODO app
Конечный результат TODO app

Дополнительные Ссылки

Комментарии (8)


  1. flander
    18.07.2023 02:32

    Интересная статья. Никогда раньше не слышал об этом языке. На сколько могу судить, он вроде не совсем популярный, никогда не видел даже вакансий, но при этом он довольно-таки с простым синтаксисом и низким порогом входа.


    1. akihayase Автор
      18.07.2023 02:32

      А ещё он компилируется в C и JS :)


  1. nin-jin
    18.07.2023 02:32
    -1

    А нормально с css работать нельзя? А отделять композицию от лог!ки? А реактивно связывать состояния?


    1. akihayase Автор
      18.07.2023 02:32
      +1

      Все это можно делать :)


    1. akihayase Автор
      18.07.2023 02:32
      +2

      касательно CSS - просто берете и пишите голый CSS


      1. nin-jin
        18.07.2023 02:32
        -2

        Почему бы не показать сразу хороший пример, а не говнокод?


        1. akihayase Автор
          18.07.2023 02:32
          +2

          хорошо, как бы Вы описали хороший код на Nim?


          1. nin-jin
            18.07.2023 02:32
            -2

            Это вы нам покажите хороший код.