Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
59 changes: 41 additions & 18 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,17 +2,19 @@

# Regor

Regor is a powerful UI framework designed to streamline the development of HTML5-based applications for both web and desktop environments. With a template syntax that closely follows Vue.js, transitioning from VueJS to Regor is seamless for developers familiar with Vue.
Regor is a runtime-first UI framework for teams that want direct DOM control, strong TypeScript ergonomics, and precise reactivity behavior without being forced into a Virtual DOM architecture.

Its template syntax is familiar to Vue users (`r-if`, `r-model`, `r-for`, `r-bind`), but its runtime model is intentionally different: Regor is built for progressive enhancement, mixed-rendering environments, and incremental adoption.

### [![Published on npm](https://img.shields.io/npm/v/regor.svg)](https://www.npmjs.com/package/regor)

[**`Try Regor Online`**](https://stackblitz.com/edit/regor-sample-1?file=index.ts)

## Key Features

- **Simplicity:** Develop UIs without a Virtual DOM for a more straightforward implementation and easier debugging.
- **TypeScript:** Enjoy native TypeScript support without workarounds.
- **No Build Step Required:** Define components in TypeScript using tagged string templates, no build step needed.
- **No VDOM Layer:** Bind directly to real DOM for transparent runtime behavior and straightforward debugging.
- **TypeScript-Native:** Use standard TypeScript interfaces, classes, and generics without framework-specific file formats.
- **No Build Step Required:** Define components in TypeScript using tagged string templates with npm, CDN ESM, or global build workflows.
- **Secure Evaluation:** Regor's secure JavaScript VM ensures safe runtime compilation. You can enable security policy in your page without removing runtime compilation support.

```html
Expand All @@ -22,9 +24,9 @@ Regor is a powerful UI framework designed to streamline the development of HTML5
/>
```

- **Flexible Reactivity:** Empowering developers with a highly flexible reactivity system.
- **Non-JS SSR:** Bind to the existing DOM without removing already mounted HTML elements, suitable for non-JavaScript server-side rendering.
- **Reentrance:** Regor supports multiple mountings in the previously mounted area using the same or different app contexts. This enables creating and mounting new directives dynamically.
- **Flexible Reactivity:** Combine `ref`, `sref`, `batch`, `pause`, `resume`, and `entangle` for explicit state orchestration.
- **Static-First + Islands:** Bind to existing DOM without removing server-rendered HTML, ideal for progressive enhancement.
- **Reentrance:** Mount multiple times in already-mounted regions with same or different app contexts.
- **Compatibility:** Rendered pages are designed for seamless integration with other libraries manipulating the DOM.

## Documentation
Expand Down Expand Up @@ -72,16 +74,13 @@ const template = html`<button @click="count++">

const props = ['message']

const myComponent = createComponent<MyComponent>(
template,
{
context: (head) => ({
message: head.props.message,
count: ref(0),
}),
props,
},
)
const myComponent = createComponent<MyComponent>(template, {
context: (head) => ({
message: head.props.message,
count: ref(0),
}),
props,
})

createApp({
components: { myComponent },
Expand Down Expand Up @@ -161,7 +160,31 @@ or

## Comparison with VueJs

Regor shares core functionality with VueJs but differs in implementation, TypeScript support, template evaluation, reactivity, server-side rendering support, compatibility.
Regor is openly inspired by Vue’s concepts (even adopting a similar directive syntax like r-if / r-model instead of v-if / v-model), but it fundamentally diverges in its implementation. It prioritizes runtime flexibility, build-less environments, and strict TypeScript integration over the Virtual DOM (VDOM) paradigm.

### Architecture and rendering model

- **Vue:** Uses a Virtual DOM. This provides excellent performance for highly dynamic Single Page Applications (SPAs) because Vue calculates diffs in memory before updating the browser. However, it usually requires a compilation step to optimize templates, and hydrating existing server-rendered HTML can be notoriously strict (hydration mismatches).
- **Regor:** Ditches the VDOM entirely. It binds directly to the actual DOM. Regor explicitly supports Static-first + dynamic islands and "Reentrance." You can mount an application multiple times over already-mounted regions or existing server-rendered HTML without destroying the elements.
- **Verdict:** Regor is significantly more flexible for integrating into existing applications, multi-page applications (MPAs), or legacy backends.

### Runtime and deployment model

- **Vue:** Commonly paired with a build pipeline for SFCs and tooling depth.
- **Regor:** Designed to require no build step. You can write standard TypeScript using tagged string templates (e.g., `html` tags for templates) and it will evaluate at runtime. Crucially, Regor features a Secure JavaScript VM for runtime compilation that adheres to strict Content Security Policies (CSP)—a common pain point when using Vue's runtime compiler in enterprise environments.
- **Verdict:** Regor wins in deployment flexibility and zero-config setups. It respects modern security policies out of the box without demanding a bundler.

### Reactivity control model

- **Vue:** Uses ES6 Proxies for a highly automated, "magical" reactivity system. You update an object, and Vue figures out what to re-render. However, this magic can sometimes abstract away performance bottlenecks, leading to over-rendering if you aren't careful with deep reactivity.
- **Regor:** Provides fine-tuned, manual control. It offers `ref` (deep reactivity) and `sref` (simple/shallow reactivity without nested observation). Furthermore, Regor provides advanced control APIs like `pause()` and `resume()` to stop a ref's auto-triggers, `entangle()` to sync two refs effortlessly, and `batch()` for precise state grouping.
- **Verdict:** Vue's reactivity is easier for beginners.. Regor’s reactivity is more flexible and transparent, giving engineers exact tools to orchestrate update semantics and prevent unwanted DOM paints.

### TypeScript ergonomics

- **Vue:** TypeScript support in Vue has improved massively, but it still relies on heavy IDE plugins (Volar) and specialized compilers (vue-tsc) to understand .vue files. The separation between the `<template>` and `<script>` requires tooling to bridge the gap.
- **Regor:** Offers native TypeScript support without workarounds. Because components and templates are defined using standard TypeScript functions, class-based contexts, and `ComponentHead<T>`, standard TypeScript compilers and IDEs understand 100% of the code immediately.
- **Verdict:** Regor offers a purer, higher-quality TypeScript experience. It leverages the language itself rather than relying on framework-specific compiler magic to provide type safety.

## Supported Directives

Expand Down
53 changes: 53 additions & 0 deletions benchmarks/index.html
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@
--fg: #e5e7eb;
--muted: #9ca3af;
--accent: #22c55e;
--winner: #4ade80;
}
body {
margin: 0;
Expand Down Expand Up @@ -60,6 +61,17 @@
padding: 8px;
text-align: left;
}
#scenario-results tbody tr.scenario-pair-a {
background: #11243a;
}
#scenario-results tbody tr.scenario-pair-b {
background: #162f4b;
}
#results .winner-metric,
#scenario-results .winner-metric {
color: var(--winner);
font-weight: 700;
}
.roots {
display: grid;
grid-template-columns: 1fr 1fr;
Expand Down Expand Up @@ -92,6 +104,35 @@ <h1>DOM Benchmark: Regor vs Vue (latest)</h1>
<button id="run-regor">Run Regor</button>
<button id="run-vue">Run Vue</button>
<button id="run">Run Both</button>
<label style="margin-left: 12px; color: var(--muted)">
Row count
<select id="row-count">
<option value="500" selected>500</option>
<option value="1000">1000</option>
<option value="2000">2000</option>
<option value="5000">5000</option>
</select>
</label>
<label style="margin-left: 12px; color: var(--muted)">
Warmups
<select id="warmup-runs">
<option value="0">0</option>
<option value="2">2</option>
<option value="4">4</option>
<option value="6" selected>6</option>
<option value="10">10</option>
</select>
</label>
<label style="margin-left: 12px; color: var(--muted)">
Samples
<select id="sample-runs">
<option value="1">1</option>
<option value="10">10</option>
<option value="20" selected>20</option>
<option value="30">30</option>
<option value="50">50</option>
</select>
</label>
<table id="results">
<thead>
<tr>
Expand All @@ -108,6 +149,18 @@ <h1>DOM Benchmark: Regor vs Vue (latest)</h1>
</thead>
<tbody></tbody>
</table>
<table id="scenario-results">
<thead>
<tr>
<th>Framework</th>
<th>Scenario</th>
<th>Median (ms)</th>
<th>P90 (ms)</th>
<th>Samples</th>
</tr>
</thead>
<tbody></tbody>
</table>
<div id="log" class="note"></div>
<div class="roots">
<div class="panel rootbox">
Expand Down
34 changes: 34 additions & 0 deletions benchmarks/initial-load.html
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@
--fg: #e5e7eb;
--muted: #9ca3af;
--accent: #22c55e;
--winner: #4ade80;
}
body {
margin: 0;
Expand Down Expand Up @@ -60,6 +61,10 @@
padding: 8px;
text-align: left;
}
#results .winner-metric {
color: var(--winner);
font-weight: 700;
}
.roots {
display: grid;
grid-template-columns: 1fr 1fr;
Expand Down Expand Up @@ -89,6 +94,35 @@ <h1>Initial Load Benchmark: Regor vs Vue</h1>
<button id="run-regor">Run Regor</button>
<button id="run-vue">Run Vue</button>
<button id="run">Run Both</button>
<label style="margin-left: 12px; color: var(--muted)">
Row count
<select id="row-count">
<option value="500" selected>500</option>
<option value="1000">1000</option>
<option value="2000">2000</option>
<option value="5000">5000</option>
</select>
</label>
<label style="margin-left: 12px; color: var(--muted)">
Warmups
<select id="warmup-runs">
<option value="0">0</option>
<option value="2">2</option>
<option value="4">4</option>
<option value="6" selected>6</option>
<option value="10">10</option>
</select>
</label>
<label style="margin-left: 12px; color: var(--muted)">
Samples
<select id="sample-runs">
<option value="1">1</option>
<option value="10">10</option>
<option value="20" selected>20</option>
<option value="30">30</option>
<option value="50">50</option>
</select>
</label>
<table id="results">
<thead>
<tr>
Expand Down
Loading