Advanced Usage¶
This guide covers advanced miki-template features: caching, library system, i18n, and more.
Table of Contents¶
Caching¶
miki-template caches compiled templates for performance. The cache is an in-memory LRU with a 100-entry limit.
Clearing the Cache¶
When to Clear Cache¶
-
Development — when templates change frequently on disk
-
Tests — to ensure fresh compilation
-
Runtime filter/tag registration — when dynamically registering custom tags/filters
// Development middleware that clears cache on file changes
const { clearCache } = require('miki-template');
if (process.env.NODE_ENV !== 'production') {
fs.watch('./views', () => {
clearCache();
console.log('Template cache cleared');
});
}
How Caching Works¶
-
Templates are cached by source string and compile options.
-
The cache key combines the template source and the options object (views, custom settings).
-
Cached templates are reused across renders, improving performance for repeated templates.
Library System¶
Libraries are bundles of filters, tags, and helpers that can be loaded into templates. Built-in libraries (humanize, cache, lorem, markdown, i18n) are auto-activated.
Registering a Library¶
const { registerLibrary } = require('miki-template');
registerLibrary('myutils', {
filters: {
shout: (val) => String(val).toUpperCase() + '!',
whisper: (val) => String(val).toLowerCase() + '...'
},
tags: {
timestamp: (tagContent, parser) => ({
render: () => new Date().toISOString()
})
},
helpers: {
formatPrice: (val) => `$${Number(val).toFixed(2)}`
}
});
import { registerLibrary } from 'miki-template';
registerLibrary('myutils', {
filters: {
shout: (val) => String(val).toUpperCase() + '!',
whisper: (val) => String(val).toLowerCase() + '...'
},
tags: {
timestamp: (tagContent, parser) => ({
render: () => new Date().toISOString()
})
},
helpers: {
formatPrice: (val) => `$${Number(val).toFixed(2)}`
}
});
Loading Libraries in Templates¶
Once registered, load the library with {% load %}:
Built-in Libraries¶
The following libraries are auto-activated (no {% load %} needed):
| Library | Features |
|---------|----------|
| humanize | Natural date formatting, number formatting |
| cache | Cache control tags and filters |
| lorem | Lorem ipsum placeholder text |
| markdown | {{ content|markdown }} filter for Markdown→HTML |
| i18n | {% trans %} and {% blocktrans %} for translations |
Deactivating and Re-registering¶
i18n / Internationalization¶
miki-template includes a built-in i18n system supporting {% trans %} and {% blocktrans %} tags.
Registering Translations¶
Setting Fallback Language¶
Template Usage¶
Managing Languages¶
Template Discovery¶
The findTemplateInViews() function intelligently locates templates in nested directories.
const { findTemplateInViews, setAppTemplateDirNames } = require('miki-template');
// Customize which directory names are treated as app template roots
setAppTemplateDirNames(['templates', 'views', 'pages']);
// Search for a template by name
const found = findTemplateInViews('home', ['./views', './app/templates']);
console.log(found);
// → /absolute/path/to/app/templates/home.html
Partial Templates¶
Partials let you define reusable template fragments using {% partialdef %} and render them on demand.
Defining and Rendering Partials¶
{% partialdef card %}
<div class="card">
<h3>{{ user.name }}</h3>
<p>{{ user.email }}</p>
</div>
{% endpartialdef %}
Render a partial:
const { render, compile } = require('miki-template');
// Using render() with file partials:
const html = render('home#card', { user: userData }, { views: './views' });
// Using compiled.renderPartial():
const compiled = compile(templateString);
const partialHtml = compiled.renderPartial('card', { user: userData });
Partial with Context¶
{% partialdef greeting %}
Hello, {{ name }}! You have {{ count }} messages.
{% endpartialdef %}
{% partial greeting with name="Alice" count=3 %}
Extending the Engine¶
Registering Custom Tags¶
const { registerTag } = require('miki-template');
registerTag('markdown', (tagContent, parser) => {
const nodelist = parser.parse(['endmarkdown']);
parser.skipTag();
const { marked } = require('marked');
return {
render: (context) => {
const body = nodelist.map(n => n.render(context)).join('');
return markSafe(marked(body));
}
};
});
import { registerTag, markSafe } from 'miki-template';
import { marked } from 'marked';
registerTag('markdown', (tagContent, parser) => {
const nodelist = parser.parse(['endmarkdown']);
parser.skipTag();
return {
render: (context) => {
const body = nodelist.map(n => n.render(context)).join('');
return markSafe(marked(body));
}
};
});