Все записи с тэгом dev

Реактивность вместо ручной работы с DOM: те же задачи на чистом JS и на Micra

·

На чистом JS интерактив делается руками: находишь элемент и меняешь его — переключаешь класс, ставишь атрибут, вписываешь текст. Для одной кнопки так и надо.

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

Реактивность меняет направление. Ты не проталкиваешь изменения в DOM по шагам — ты описываешь, что от чего зависит, и трогаешь только состояние. DOM подстраивается сам. Micra — небольшая библиотека ровно про это, поверх готового серверного HTML. Она ничего не заменяет и ни на что не претендует, просто закрывает нишу, где сервер уже отдал разметку, а на клиенте нужно немного интерактива.

Ниже — несколько одинаковых задач, каждая дважды: на чистом JS и на Micra. Разница в строчках будет, но интереснее другое — момент, когда ручная слежка за DOM перестаёт окупаться.

Читать далее →

Micra + htmx: HTML по проводу и локальное состояние рядом

·

Вчера релизнул версию 2.7.0 Микры и изменения были связаны с улучшенной работой с htmx. По этому поводу и статья.

htmx и Micra.js хорошо уживаются на одной странице, потому что отвечают за разное. htmx приносит готовый HTML с сервера в ответ на действие — клик, сабмит, таймер. Micra держит на этом HTML состояние, которое серверу знать незачем: открыт ли дропдаун, что набрано в неотправленном поле, какая вкладка активна. Это живёт в браузере, и запрос ради этого не нужен.

Чем хорош htmx

Серверный UI браузер умел всегда, но только через два элемента: ссылка шлёт GET, форма — GET или POST, и ответ в обоих случаях заменяет страницу целиком. htmx распространяет ту же механику на всё остальное — запрос может слать любой элемент по любому событию любым HTTP-методом, а ответ заменяет не страницу целиком, а указанный кусок DOM.

Читать далее →

Почему я сделал Micra

·

Я помню время, когда jQuery стоял почти на каждом сайте. Тогда еще не было фреймворков и jQuery был простым способом дотянуться до DOM: навесить обработчик, что-то показать, что-то спрятать, дёрнуть запрос. Тогда это решало большинство задач. Потом фронтенд стал сложнее. Во многом по делу, потому что приложения выросли, и React, Vue, Svelte выросли вместе с ними. Но такая сложность нужна не всегда.

Осталось много проектов, где сервер уже отдаёт готовую HTML-разметку, а на клиенте требуется лишь немного реактивности: открыть модалку, обновить счётчик, отфильтровать таблицу, переключить вкладку. Разворачивать ради этого полноценный фреймворк со сборкой и роутингом часто не хочется. А писать на чистом JavaScript быстро становится неудобно, когда нужно отслеживать состояние и синхронизировать его с DOM.

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

Читать далее →

Micra.js под капотом: как устроен реактивный фреймворк

·

Это длинный текст про то, как изнутри устроена Micra.js — маленькая библиотека, которая добавляет реактивность к HTML, отрендеренному на сервере. Я написал её, чтобы закрыть конкретную нишу: страницы и админки, где сервер уже отдаёт готовую разметку, а на клиенте нужно лишь немного интерактивности — переключить вкладку, открыть модалку, отфильтровать таблицу, сходить за данными. Раньше для этого тянулись к jQuery, потом к Alpine. Micra — это попытка дать тот же «сахар», но предсказуемо, типизированно и с учётом Content-Security-Policy.

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

Читать далее →

Релиз Micra.js 2.5.0

·

Пару недель назад я писал, что у библиотеки появился второй читатель — языковая модель. Тогда я думал, что главная задача — научить LLM правильно её готовить. Но потом решил, что не менее полезно послушать, что LLM думает о самой библиотеке.

Я скормил llms.txt другой модели и попросил разобрать: чего не хватает «идеальному фреймворку для тех, кому React — оверхед». Часть идей взял на заметку. Примерно тогда же я доводил до конца PR с Micra в js-framework-benchmark — один из самых авторитетных бенчей JS-фреймворков, где рядом React, Vue, Svelte, Solid и другие. При ревью этого PR его автор указал на проблему, которая пересеклась с одним из пунктов от модели.

Читать далее →

Micra.js, две недели спустя

·

В прошлой заметке я выложил Micra.js — маленький реактивный фреймворк для server-rendered страниц. Дальше пошли две недели, за которые я выпустил несколько версий.

Добавил в Micra кросс-библиотечный бенчмарк. Постарался сделать честную страницу, где Micra, Alpine, petite-vue, Stimulus и голый ванильный JS гоняют одни и те же сценарии в соседних фреймах.

Цифры оказались приятно-неприличными. Обновить 5 строк в списке из 1000:

— Micra — 0 мс
— Alpine.js — 919 мс
— petite-vue — 1005 мс

Читать далее →

Micra.js — лёгкий реактивный фреймворк для простых сайтов

·

Я помню время когда jQuery был UI-библиотекой для работы с DOM по умолчанию. Потом появился Knockout.js, Backbone.js и так мы дошли до React/Vue/Svelte. Фронтенд стал сложнее. Но такая сложность нужна не всегда. В мире всё ещё существуют простые сайты, состоящие из нескольких страниц, небольшие SaaS, панели управления и блоги. Часто таким решениям не требуется большой и сложный фронтенд. И в этом случае тоже приходится думать с помощью какого инструмента решать задачу создания интерфейса. В своих проектах я пробовал разные подходы — от Vanilla.js до React-а и всё пытался подобрать удобное решение, позволяющее совместить в себе реактивность и возможности взаимодействия с DOM и поддержку серверного рендеринга. А еще для простых сайтов не хочется тянуть кучу зависимостей. Иногда достаточно просто подключить библиотеку извне.

Так в ходе поиска баланса я набросал Micra.js — небольшую UI библиотеку на 5 Kb. Она имеет свои плюсы и минусы, абсолютно неуникальна и не претендует на звание заменителя всех других библиотек. Скорее это сборник практик, которые сформировались в единое решение.

Что это и как работает

Micra.js — это лёгкий реактивный фреймворк, который работает через shallow‑Proxy, отслеживая только верхний уровень state. Любое изменение top‑level свойства вызывает ререндер, а вложенные объекты нужно заменять целиком. Все синхронные обновления состояния батчатся в один microtask, поэтому несколько записей приводят к одному ререндеру. При первом рендере Micra сканирует DOM, собирает директивы (data-text, data-if, data-model и др.) и кэширует их, чтобы последующие обновления были быстрыми и не требовали повторного обхода дерева.

Выражения в директивах выполняются через быстрый путь для простых обращений к свойствам или через компиляцию с глобальным кэшем для сложных выражений. Внутри выражений доступен расширенный exprState, включающий методы компонента и хелперы (prop, emit, fetch). Списки с data-each и data-key обновляются через keyed‑diff: переиспользуются существующие DOM‑ноды, создаются только новые, а исчезнувшие удаляются. Каждый data-component создаёт независимый инстанс со своим состоянием, методами, props из data-* и собственным жизненным циклом. Компоненты общаются через event bus, а доступ к конкретному экземпляру возможен через Micra.instances().

Как видите, ничего нового и уникального. Некоторые решения компромиссны. Например, проксирование top-level. Для решений типа "показать модалку", "отфильтровать таблицы" выглядит достаточно. Меньше багов, выше производительность, так как нет лишних обходов. Но я не исключаю, что позже приду необходимости deep‑proxy.

В то же время, я собрал сборник рецептов и набор компонентов, которые можно копировать и использовать. В качестве эксперимента, хочу попробовать обучить AI использовать Micra.js в качестве замены React. Задачка, конечно, требует времени, потому что кодовая база с React огромна. В то же время, это не всегда играет на руку. Примеры кода могут быть и хорошими и плохими и корректировка достигается с помощью правильный скиллов и гайдлайнов. И я думаю, что если это можно сделать с одной библиотекой, то можно и с другой.

Нельзя просто взять и сгенерировать тему

·

В рамках работы над open-source проектом работал над задачкой по генерации тем. То есть в проекте было несколько тем: одни темы имели светлый и темный режим, другие - только светлый или только темный. И задача сводилась к тому, чтобы сделать для всех тем светлый и темный режим.

20260429_090506_ae78eb.webp

Вот на скриншоте показаны несколько темных тем: Dracula, Solarized, Gruvbox, Monokai, Moonlight. В теории можно взять и инвертировать светлоту, получив тем самым светлую тему. В теории теория и практика не отличаются. На практике всё совсем наоборот 😀. Чтобы объяснить почему, полезно сначала посмотреть на то, как устроена работа с цветом в принципе.

Читать далее →

Про подключение Garmin MCP к Claude Code и забег в Бечее

·

На днях с подачи приятеля подключил Garmin MCP к Claude Code. Опыт интересный. В первую очередь, потому что все эти данные мне и так известны и доступны в виде сухой статистики в Garmin Connect. Хотелось попробовать новый опыт взаимодействия.

20260328_202912_0a7bbc.webp

Читать далее →

TrueNorth для ясности в делах

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

20260118_132929_a4d078.webp
TrueNorth Dashboard

Читать далее →