@minima-dev/minima-js
v0.1.63
Published
Minima is a small, fast and simple reactive UI framework with DI-container out of the box (798ms for 1million updates)
Downloads
10,199
Maintainers
Readme
Minima
Note [1]
Hello, it's @minima-dev. I was testing the package for personal uses only and didn't expect any downloads. Sorry, if my previous versions didn't work, they were experimental. I don't drop the project on a halfway. So I hope you will continue use Minima from now on. Please, use versions from at least 0.1.17/ Please do not use 0.1.19, 0.1.20. Thank you for downloading my package! Much love from @minima-dev!
Note [2]
The English/Russian documentations will update along each other, in order to not miss a important update!
English documentation
630 LoC. 80ms for 1 million updates. No-VDOM solution.
Minima is a minimalistic frontend framework with reactive state, DI-container out of the box and swift DOM-updates by assigning URL-address for every node. The solution doesn't use Virtual DOM, doesn't need compilation shenanigans and outperforms React by ~1.4x-10x in benchmarks.
No React, Vue, Svelte or Solid. Minima is written from scratch as an instrument for high-performance UI applications.
Feautures
- ⚡ Swift performance
1 000 000 sync update for about 80 ms - 📦 Minimal size
The whole solution is 630 LoC compiled JavaScript (~3 KB gzip) - 🧩 Component approach
JSX-syntax, effect and state decorators - 🎯 Update by URL
Every node has URL like/div[0]/span[0] - 🧠 FIOI-scheduler
Batching byrequestAnimationFramewith philosophy "Flushing Independent of Instance" (FIOI) - 🧬 Auto-collecting dependencies in effects
@Effectderives its dependencies from usage - 🏗 Out of the box DI-container
@Injectfor dependency injection - 🖼 Two backends for rendering
DOM and Canvas out of the box - 📍 ContextProvider + fabric
Via attributefabricand jsx-tagContextProvider
🚀 Swift start
npm i @minima-dev/minima-jsBarebone tsconfig.json
{
"compilerOptions": {
"jsx": "react",
"outDir": "./dist",
"noImplicitAny": false,
"module": "esnext",
"moduleResolution": "bundler",
"experimentalDecorators": true,
"emitDecoratorMetadata": true,
"useDefineForClassFields": false,
"rootDir": ".",
"allowSyntheticDefaultImports": true
},
"include": [
/* Include your project files */
],
"exclude": [
"node_modules"
]
}
Barebone esbuild config
import esbuild from 'esbuild'
const ctx = await esbuild.context({
entryPoints: [/* Include your project files */],
bundle: true,
outfile: 'dist/index.js',
format: 'esm',
platform: 'browser',
jsx: 'automatic',
jsxFactory: 'jsx',
target: 'esnext',
loader: {
'.tsx': 'tsx',
'.ts': 'ts'
}
})
try {
ctx.watch()
} catch (e) {
console.log(e)
process.exit(1)
}
Barebone package.json
{
"dependencies": {
"@minima-dev/minima-js": "^0.1.17",
"esbuild": "^0.28.1",
"typescript": "^6.0.3"
},
"scripts": {
"watch": "node esbuild.watch.config.js"
},
"type": "module"
}
Custom component example
import { Component, State, Effect, jsx } from '@minima-dev/minima-js';
class Counter extends Component {
@State(0) count = 0;
@Effect
logOnChange() {
console.log(`Counter changed to ${this.count()}`);
}
increment = () => {
this.count = () => this.count() + 1;
};
Create() {
return (
<div>
<span>Count: {this.count}</span>
<button onClick={this.increment}>+1</button>
</div>
);
}
}📊 Benchmarks
| Framework | Time estimated (1 million updates) | Size (min+gzip) | Optimizations | |-----------|--------------------------|-------------------|----------------| | Minima | 80 мс ⚡ | ~3 KB | Delayed mode (Scheduled DOM) | React 18 | ~223 мс | ~40 KB | Manual flushSync() + unstable_batchUpdates()
🧩 Decorators
@State(initialValue)
Creates reactive field. Returns lambda for reading.
@State(0) count = 0;
// this.count() — get
// this.count = () => 5 — set@Effect
Subscribes on all fields @State, which it uses within its function.
@Effect
log() {
console.log(this.count()); // Auto subscription
}@Inject(token)
Injects dependency by token (constructor)
@Inject(Backend) backend;🖥 Backends
DOM
import { DOMB } from 'minima';
const backend = new DOMB.Base(document.body);Canvas
I am working on it, it will be released on version 0.2.0
🔗 URL
Every node is assigned URL relative to its root:
/div[0]/span[0]/button[2]It allows:
- Debuggins
- Update the node without diffing
- Virtual scroll and dynamic lists
Contacts
I am 21 year old boy and I am working on this framework for about 7 days total. Didn't expect somebody will take an interest in my project. I hope your days will be better!
Russian documentation
630 строк. 80 мс на 1 млн обновлений. Без виртуалки.
Minima — это минималистичный фронтенд-фреймворк с реактивным состоянием, встроенным DI-контейнером и точечными обновлениями DOM по URL-адресации узлов. Он не использует Virtual DOM, не требует сложной компиляции и при этом обходит React по скорости в 1,4-10 раз.
Никакого React, Vue, Svelte или Solid. Minima написан с нуля как инструмент для высокопроизводительных интерфейсов, и это полностью изменило подход автора к фронтенду.
🔥 Особенности
- ⚡ Молниеносная производительность
1 000 000 синхронных обновлений за 80 мс - 📦 Минимальный размер
Всего 630 строк скомпилированного JavaScript (~3 KB gzip) - 🧩 Компонентный подход
JSX-синтаксис, декораторы состояния и эффектов - 🎯 Точечные обновления по URL
Каждый узел дерева имеет уникальный URL вида/div[0]/span[0] - 🧠 FIOI-планировщик
Батчинг черезrequestAnimationFrameс философией Flushing Independent of Instance - 🧬 Автоматический сбор зависимостей
@Effectсам подписывается на используемые поля состояния - 🏗 Встроенный DI-контейнер
@Injectдля внедрения зависимостей - 🖼 Два бекенда рендеринга
DOM и Canvas из коробки - 📍 Контекст + фабрика
Через атрибутfabricиContextProvider
🚀 Быстрый старт
npm i @minima-dev/minima-js
# или просто скопируйте index.js в проектПример компонента
import { Component, State, Effect, jsx } from 'minima';
class Counter extends Component {
@State(0) count = 0;
@Effect
logOnChange() {
console.log(`Counter changed to ${this.count()}`);
}
increment = () => {
this.count = () => this.count() + 1;
};
Create() {
return (
<div>
<span>Count: {this.count}</span>
<button onClick={this.increment}>+1</button>
</div>
);
}
}📊 Бенчмарк
| Фреймворк | Время (1 млн обновлений) | Размер (min+gzip) | Optimizations | |-----------|--------------------------|-------------------|----------------| | Minima | 80 мс ⚡ | ~3 KB | Delayed mode (Scheduled DOM) | React 18 | ~223 мс | ~40 KB | Ручной flushSync() + unstable_batchUpdates()
Тест проводился на синхронных обновлениях состояния с точечным ререндером по URL.
🧠 Как это работает
- Статическое дерево — компоненты рендерятся один раз, URL узлов фиксируются.
- Прямые ссылки на DOM — бекенд хранит Map<URL, DOM-элемент>.
- Планировщик через rAF — все мутации батчатся в один кадр.
- @State → DependencyGraph → URL — изменение состояния обновляет только связанные узлы.
- FIOI — Flushing Independent of Instance, обновления не зависят от дерева.
🧩 Декораторы
@State(initialValue)
Создаёт реактивное поле. Доступ через геттер возвращает лямбду для чтения.
@State(0) count = 0;
// this.count() — читаем
// this.count = () => 5 — записываем@Effect
Автоматически подписывается на все @State, которые используются внутри.
@Effect
log() {
console.log(this.count()); // автоматическая подписка
}@Inject(token)
Внедряет зависимость из DI-контейнера.
@Inject(Backend) backend;🖥 Бекенды
DOM
import { DOMB } from 'minima';
const backend = new DOMB.Base(document.body);Canvas
На текущий момент его нет, я его выпущу в версии 0.2.0
🔗 URL-адресация
Каждый узел получает уникальный URL относительно корня:
/div[0]/span[0]/button[2]Это позволяет:
- Отлаживать изменения через консоль
- Обновлять конкретный узел без диффинга
- Строить виртуальный скролл и динамические списки
📄 Лицензия
MIT © SampleUserD 2026
🤝 Вклад
Если ты нашёл баг или хочешь предложить фичу — создавай Issue или Pull Request.
Мы очень скромны, но всегда рады помощи ❤️
💬 Контакты
Автор — анонимный 21-летний разработчик, который никогда не программировал на React, Vue, Svelte или Solid.
Но это не помешало ему сделать Minima.
Спасибо за внимание. Надеюсь, этот код сделает чей-то день чуточку лучше. 🚀
