Runtime System ​
TachUI's runtime system provides direct DOM manipulation without virtual DOM overhead, complete component lifecycle management, and seamless integration with the reactive system.
Overview ​
The runtime system is the foundation that executes the code generated by TachUI's compiler. It provides:
- Component Lifecycle: Mount, update, and unmount components with proper cleanup
- Direct DOM Rendering: Efficient DOM manipulation without virtual DOM overhead
- Reactive Integration: Seamless connection between signals/effects and DOM updates
- Memory Management: Automatic cleanup and leak prevention
- Performance Monitoring: Built-in performance tracking and optimization
Core Concepts ​
Component Lifecycle ​
Every TachUI component follows a predictable lifecycle:
import { createComponent } from '@tachui/core'
const MyComponent = createComponent((props) => {
// Component render function
return h('div', { className: 'my-component' },
`Hello, ${props.name}!`
)
}, {
displayName: 'MyComponent',
lifecycle: {
onMount: () => {
console.log('Component mounted')
// Return cleanup function
return () => console.log('Component cleanup')
},
onUnmount: () => {
console.log('Component unmounted')
},
onError: (error) => {
console.error('Component error:', error)
}
}
})Direct DOM Rendering ​
TachUI renders directly to the DOM for maximum performance:
import { h, text, DOMRenderer } from '@tachui/core'
const renderer = new DOMRenderer()
// Create DOM structure
const element = h('div', { className: 'container' },
h('h1', null, 'Welcome'),
h('p', null, text(() => `Dynamic content: ${signal()}`)),
h('button', {
onClick: () => handleClick()
}, 'Click me')
)
// Render to DOM
const container = document.getElementById('app')!
renderer.render(element, container)Reactive Integration ​
The runtime system automatically connects reactive signals to DOM updates:
import { createSignal, createEffect } from '@tachui/core'
const [count, setCount] = createSignal(0)
const [message, setMessage] = createSignal('Hello')
// Reactive text content
const counterText = text(() => `Count: ${count()}`)
// Reactive styles
const styledElement = h('div', {
style: () => ({
color: count() > 5 ? 'red' : 'blue',
fontSize: `${12 + count()}px`
})
}, counterText)Component Creation ​
Basic Components ​
const SimpleComponent = createComponent((props) => {
return h('div', null, `Hello, ${props.name}!`)
})
// Usage
const instance = SimpleComponent({ name: 'World' })Reactive Components ​
const ReactiveComponent = createReactiveComponent((props) => {
const [count, setCount] = createSignal(props.initialCount || 0)
return h('div', { className: 'counter' },
h('p', null, text(() => `Count: ${count()}`)),
h('button', {
onClick: () => setCount(c => c + 1)
}, 'Increment')
)
})Components with Default Props ​
interface GreetingProps {
name: string
greeting?: string
}
const Greeting = createComponent<GreetingProps>((props) => {
return h('div', null, `${props.greeting}, ${props.name}!`)
}, {
displayName: 'Greeting',
defaultProps: {
greeting: 'Hello'
}
})Enhanced Lifecycle ​
Adding Lifecycle Hooks ​
const EnhancedComponent = withLifecycle(BaseComponent, {
onMount: () => {
// Setup code
const subscription = subscribe()
// Return cleanup function
return () => subscription.unsubscribe()
},
onUnmount: () => {
// Cleanup code
}
})Error Boundaries ​
const ErrorBoundary = createErrorBoundary((error) => {
return h('div', { className: 'error' },
h('h2', null, 'Something went wrong'),
h('p', null, error.message)
)
})
// Usage
const SafeApp = ErrorBoundary({
children: RiskyComponent({})
})Component Management ​
Component Manager ​
The ComponentManager tracks all component instances:
import { ComponentManager } from '@tachui/core'
const manager = ComponentManager.getInstance()
// Register components
manager.registerComponent(instance)
// Schedule updates
manager.scheduleUpdate(instance.id)
// Get component info
const component = manager.getComponent(instance.id)
const allComponents = manager.getAllComponents()
// Cleanup
manager.unregisterComponent(instance.id)
manager.cleanup() // Clean up all componentsComponent Registry ​
// Components are automatically registered when created
const component = createComponent(() => h('div', null, 'Hello'))
const instance = component({})
// Instance has unique ID and tracking
console.log(instance.id) // "component_1640995200000_abc123def"
console.log(instance.type) // "component"DOM Manipulation ​
Element Creation ​
// Simple element
const div = h('div', { className: 'container' }, 'Content')
// Element with props and children
const complex = h('section', {
id: 'main',
className: 'main-section',
'data-testid': 'main'
},
h('h1', null, 'Title'),
h('p', null, 'Paragraph'),
h('button', { onClick: handleClick }, 'Click me')
)
// Nested structure
const app = h('div', { className: 'app' },
h('header', null, 'Header'),
h('main', null, 'Main content'),
h('footer', null, 'Footer')
)Text Nodes ​
// Static text
const staticText = text('Hello, World!')
// Reactive text
const [name, setName] = createSignal('TachUI')
const reactiveText = text(() => `Hello, ${name()}!`)
// Text in elements
const element = h('p', null, text(() => `Count: ${count()}`))Event Handling ​
const button = h('button', {
onClick: (event) => {
console.log('Button clicked!', event)
setCount(c => c + 1)
},
onMouseOver: () => console.log('Mouse over'),
onMouseOut: () => console.log('Mouse out')
}, 'Interactive Button')Styling ​
// Static styles
const styledDiv = h('div', {
style: {
color: 'blue',
fontSize: '16px',
padding: '10px'
}
}, 'Styled content')
// Reactive styles
const reactiveStyled = h('div', {
style: () => ({
color: isActive() ? 'green' : 'gray',
transform: `scale(${scale()})`,
opacity: visible() ? 1 : 0
})
}, 'Reactive styles')
// CSS classes
const withClasses = h('div', {
className: () => `
base-class
${isActive() ? 'active' : ''}
${hasError() ? 'error' : ''}
`.trim()
}, 'Dynamic classes')DOM Bridge System ​
Application Root Mounting ​
TachUI uses a DOM bridge system to connect component instances to actual browser DOM elements. The primary entry point is mountRoot():
import { mountRoot } from '@tachui/core'
// Create your application component
const App = createComponent(() => {
return h('div', { className: 'app' },
h('h1', null, 'Welcome to TachUI'),
h('p', null, 'This text is rendered to the DOM!')
)
})
// Mount your app to the DOM (requires element with id="app")
mountRoot(() => App({}))Component Tree Mounting ​
The DOM bridge automatically handles nested component structures:
const Header = createComponent(() => h('header', null, 'Site Header'))
const Main = createComponent(() => h('main', null, 'Main Content'))
const Footer = createComponent(() => h('footer', null, 'Site Footer'))
const App = createComponent(() => {
return h('div', { className: 'app-layout' },
Header({}),
Main({}),
Footer({})
)
})
mountRoot(() => App({}))Modifier Integration ​
The DOM bridge automatically applies TachUI modifiers to DOM elements:
const StyledComponent = createComponent(() => {
return Text('Styled Text')
.fontSize(24)
.backgroundColor('#f0f0f0')
.padding(16)
.cornerRadius(8)
})
// All modifiers are automatically applied to the DOM element
mountRoot(() => StyledComponent({}))Event Handler Binding ​
Component events are automatically connected to DOM event listeners:
const InteractiveButton = createComponent(() => {
const [count, setCount] = createSignal(0)
return Button(`Clicked ${count()} times`)
.onTap(() => setCount(c => c + 1))
.backgroundColor(count() > 5 ? '#ff4444' : '#4444ff')
})
mountRoot(() => InteractiveButton({}))Reactive Updates ​
The DOM bridge maintains reactive connections between signals and DOM:
const ReactiveDemo = createComponent(() => {
const [message, setMessage] = createSignal('Hello, TachUI!')
const [count, setCount] = createSignal(0)
return VStack([
Text(message)
.fontSize(18)
.foregroundColor('#333'),
Text(() => `Count: ${count()}`)
.fontSize(16)
.foregroundColor('#666'),
Button('Update')
.onTap(() => {
setCount(c => c + 1)
setMessage(`Updated ${count() + 1} times`)
})
])
})
mountRoot(() => ReactiveDemo({}))Rendering and Mounting ​
Basic Rendering ​
import { renderComponent } from '@tachui/core'
const App = createComponent(() => {
return h('div', null, 'My App')
})
const instance = App({})
const container = document.getElementById('app')!
// Render and get cleanup function
const cleanup = renderComponent(instance, container)
// Later, cleanup when needed
cleanup()Multiple Components ​
const Header = createComponent(() => h('header', null, 'Header'))
const Main = createComponent(() => h('main', null, 'Main'))
const Footer = createComponent(() => h('footer', null, 'Footer'))
const App = createComponent(() => {
const headerInstance = Header({})
const mainInstance = Main({})
const footerInstance = Footer({})
return h('div', { className: 'app' },
headerInstance.render(),
mainInstance.render(),
footerInstance.render()
)
})Memory Management ​
Automatic Cleanup ​
const ComponentWithCleanup = createComponent(() => {
const [data, setData] = createSignal(null)
// Setup subscription
const unsubscribe = dataService.subscribe(setData)
// Cleanup is handled automatically when component unmounts
onCleanup(unsubscribe)
return h('div', null, text(() => data() || 'Loading...'))
})Manual Cleanup ​
const manager = ComponentManager.getInstance()
// Clean up specific component
manager.unregisterComponent(componentId)
// Clean up all components
manager.cleanup()
// Clean up renderer resources
const renderer = new DOMRenderer()
renderer.cleanup()Performance ​
Efficient Updates ​
// Only the changed parts of the DOM are updated
const OptimizedComponent = createComponent(() => {
const [count, setCount] = createSignal(0)
const [name, setName] = createSignal('User')
return h('div', null,
// This text node only updates when count changes
h('p', null, text(() => `Count: ${count()}`)),
// This text node only updates when name changes
h('p', null, text(() => `Name: ${name()}`)),
// Static content never updates
h('p', null, 'This never changes')
)
})Batched Updates ​
import { batch } from '@tachui/core'
// Multiple updates are batched automatically
const updateMultiple = () => {
batch(() => {
setCount(c => c + 1)
setName('New Name')
setVisible(true)
// Only one DOM update occurs
})
}Development Tools ​
Component Tree Inspection ​
import { getComponentTree } from '@tachui/core'
// Get component hierarchy for debugging
const tree = getComponentTree()
console.log('Component tree:', tree)Performance Monitoring ​
import { enablePerformanceTracking } from '@tachui/core'
// Enable performance tracking in development
if (process.env.NODE_ENV === 'development') {
enablePerformanceTracking()
}Integration Examples ​
With SwiftUI Syntax ​
When using TachUI's SwiftUI syntax, the runtime system handles the execution:
// SwiftUI syntax (compiled by TachUI)
VStack {
Text("Hello, World!")
.font("24px")
.foregroundColor("blue")
Button("Click me")
.onTapGesture(() => handleClick())
}
// Compiles to runtime calls:
const container1 = document.createElement('div')
container1.className = 'tachui-v flex flex-col'
const textElement2 = document.createElement('span')
textElement2.className = 'tachui-text'
textElement2.textContent = "Hello, World!"
Object.assign(textElement2.style, {
fontSize: "24px",
color: "blue"
})
const buttonElement3 = document.createElement('button')
buttonElement3.textContent = "Click me"
buttonElement3.addEventListener('click', () => handleClick())
container1.appendChild(textElement2)
container1.appendChild(buttonElement3)With Reactive State ​
// Reactive state integration
@State count = 0
@Computed doubled = count * 2
VStack {
Text(`Count: ${count}`)
Text(`Doubled: ${doubled}`)
Button("Increment")
.onTapGesture(() => count++)
}
// Runtime handles reactive updates automaticallyPerformance Benchmarks ​
TachUI includes comprehensive performance benchmarks aligned with industry standards:
Running Benchmarks ​
# Quick performance check
npm run benchmark:quick
# Full benchmark suite with framework comparison
npm run benchmark:compare
# Individual benchmark tests
npm run benchmarkBenchmark Coverage ​
TachUI benchmarks cover all critical performance scenarios:
- Component Creation - Creating 1,000 components
- Mass Updates - Replacing all data at once
- Partial Updates - Updating every 10th row (most important for UX)
- User Interactions - Row selection and manipulation
- Memory Efficiency - Heap usage and cleanup
- Bundle Size - Framework overhead impact
Framework Comparisons ​
Benchmarks compare TachUI against major frameworks:
- React 18.2.0 (most popular)
- Vue 3.3.0 (progressive framework)
- SolidJS 1.7.0 (closest architecture)
- Svelte 4.0.0 (compile-time optimized)
- Angular 16.0.0 (enterprise framework)
- Preact 10.15.0 (lightweight alternative)
Performance Targets ​
TachUI aims for industry-leading performance:
- ✅ Sub-30ms component creation
- ✅ Sub-15ms reactive updates
- ✅ <8MB memory usage
- ✅ <20KB bundle size
Results are automatically scored on a 0-100 scale for easy tracking.
Next Steps ​
- Performance Benchmarks - Detailed benchmark documentation
- State Management - State management and dependency injection
- Performance Guide - Optimization techniques
- Component Guide - Component usage patterns
- Testing - Testing TachUI components