Skip to main content

Server-side rendering

You can get rendered components via the registry rest api.

curl http://my-components-registry.mydomain.com/hello-world

{
"href": "https://my-components-registry.mydomain.com/hello-world",
"version": "1.0.0",
"requestVersion": "",
"html": "<oc-component href=\"https://my-components-registry.mydomain.com/hello-world\" data-hash=\"cad2a9671257d5033d2abfd739b1660993021d02\" id=\"2890594349\" data-rendered=\"true\" data-version=\"1.0.13\">Hello John doe!</oc-component>",
"type": "oc-component",
"renderMode": "rendered"
}

Nevertheless, for improving caching and response size, when using the node.js client or any language capable of executing server-side javascript the request will look more like:

 curl http://my-components-registry.mydomain.com/hello-world/~1.0.0 -H Accept:application/vnd.oc.unrendered+json

{
"href": "https://my-components-registry.mydomain.com/hello-world/~1.0.0",
"version": "1.0.0",
"requestVersion": "~1.0.0",
"data": {
"name": "John doe"
},
"template": {
"src": "https://s3.amazonaws.com/your-s3-bucket/components/hello-world/1.0.0/template.js",
"type": "oc-template-es6",
"key": "cad2a9671257d5033d2abfd739b1660993021d02"
},
"type": "oc-component",
"renderMode": "unrendered"
}

In this case you get the compiled view + the data, and you can do the rendering, eventually, interpolating the view-model data and rendering the compiled view with it.

When retrieving multiple components, a batch POST endpoint allows to make a single request to the API.

Web Framework Integration Examples

Express.js Integration

const express = require('express');
const oc = require('oc-client-node');

const app = express();
const client = oc.Client({
registries: ['https://my-registry.com'],
components: {
cache: {
type: 'memory',
options: {
max: 100,
maxAge: 1000 * 60 * 5 // 5 minutes
}
}
}
});

app.get('/', async (req, res) => {
try {
const header = await client.renderComponent('header', { user: req.user });
const footer = await client.renderComponent('footer');

res.render('index', { header: header.html, footer: footer.html });
} catch (error) {
console.error('Component rendering failed:', error);
res.render('index', { header: '', footer: '' });
}
});

Koa.js Integration

const Koa = require('koa');
const oc = require('oc-client-node');

const app = new Koa();
const client = oc.Client({ registries: ['https://my-registry.com'] });

app.use(async (ctx) => {
try {
const components = await Promise.all([
client.renderComponent('navigation'),
client.renderComponent('content', { page: ctx.path })
]);

ctx.body = `
<html>
<body>
${components[0].html}
${components[1].html}
</body>
</html>
`;
} catch (error) {
ctx.status = 500;
ctx.body = 'Error rendering components';
}
});

Next.js Integration

// pages/api/components/[...component].js
import oc from 'oc-client-node';

const client = oc.Client({
registries: ['https://my-registry.com']
});

export default async function handler(req, res) {
const { component } = req.query;
const componentName = component[0];

try {
const result = await client.renderComponent(componentName, req.query);
res.status(200).json(result);
} catch (error) {
res.status(500).json({ error: 'Component rendering failed' });
}
}

Caching Strategies

Redis Caching

const redis = require('redis');
const client = redis.createClient();

const ocClient = oc.Client({
registries: ['https://my-registry.com'],
components: {
cache: {
type: 'redis',
options: {
client: client,
prefix: 'oc:',
ttl: 300 // 5 minutes
}
}
}
});

Memory Caching with LRU

const LRU = require('lru-cache');

const cache = new LRU({
max: 500,
maxAge: 1000 * 60 * 10 // 10 minutes
});

const ocClient = oc.Client({
registries: ['https://my-registry.com'],
components: {
cache: {
type: 'memory',
options: cache
}
}
});

Error Handling

Graceful Fallbacks

async function renderComponentWithFallback(name, params, fallback = '') {
try {
const result = await client.renderComponent(name, params);
return result.html;
} catch (error) {
console.error(`Component ${name} failed:`, error);
return fallback;
}
}

// Usage
const header = await renderComponentWithFallback('header', { user }, '<header>Default Header</header>');

Timeout Handling

const client = oc.Client({
registries: ['https://my-registry.com'],
timeout: 5000, // 5 seconds
retry: 3
});

Available Clients