Coherent.js Migration Guide
This guide helps developers migrate from traditional frameworks (React, Vue, Express, etc.) or template engines (Handlebars, EJS, etc.) to Coherent.js.
Coherent.js delivers exceptional performance with validated production metrics:
- 80.7KB gzipped production bundle
- 247 renders/sec performance with LRU caching
- 42.7% performance improvement over traditional OOP
- 79.5% tree shaking reduction for DevTools
Getting Started with Migration
Step 1: Install Coherent.js
pnpm add @coherent.js/core @coherent.js/state @coherent.js/api
# Development tools (tree-shakable)
pnpm add -D @coherent.js/devtoolsStep 2: Configure Package.json
{
"coherent": {
"enableTreeShaking": true,
"enableStreaming": true,
"enableLRUCaching": true,
"performance": {
"enableMetrics": true
}
}
}Step 3: Migrate State Management
import { createFormState, createListState } from '@coherent.js/state';
const userForm = createFormState({ name: '', email: '' });
const productList = createListState([], { pageSize: 20 });Step 4: Convert Components
const UserList = () => ({
div: {
className: 'user-list',
children: productList.sortedItems.map(user => UserCard(user))
}
});From React
Component Structure
React JSX:
function Greeting({ name }) {
return (
<div className="greeting">
<h1>Hello, {name}!</h1>
</div>
);
}Coherent.js Object:
function Greeting({ name }) {
return {
div: {
className: 'greeting',
children: [
{ h1: { text: `Hello, ${name}!` } }
]
}
};
}State Management
React with useState:
function Counter() {
const [count, setCount] = useState(0);
return (
<div>
<p>Count: {count}</p>
<button onClick={() => setCount(count + 1)}>Increment</button>
</div>
);
}Coherent.js with withState:
import { withState } from '@coherent.js/core';
const Counter = withState({ count: 0 })(({ state, setState }) => ({
div: {
children: [
{ p: { text: `Count: ${state.count}` } },
{ button: { text: 'Increment', onclick: () => setState({ count: state.count + 1 }) } }
]
}
}));Conditional Rendering
React:
function UserProfile({ user }) {
return (
<div>
{user ? <p>Welcome, {user.name}!</p> : <p>Please log in</p>}
</div>
);
}Coherent.js:
function UserProfile({ user }) {
return {
div: {
children: [
user
? { p: { text: `Welcome, ${user.name}!` } }
: { p: { text: 'Please log in' } }
]
}
};
}List Rendering
React:
function TodoList({ todos }) {
return (
<ul>
{todos.map(todo => (
<li key={todo.id} className={todo.completed ? 'completed' : 'pending'}>
{todo.text}
</li>
))}
</ul>
);
}Coherent.js:
function TodoList({ todos }) {
return {
ul: {
children: todos.map((todo) => ({
li: {
text: todo.text,
className: todo.completed ? 'completed' : 'pending'
}
}))
}
};
}React Performance Benefits
- 42.7% faster rendering with hybrid FP/OOP approach
- 100% cacheable pure functional components
- Better memory management with OOP state encapsulation
From Vue
Template System
Vue Template:
<template>
<div class="product-card">
<h3>{{ product.name }}</h3>
<p>${{ product.price }}</p>
<button @click="addToCart">Add to Cart</button>
</div>
</template>Coherent.js:
const ProductCard = (product) => ({
div: {
className: 'product-card',
children: [
{ h3: { text: product.name } },
{ p: { text: `${product.price}` } },
{ button: { text: 'Add to Cart', onclick: () => addToCart(product) } }
]
}
});Vue State Management
Vue Composition API:
import { ref, computed } from 'vue';
const cart = ref([]);
const total = computed(() => cart.value.reduce((sum, item) => sum + item.price, 0));Coherent.js:
const shoppingCart = createListState([]);
shoppingCart.addToCart = (product) => {
shoppingCart.addItem(product);
updateTotal();
};From Template Engines (Handlebars, EJS)
Basic Template
Handlebars:
<div class="greeting">
<h1>Hello, {{name}}!</h1>
<p>You have {{notifications}} notifications</p>
</div>Coherent.js:
function Greeting({ name, notifications }) {
return {
div: {
className: 'greeting',
children: [
{ h1: { text: `Hello, ${name}!` } },
{ p: { text: `You have ${notifications} notifications` } }
]
}
};
}Conditional Blocks
Handlebars:
{{#if user}}
<p>Welcome, {{user.name}}!</p>
{{else}}
<p>Please log in</p>
{{/if}}Coherent.js:
function UserProfile({ user }) {
return {
div: {
children: [
user
? { p: { text: `Welcome, ${user.name}!` } }
: { p: { text: 'Please log in' } }
]
}
};
}From String Concatenation
String Concatenation:
function createGreeting(name) {
return `<div class="greeting"><h1>Hello, ${name}!</h1></div>`;
}Coherent.js:
import { render } from '@coherent.js/core';
function Greeting({ name }) {
return {
div: {
className: 'greeting',
children: [{ h1: { text: `Hello, ${name}!` } }]
}
};
}
const html = render(Greeting({ name: 'World' }));From Express to Coherent.js API
Route Definition
Express:
app.get('/api/users/:id', async (req, res) => {
try {
const user = await getUser(req.params.id);
res.json(user);
} catch (error) {
res.status(500).json({ error: error.message });
}
});Coherent.js API (with LRU caching):
const api = createAPI({
routes: {
'GET /api/users/:id': async ({ params }) => {
const user = await getUser(params.id);
return { status: 200, body: user };
}
},
enableLRUCaching: true,
cacheSize: 1000
});Hydration Migration
One of the most critical aspects when migrating from client-side frameworks is understanding how to make server-rendered components interactive.
From React Hydration
React (automatic):
function Counter() {
const [count, setCount] = useState(0);
return <button onClick={() => setCount(count + 1)}>Count: {count}</button>;
}Coherent.js (explicit hydration):
// Server-side component
const Counter = withState({ count: 0 })(({ state, stateUtils }) => {
const { setState } = stateUtils;
return {
div: {
'data-coherent-component': 'counter',
children: [
{ p: { text: `Count: ${state.count}` } },
{ button: { text: 'Increment', onclick: () => setState({ count: state.count + 1 }) } }
]
}
};
});
// Client-side hydration
import { autoHydrate } from '@coherent.js/client';
document.addEventListener('DOMContentLoaded', () => {
autoHydrate({ counter: Counter });
});Key Hydration Differences
Event Handler Serialization: In Coherent.js, event handlers become
data-actionattributes during SSR, then are reconnected during hydration.Component Identification: Uses explicit
data-coherent-componentattributes instead of React's reconciliation.State Initialization: Extract from DOM or pass through props rather than automatic matching.
Progressive Enhancement Pattern
{
form: {
action: '/api/submit', // Fallback for no-JS
method: 'POST',
onsubmit: enhancedSubmit, // Enhanced with hydration
children: [
{ input: { name: 'email', required: true } },
{ button: { type: 'submit', text: 'Submit' } }
]
}
}Common Patterns
Event Handling
Before (React): <button onClick={handleClick}>Click me</button>
After (Coherent.js): { button: { text: 'Click me', onclick: handleClick } }
Styling
Before: <div className="container highlighted">Content</div>
After: { div: { className: 'container highlighted', text: 'Content' } }
Data Attributes
Before: <div data-id="123" data-role="button">Content</div>
After: { div: { 'data-id': '123', 'data-role': 'button', text: 'Content' } }
Performance Optimization
Bundle Size Optimization
// Avoid: Import entire DevTools
import DevTools from '@coherent.js/devtools';
// Recommended: Tree-shakable imports
import { logComponentTree } from '@coherent.js/devtools/visualizer';
import { createPerformanceDashboard } from '@coherent.js/devtools/performance';Production Bundle Results
Core: 45.9KB gzipped
State: 8.5KB gzipped
API: 10.6KB gzipped
DevTools (selective): 15.7KB gzipped
Total: 80.7KB gzipped production bundle
Tree Shaking: 79.5% reduction (128.8KB -> 27KB selective)Build Configuration
// vite.config.js
export default {
build: {
rollupOptions: {
output: {
manualChunks: {
'coherent-core': ['@coherent.js/core'],
'coherent-state': ['@coherent.js/state']
}
}
},
minify: 'terser',
target: 'es2020'
}
};Key Benefits of Migrating to Coherent.js
- Universal Rendering: Same components work on server and client
- Type Safety: Full TypeScript support with built-in type definitions
- Performance: Built-in performance monitoring and optimization
- Security: Automatic HTML escaping and XSS protection
- No Build Step: Pure JavaScript with no compilation required
- Progressive Enhancement: Forms and interactions work without JavaScript
- Streaming: Native support for streaming large documents
- Memory Efficiency: Smart caching and object pooling
Migration Checklist
Server-Side Migration
- Identify components that need to be converted
- Convert JSX/templates to Coherent.js object structure
- Replace state management with
withState - Update event handling (onclick, etc.)
- Add
data-coherent-componentattributes for interactive components - Test server-side rendering output
Client-Side Hydration Setup
- Install
@coherent.js/clientpackage - Create hydration entry point (
hydration.js) - Set up component registry for
autoHydrate - Bundle hydration script for the browser
- Add hydration script to HTML pages
- Handle timing with
DOMContentLoadedevents - Test interactive features after hydration
- Verify no hydration mismatch warnings
Testing and Optimization
- Verify performance improvements
- Test progressive enhancement (works without JS)
- Implement selective hydration for performance
- Configure tree shaking for production
- Test bundle size (target: <85KB gzipped)
- Validate performance (target: 240+ renders/sec)
- Update build/deployment processes
For more details, see Advanced Components, Hydration Guide, and Performance Optimizations.