@madojs/mado 0.5.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/AGENTS.md +291 -0
- package/CHANGELOG.md +23 -0
- package/LICENSE +21 -0
- package/README.md +371 -0
- package/ROADMAP.md +52 -0
- package/dist/src/component.d.ts +48 -0
- package/dist/src/component.js +140 -0
- package/dist/src/component.js.map +1 -0
- package/dist/src/context.d.ts +40 -0
- package/dist/src/context.js +67 -0
- package/dist/src/context.js.map +1 -0
- package/dist/src/css.d.ts +54 -0
- package/dist/src/css.js +137 -0
- package/dist/src/css.js.map +1 -0
- package/dist/src/devtools.d.ts +22 -0
- package/dist/src/devtools.js +63 -0
- package/dist/src/devtools.js.map +1 -0
- package/dist/src/diagnostics.d.ts +11 -0
- package/dist/src/diagnostics.js +28 -0
- package/dist/src/diagnostics.js.map +1 -0
- package/dist/src/each.d.ts +39 -0
- package/dist/src/each.js +35 -0
- package/dist/src/each.js.map +1 -0
- package/dist/src/forms.d.ts +71 -0
- package/dist/src/forms.js +161 -0
- package/dist/src/forms.js.map +1 -0
- package/dist/src/head.d.ts +19 -0
- package/dist/src/head.js +97 -0
- package/dist/src/head.js.map +1 -0
- package/dist/src/html/bindings.d.ts +78 -0
- package/dist/src/html/bindings.js +304 -0
- package/dist/src/html/bindings.js.map +1 -0
- package/dist/src/html/parser.d.ts +64 -0
- package/dist/src/html/parser.js +521 -0
- package/dist/src/html/parser.js.map +1 -0
- package/dist/src/html/template-types.d.ts +27 -0
- package/dist/src/html/template-types.js +8 -0
- package/dist/src/html/template-types.js.map +1 -0
- package/dist/src/html/template.d.ts +45 -0
- package/dist/src/html/template.js +119 -0
- package/dist/src/html/template.js.map +1 -0
- package/dist/src/html.d.ts +16 -0
- package/dist/src/html.js +16 -0
- package/dist/src/html.js.map +1 -0
- package/dist/src/index.d.ts +35 -0
- package/dist/src/index.js +39 -0
- package/dist/src/index.js.map +1 -0
- package/dist/src/lazy.d.ts +38 -0
- package/dist/src/lazy.js +73 -0
- package/dist/src/lazy.js.map +1 -0
- package/dist/src/lifecycle.d.ts +45 -0
- package/dist/src/lifecycle.js +66 -0
- package/dist/src/lifecycle.js.map +1 -0
- package/dist/src/page.d.ts +161 -0
- package/dist/src/page.js +38 -0
- package/dist/src/page.js.map +1 -0
- package/dist/src/persisted.d.ts +47 -0
- package/dist/src/persisted.js +119 -0
- package/dist/src/persisted.js.map +1 -0
- package/dist/src/resource.d.ts +120 -0
- package/dist/src/resource.js +275 -0
- package/dist/src/resource.js.map +1 -0
- package/dist/src/router/manifest.d.ts +56 -0
- package/dist/src/router/manifest.js +302 -0
- package/dist/src/router/manifest.js.map +1 -0
- package/dist/src/router/match.d.ts +62 -0
- package/dist/src/router/match.js +117 -0
- package/dist/src/router/match.js.map +1 -0
- package/dist/src/router/navigation.d.ts +89 -0
- package/dist/src/router/navigation.js +263 -0
- package/dist/src/router/navigation.js.map +1 -0
- package/dist/src/router.d.ts +13 -0
- package/dist/src/router.js +13 -0
- package/dist/src/router.js.map +1 -0
- package/dist/src/signal.d.ts +67 -0
- package/dist/src/signal.js +238 -0
- package/dist/src/signal.js.map +1 -0
- package/docs/README.md +12 -0
- package/docs/en/00-the-mado-way.md +106 -0
- package/docs/en/01-routing.md +204 -0
- package/docs/en/02-project-layout.md +58 -0
- package/docs/en/03-static-bake.md +251 -0
- package/docs/en/04-ide-setup.md +162 -0
- package/docs/en/05-why-mado.md +193 -0
- package/docs/en/06-for-backenders.md +422 -0
- package/docs/en/07-llm-pitfalls.md +486 -0
- package/docs/en/08-llm-zero-history-test.md +56 -0
- package/docs/en/09-shadow-vs-light-dom.md +122 -0
- package/docs/en/README.md +16 -0
- package/docs/fr/00-the-mado-way.md +108 -0
- package/docs/fr/01-routing.md +202 -0
- package/docs/fr/02-project-layout.md +58 -0
- package/docs/fr/03-static-bake.md +290 -0
- package/docs/fr/04-ide-setup.md +162 -0
- package/docs/fr/05-why-mado.md +193 -0
- package/docs/fr/06-for-backenders.md +432 -0
- package/docs/fr/07-llm-pitfalls.md +487 -0
- package/docs/fr/08-llm-zero-history-test.md +60 -0
- package/docs/fr/09-shadow-vs-light-dom.md +121 -0
- package/docs/fr/README.md +16 -0
- package/docs/ru/00-the-mado-way.md +93 -0
- package/docs/ru/01-routing.md +194 -0
- package/docs/ru/02-project-layout.md +57 -0
- package/docs/ru/03-static-bake.md +251 -0
- package/docs/ru/04-ide-setup.md +144 -0
- package/docs/ru/05-why-mado.md +193 -0
- package/docs/ru/06-for-backenders.md +422 -0
- package/docs/ru/07-llm-pitfalls.md +485 -0
- package/docs/ru/08-llm-zero-history-test.md +56 -0
- package/docs/ru/09-shadow-vs-light-dom.md +122 -0
- package/docs/ru/README.md +14 -0
- package/docs/uk/00-the-mado-way.md +54 -0
- package/docs/uk/01-routing.md +82 -0
- package/docs/uk/02-project-layout.md +46 -0
- package/docs/uk/03-static-bake.md +49 -0
- package/docs/uk/04-ide-setup.md +26 -0
- package/docs/uk/05-why-mado.md +34 -0
- package/docs/uk/06-for-backenders.md +50 -0
- package/docs/uk/07-llm-pitfalls.md +82 -0
- package/docs/uk/08-llm-zero-history-test.md +31 -0
- package/docs/uk/09-shadow-vs-light-dom.md +40 -0
- package/docs/uk/README.md +16 -0
- package/llms.txt +155 -0
- package/package.json +81 -0
- package/scripts/bake.mjs +406 -0
- package/scripts/bundle.mjs +146 -0
- package/scripts/cli.mjs +382 -0
- package/scripts/new.mjs +80 -0
- package/scripts/preview.mjs +176 -0
- package/scripts/release-notes.mjs +66 -0
- package/scripts/showcase-regression.mjs +392 -0
- package/server/serve.mjs +292 -0
- package/starters/crud/README.md +21 -0
- package/starters/crud/index.html +20 -0
- package/starters/crud/package.json +17 -0
- package/starters/crud/src/components/app-shell.ts +51 -0
- package/starters/crud/src/components/ticket-detail.ts +33 -0
- package/starters/crud/src/components/ticket-form.ts +69 -0
- package/starters/crud/src/components/ticket-list.ts +66 -0
- package/starters/crud/src/lib/api.ts +76 -0
- package/starters/crud/src/main.ts +12 -0
- package/starters/crud/src/pages/home.ts +18 -0
- package/starters/crud/src/pages/not-found.ts +12 -0
- package/starters/crud/src/pages/ticket-detail.ts +6 -0
- package/starters/crud/src/pages/ticket-new.ts +6 -0
- package/starters/crud/src/pages/tickets.ts +6 -0
- package/starters/crud/src/routes.ts +9 -0
- package/starters/crud/src/styles/global.ts +155 -0
- package/starters/crud/tsconfig.json +15 -0
- package/starters/minimal/README.md +19 -0
- package/starters/minimal/index.html +20 -0
- package/starters/minimal/package.json +17 -0
- package/starters/minimal/src/components/app-counter.ts +31 -0
- package/starters/minimal/src/main.ts +9 -0
- package/starters/minimal/src/pages/home.ts +18 -0
- package/starters/minimal/src/pages/not-found.ts +14 -0
- package/starters/minimal/src/routes.ts +6 -0
- package/starters/minimal/src/styles/global.ts +60 -0
- package/starters/minimal/tsconfig.json +15 -0
- package/templates/page-detail.ts +63 -0
- package/templates/page-form.ts +94 -0
- package/templates/page-list.ts +79 -0
|
@@ -0,0 +1,144 @@
|
|
|
1
|
+
# IDE-поддержка `html\`\`` и `css\`\``
|
|
2
|
+
|
|
3
|
+
Из коробки `html\`...\`` и `css\`...\`` — это просто tagged-template-строки. TypeScript их не знает, IDE их не подсвечивает. Это **сознательный компромисс** ради нулевых рантайм-зависимостей и отсутствия билд-плагинов.
|
|
4
|
+
|
|
5
|
+
Хорошая новость: Mado использует те же конвенции, что и [lit](https://lit.dev), поэтому работают **готовые** IDE-инструменты от lit-экосистемы.
|
|
6
|
+
|
|
7
|
+
---
|
|
8
|
+
|
|
9
|
+
## VS Code (рекомендованный сетап)
|
|
10
|
+
|
|
11
|
+
### 1. Установить [lit-plugin](https://marketplace.visualstudio.com/items?itemName=runem.lit-plugin)
|
|
12
|
+
|
|
13
|
+
VS Code → Extensions → найти **"lit-plugin"** (от runem) → Install.
|
|
14
|
+
|
|
15
|
+
Что появится:
|
|
16
|
+
|
|
17
|
+
- Подсветка HTML внутри `html\`\``.
|
|
18
|
+
- Подсветка CSS внутри `css\`\``.
|
|
19
|
+
- Авто-комплит HTML-тегов, атрибутов, событий.
|
|
20
|
+
- Проверка опечаток в атрибутах.
|
|
21
|
+
- Go-to-definition для кастомных элементов (если описаны через `customElements.json` или JSDoc).
|
|
22
|
+
- Diagnostics на неверные binding'и.
|
|
23
|
+
|
|
24
|
+
### 2. Указать имена тегов
|
|
25
|
+
|
|
26
|
+
`lit-plugin` ищет идентификаторы `html` и `css` в импортах. Если вы не переименовываете их при импорте — настройка нулевая, всё работает:
|
|
27
|
+
|
|
28
|
+
```ts
|
|
29
|
+
import { html, css } from "@madojs/mado";
|
|
30
|
+
|
|
31
|
+
const tpl = html`<button @click=${fn}>${label}</button>`;
|
|
32
|
+
```
|
|
33
|
+
|
|
34
|
+
### 3. (Опционально) Свои `customElements.json`
|
|
35
|
+
|
|
36
|
+
Если хотите авто-комплит по своим `<x-*>`-компонентам, опишите их через [Custom Elements Manifest](https://github.com/webcomponents/custom-elements-manifest):
|
|
37
|
+
|
|
38
|
+
```bash
|
|
39
|
+
npm install --save-dev @custom-elements-manifest/analyzer
|
|
40
|
+
npx cem analyze --globs "src/components/**/*.ts"
|
|
41
|
+
```
|
|
42
|
+
|
|
43
|
+
Создаст `custom-elements.json`, который `lit-plugin` подхватит автоматически.
|
|
44
|
+
|
|
45
|
+
---
|
|
46
|
+
|
|
47
|
+
## WebStorm / IntelliJ
|
|
48
|
+
|
|
49
|
+
WebStorm понимает `html\`\`` и `css\`\`` **из коробки** — нативная поддержка lit-style template-литералов с 2021 года. Никаких плагинов ставить не нужно.
|
|
50
|
+
|
|
51
|
+
Если подсветка не появляется:
|
|
52
|
+
|
|
53
|
+
- Settings → Languages & Frameworks → JavaScript → проверить, что включено "Use types from server"
|
|
54
|
+
- Перезагрузить TS-сервер: ⌘+⇧+P → "Restart TypeScript Server"
|
|
55
|
+
|
|
56
|
+
---
|
|
57
|
+
|
|
58
|
+
## Neovim / Helix
|
|
59
|
+
|
|
60
|
+
Используйте [`lit-html-server`](https://github.com/runem/lit-analyzer/tree/master/packages/lit-html-server) (LSP-сервер от того же автора, что и lit-plugin):
|
|
61
|
+
|
|
62
|
+
```bash
|
|
63
|
+
npm install -g lit-html-server
|
|
64
|
+
```
|
|
65
|
+
|
|
66
|
+
`init.lua` (для `lspconfig`):
|
|
67
|
+
|
|
68
|
+
```lua
|
|
69
|
+
require('lspconfig').lit_html.setup{
|
|
70
|
+
cmd = { 'lit-html-server', '--stdio' },
|
|
71
|
+
filetypes = { 'typescript', 'javascript' },
|
|
72
|
+
}
|
|
73
|
+
```
|
|
74
|
+
|
|
75
|
+
---
|
|
76
|
+
|
|
77
|
+
## Что НЕ работает (известные ограничения)
|
|
78
|
+
|
|
79
|
+
- **Type-check биндингов через сигналы.** `html\`<input .value=${count}>\`` — `lit-plugin` ожидает строку, а `count` это `Signal<number>`. Подавляется через `// @ts-expect-error` или комментарием `<!-- @ts-ignore -->`. Будет улучшено в Phase 3+.
|
|
80
|
+
- **Кастомные директивы (`each`)** распознаются как обычные функции — без специальной семантики у плагина.
|
|
81
|
+
- **Атрибуты с префиксами `@`, `.`, `?`** иногда подсвечиваются как ошибки, если в `lit-plugin` отключён `"no-unknown-attribute": false`. В `.vscode/settings.json`:
|
|
82
|
+
|
|
83
|
+
```json
|
|
84
|
+
{
|
|
85
|
+
"lit-plugin.rules": {
|
|
86
|
+
"no-unknown-attribute": "off",
|
|
87
|
+
"no-incompatible-type-binding": "off"
|
|
88
|
+
}
|
|
89
|
+
}
|
|
90
|
+
```
|
|
91
|
+
|
|
92
|
+
---
|
|
93
|
+
|
|
94
|
+
## JSDoc-типизация компонентов
|
|
95
|
+
|
|
96
|
+
Чтобы IDE подхватывал кастомные элементы внутри `html\`\``, аннотируйте `component()`-определение через JSDoc:
|
|
97
|
+
|
|
98
|
+
```ts
|
|
99
|
+
/**
|
|
100
|
+
* @element x-counter
|
|
101
|
+
* @attr {number} initial - стартовое значение
|
|
102
|
+
* @fires {CustomEvent<number>} change - на каждое изменение
|
|
103
|
+
*/
|
|
104
|
+
component("x-counter", () => {
|
|
105
|
+
/* ... */
|
|
106
|
+
});
|
|
107
|
+
```
|
|
108
|
+
|
|
109
|
+
`lit-plugin` это распознаёт и предлагает атрибуты при печати `<x-counter ...>`.
|
|
110
|
+
|
|
111
|
+
---
|
|
112
|
+
|
|
113
|
+
## Prettier / форматирование
|
|
114
|
+
|
|
115
|
+
Prettier с **3.0+** форматирует `html\`\`` через [`@prettier/plugin-xml`](https://github.com/prettier/plugin-xml) или встроенный режим. Минимальный `.prettierrc`:
|
|
116
|
+
|
|
117
|
+
```json
|
|
118
|
+
{
|
|
119
|
+
"semi": true,
|
|
120
|
+
"singleQuote": false,
|
|
121
|
+
"embeddedLanguageFormatting": "auto"
|
|
122
|
+
}
|
|
123
|
+
```
|
|
124
|
+
|
|
125
|
+
Опция `embeddedLanguageFormatting: "auto"` (default) форматирует содержимое tagged-template-литералов с известными тегами (`html`, `css`).
|
|
126
|
+
|
|
127
|
+
---
|
|
128
|
+
|
|
129
|
+
## ESLint
|
|
130
|
+
|
|
131
|
+
Если используете ESLint, плагин [`eslint-plugin-lit`](https://github.com/43081j/eslint-plugin-lit) даёт правила специально под tagged-template-html (а правила [`eslint-plugin-wc`](https://github.com/43081j/eslint-plugin-wc) — под Web Components в целом). Конфигурация — на ваш вкус, не required.
|
|
132
|
+
|
|
133
|
+
---
|
|
134
|
+
|
|
135
|
+
## TL;DR
|
|
136
|
+
|
|
137
|
+
| Редактор | Setup | Уровень DX |
|
|
138
|
+
|---|---|---|
|
|
139
|
+
| **VS Code** | поставить `lit-plugin` | ★★★★ |
|
|
140
|
+
| **WebStorm** | ничего | ★★★★ |
|
|
141
|
+
| **Neovim/Helix** | `lit-html-server` через LSP | ★★★ |
|
|
142
|
+
| **Vim без LSP** | вручную | ★ |
|
|
143
|
+
|
|
144
|
+
Без IDE-плагина Mado тоже работает: `html\`\`` остаётся валидным TS-кодом, всё компилируется и запускается. Просто строка внутри подсвечивается как строка.
|
|
@@ -0,0 +1,193 @@
|
|
|
1
|
+
# Why Mado (and why not Lit / Solid / Alpine / htmx)
|
|
2
|
+
|
|
3
|
+
> Если ты выбираешь фронт-стек для нового проекта, эта страница для тебя.
|
|
4
|
+
> Если у тебя уже что-то работает — **не мигрируй ради миграции**, это всегда дороже, чем кажется.
|
|
5
|
+
|
|
6
|
+
Mado — не «убийца» React/Vue/Svelte. Это узкоспециализированный инструмент. Здесь я честно объясняю, **в каких случаях Mado действительно лучше альтернатив**, а в каких — нет.
|
|
7
|
+
|
|
8
|
+
---
|
|
9
|
+
|
|
10
|
+
## TL;DR — одной таблицей
|
|
11
|
+
|
|
12
|
+
| Если вам важно… | Берите |
|
|
13
|
+
|---|---|
|
|
14
|
+
| Лучшая обучающая инфраструктура / огромная экосистема | **React** или **Vue** |
|
|
15
|
+
| Дизайн-система компонентов для встраивания в любые фреймворки | **Lit** |
|
|
16
|
+
| Топовый перфоманс на больших списках, "близкий к ванилле" с JSX | **Solid** или **Svelte 5** |
|
|
17
|
+
| Прогрессивное улучшение классических серверных приложений | **htmx** + ваш бек |
|
|
18
|
+
| "Украшение" статического сайта реактивностью | **Alpine.js** |
|
|
19
|
+
| Минимум инструмента, максимум платформы, всё в одной коробке (роутер + data + формы + SEO), читается за вечер | **Mado** ✓ |
|
|
20
|
+
|
|
21
|
+
Если ваш кейс не попадает в последний пункт — Mado скорее всего не лучший выбор. Это нормально.
|
|
22
|
+
|
|
23
|
+
---
|
|
24
|
+
|
|
25
|
+
## Mado vs Lit
|
|
26
|
+
|
|
27
|
+
**Lit** — самая близкая по духу альтернатива. Тот же подход: Web Components + tagged templates + минимум магии.
|
|
28
|
+
|
|
29
|
+
| | Lit | Mado |
|
|
30
|
+
|---|---|---|
|
|
31
|
+
| Размер | ~6 КБ | ~16 КБ |
|
|
32
|
+
| Возраст / поддержка | ~10 лет, Google | 6 месяцев, один автор |
|
|
33
|
+
| Реактивность | декораторы `@property` + ручной `requestUpdate` | сигналы (`signal`/`computed`/`effect`) из коробки |
|
|
34
|
+
| Роутер | нет, нужно искать (`@lit-labs/router`, etc) | в комплекте: `routes()` + nested + prefetch + sync-cache |
|
|
35
|
+
| Data fetching | нет, нужно собирать | `resource()` + `mutation()` + glob-инвалидация |
|
|
36
|
+
| Формы | нет | `useForm()` на нативной HTML5-валидации |
|
|
37
|
+
| SEO / static | сложно (`@lit-labs/ssr`) | `bake` (linkedom) + edge-prerender |
|
|
38
|
+
| Билд | нужен esbuild/rollup/webpack | хватает `tsc` |
|
|
39
|
+
| Стиль кода | классы + декораторы | функции + tagged templates |
|
|
40
|
+
| Экосистема | реальная (Shoelace, Material Web, и т.д.) | нет |
|
|
41
|
+
| Когда выбрать | пишете дизайн-систему / Web-Components-библиотеку для встраивания | пишете приложение целиком, хотите всё в одной коробке |
|
|
42
|
+
|
|
43
|
+
**Честный pitch:** *«Lit — лучше, если ты пишешь дизайн-систему компонентов. Mado — лучше, если ты пишешь приложение и хочешь батарейки в коробке без сборки 8 пакетов.»*
|
|
44
|
+
|
|
45
|
+
---
|
|
46
|
+
|
|
47
|
+
## Mado vs Solid
|
|
48
|
+
|
|
49
|
+
**Solid** — топовая реактивная либа на сигналах. Технически очень крутая.
|
|
50
|
+
|
|
51
|
+
| | Solid | Mado |
|
|
52
|
+
|---|---|---|
|
|
53
|
+
| Размер | ~7 КБ | ~16 КБ |
|
|
54
|
+
| Перфоманс | топ-3 на js-framework-benchmark | хорошо, но не топ |
|
|
55
|
+
| Реактивность | сигналы (тот же класс идей) | сигналы |
|
|
56
|
+
| Шаблоны | JSX (компилируется в реактивные expressions) | tagged template `html\`\`` |
|
|
57
|
+
| Компонентная модель | функции, виртуальные узлы Solid | Web Components |
|
|
58
|
+
| Билд | Vite + babel-plugin-solid обязательны | только `tsc` |
|
|
59
|
+
| Роутер | `@solidjs/router` | в комплекте |
|
|
60
|
+
| Data | `createResource` | `resource()` |
|
|
61
|
+
| SSR | поддерживается серьёзно (SolidStart) | намеренно нет |
|
|
62
|
+
| Экосистема | растёт, ~50 пакетов | нет |
|
|
63
|
+
| Когда выбрать | нужен топовый перф + JSX + готов настраивать билд | хотите запустить без билда / минимум инфраструктуры |
|
|
64
|
+
|
|
65
|
+
**Честный pitch:** *«Solid технически быстрее и зрелее. Но Solid требует Vite + babel-плагин. Mado не требует ничего, кроме `tsc` — это «открой VS Code, F5 и работай». Если эта разница не критична — берите Solid.»*
|
|
66
|
+
|
|
67
|
+
---
|
|
68
|
+
|
|
69
|
+
## Mado vs Svelte 5
|
|
70
|
+
|
|
71
|
+
**Svelte 5** с runes — тоже сигнальная модель, тоже минималистичная.
|
|
72
|
+
|
|
73
|
+
| | Svelte 5 | Mado |
|
|
74
|
+
|---|---|---|
|
|
75
|
+
| Размер runtime | ~3 КБ | ~16 КБ |
|
|
76
|
+
| Компилятор | обязателен (.svelte → JS) | нет |
|
|
77
|
+
| Синтаксис | свой .svelte формат | TS + tagged templates |
|
|
78
|
+
| Реактивность | `$state`/`$derived` (runes) | `signal`/`computed` |
|
|
79
|
+
| SSR / SvelteKit | полноценная, mature | намеренно нет |
|
|
80
|
+
| Экосистема | большая, dev-tools отличные | нет |
|
|
81
|
+
| Когда выбрать | новый продакшен проект с командой | приватный/внутренний инструмент, нужна простота |
|
|
82
|
+
|
|
83
|
+
**Честный pitch:** *«Svelte — продуктовый выбор. Mado — инженерный. Если у вас команда и продакшен — Svelte. Если вы один и хотите контроль — Mado.»*
|
|
84
|
+
|
|
85
|
+
---
|
|
86
|
+
|
|
87
|
+
## Mado vs htmx
|
|
88
|
+
|
|
89
|
+
**htmx** — другая школа: HTML-fragments over the wire.
|
|
90
|
+
|
|
91
|
+
| | htmx | Mado |
|
|
92
|
+
|---|---|---|
|
|
93
|
+
| Архитектура | HTML с сервера, обновление через fragments | SPA: JS грузит данные, рендерит сам |
|
|
94
|
+
| Зависит от бека | сильно (бек должен уметь отдавать HTML) | слабо (бек — JSON API) |
|
|
95
|
+
| State на клиенте | минимальный (cookies, localStorage) | полноценный (signal, persisted) |
|
|
96
|
+
| Optimistic updates | сложно | легко (mutation + invalidates) |
|
|
97
|
+
| Offline / PWA | плохо | нормально |
|
|
98
|
+
| Размер | ~14 КБ | ~16 КБ |
|
|
99
|
+
| Когда выбрать | классическое серверное приложение (Rails, Django, Phoenix), нужно «оживить» | SPA-опыт обязателен, бек — REST/GraphQL |
|
|
100
|
+
|
|
101
|
+
**Честный pitch:** *«htmx — если бек крепкий и умеет HTML. Mado — если бек отдаёт JSON, а вам нужен полноценный SPA-опыт.»*
|
|
102
|
+
|
|
103
|
+
---
|
|
104
|
+
|
|
105
|
+
## Mado vs Alpine.js
|
|
106
|
+
|
|
107
|
+
**Alpine** — реактивные атрибуты прямо в HTML.
|
|
108
|
+
|
|
109
|
+
| | Alpine | Mado |
|
|
110
|
+
|---|---|---|
|
|
111
|
+
| Назначение | украшение статического HTML | полноценное SPA |
|
|
112
|
+
| Размер | ~7 КБ | ~16 КБ |
|
|
113
|
+
| State management | `x-data` локально | сигналы + context + persisted |
|
|
114
|
+
| Роутинг | нет | в комплекте |
|
|
115
|
+
| TypeScript | плохо | first-class |
|
|
116
|
+
| Когда выбрать | статика, лендинги, нужны 5 интерактивных кнопок | full app: страницы, навигация, формы, data |
|
|
117
|
+
|
|
118
|
+
**Честный pitch:** *«Alpine — для интерактива на статике. Mado — для полноценного приложения.»*
|
|
119
|
+
|
|
120
|
+
---
|
|
121
|
+
|
|
122
|
+
## Mado vs React + ecosystem
|
|
123
|
+
|
|
124
|
+
Я не буду долго на этом останавливаться, потому что React — это **другая весовая категория** по экосистеме и зрелости. Но если вы серьёзно сравниваете:
|
|
125
|
+
|
|
126
|
+
**React выигрывает:**
|
|
127
|
+
- огромная экосистема: тысячи UI-китов, тысячи статей, бесконечные туториалы;
|
|
128
|
+
- AI-помощники (ChatGPT, Copilot) знают React лучше всех;
|
|
129
|
+
- лучший job market;
|
|
130
|
+
- лучшая поддержка SSR (Next.js).
|
|
131
|
+
|
|
132
|
+
**Mado выигрывает:**
|
|
133
|
+
- размер бандла в десятки раз меньше;
|
|
134
|
+
- нулевая инфраструктура (нет Vite, нет Babel, нет 200 пакетов);
|
|
135
|
+
- читается за вечер — если что-то сломалось, открой `src/`;
|
|
136
|
+
- сигналы вместо хуков (нет правил «нельзя в if», нет stale-closure ловушек);
|
|
137
|
+
- не нужно мигрировать с major на major.
|
|
138
|
+
|
|
139
|
+
**Когда выбрать Mado вместо React:**
|
|
140
|
+
- проект на 1-3 человек, на годы вперёд;
|
|
141
|
+
- размер бандла критичен;
|
|
142
|
+
- вы устали от React-усталости и готовы пожертвовать экосистемой ради простоты.
|
|
143
|
+
|
|
144
|
+
**Когда выбрать React:**
|
|
145
|
+
- команда от 5 человек;
|
|
146
|
+
- нужны UI-киты, нужна экосистема;
|
|
147
|
+
- проект, который будет нанимать новых людей с рынка;
|
|
148
|
+
- нужен SSR с гидрацией (Next.js).
|
|
149
|
+
|
|
150
|
+
---
|
|
151
|
+
|
|
152
|
+
## Сильнейший аргумент Mado
|
|
153
|
+
|
|
154
|
+
Не размер, не перф, не сигналы — у всего этого есть конкуренты лучше.
|
|
155
|
+
|
|
156
|
+
> **«Открой исходник и прочитай его за вечер. ~3500 строк, 12 модулей. Если что-то сломалось — ты не идёшь в issue на 3000 комментариев. Ты идёшь в `src/router.ts` и читаешь 500 строк.»**
|
|
157
|
+
|
|
158
|
+
Это называется **ownership** — ты владеешь кодом, а не зависишь от чужого.
|
|
159
|
+
|
|
160
|
+
Для бекендеров, которые привыкли к маленьким понятным библиотекам (chi в Go, axum в Rust, FastAPI в Python), это **родное ощущение**. Для тех, кому это не важно — берите что больше и зрелее.
|
|
161
|
+
|
|
162
|
+
---
|
|
163
|
+
|
|
164
|
+
## Что насчёт перфоманса?
|
|
165
|
+
|
|
166
|
+
Честно: **Mado не самый быстрый**. Топ-3 на js-framework-benchmark — это Solid, Inferno, Svelte. Mado ближе к Lit / Preact по характеристикам.
|
|
167
|
+
|
|
168
|
+
Что Mado делает для перфа из коробки:
|
|
169
|
+
- **lazy `computed`** (dirty-flag, не eager);
|
|
170
|
+
- **batch microtask scheduler** для `signal.set`;
|
|
171
|
+
- **keyed reconciliation** в `each()` с реальным DOM-reuse;
|
|
172
|
+
- **sync-rendering** для кешированных страниц в роутере;
|
|
173
|
+
- **hover-prefetch** lazy-chunk'ов;
|
|
174
|
+
- **View Transitions API** для плавных переходов;
|
|
175
|
+
- **shared `adoptedStyleSheets`** для CSS;
|
|
176
|
+
- **`modulepreload` hints** на dev-сервере.
|
|
177
|
+
|
|
178
|
+
Этого достаточно для большинства приложений. Если вы строите Excel в браузере или 60fps WebGL-визуализацию — это не сюда (это в Solid или нативный JS).
|
|
179
|
+
|
|
180
|
+
---
|
|
181
|
+
|
|
182
|
+
## Резюме
|
|
183
|
+
|
|
184
|
+
Mado — это **узкий** инструмент с честным позиционированием. Он сильнее всего там, где:
|
|
185
|
+
|
|
186
|
+
1. Вы хотите **владеть** кодом и читать его целиком.
|
|
187
|
+
2. Вам критична **простота инфраструктуры** (никакого Vite/Webpack/Babel).
|
|
188
|
+
3. Вам нужны **батарейки в одной коробке** (роутер + data + формы + SEO).
|
|
189
|
+
4. Вы не junior и не боитесь Web Components.
|
|
190
|
+
|
|
191
|
+
Если хоть один пункт не про вас — берите альтернативу из таблицы выше. Не миритесь с инструментом, который не подходит.
|
|
192
|
+
|
|
193
|
+
— Автор Mado, бывший React-разработчик, перешедший на бекенд и теперь склеивающий фронт в свободное время.
|