Template Caching
EJS caches compiled templates by default in production. This means the template is only parsed once, then reused for subsequent requests.
app.set('view cache', true);
app.set('views', './views');
app.set('view engine', 'ejs');
In development, you might want to disable caching so changes appear immediately.
app.set('view cache', process.env.NODE_ENV === 'production');
Try it Yourself →
Precompiling Templates
For critical templates, precompile them at application startup. This eliminates the compilation overhead on the first request.
const ejs = require('ejs');
const fs = require('fs');
const templateSource = fs.readFileSync('./views/home.ejs', 'utf8');
const compiledFn = ejs.compile(templateSource, { filename: 'home.ejs' });
app.get('/', (req, res) => {
const html = compiledFn({ title: 'Home', user: req.user });
res.send(html);
});
Precompiled templates are especially useful for high-traffic pages.
Minimizing Include Depth
Deeply nested includes slow down rendering. Each include requires disk I/O and template parsing. Keep your include tree shallow.
<%-- Deep nesting (slow) --%>
<%- include('partials/layout/header') %>
<%- include('partials/layout/nav') %>
<%- include('partials/layout/user-menu') %>
<%-- Flat structure (fast) --%>
<%- include('partials/header') %>
<%- include('partials/nav') %>
<%- include('partials/user-menu') %>
Aim for no more than 2-3 levels of include nesting.
Try it Yourself →Lazy Loading Components
Only include components when they're needed. Use conditional includes to skip unnecessary rendering.
<% if (showSidebar) { %>
<%- include('partials/sidebar') %>
<% } %>
<% if (notifications && notifications.length) { %>
<%- include('partials/notifications', { notifications }) %>
<% } %>
<% if (isAdmin) { %>
<%- include('partials/admin-panel') %>
<% } %>
Don't render components that won't be visible. This saves both processing time and bandwidth.
<%-- Bad: always includes the component --%>
<%- include('partials/heavy-chart') %>
<%-- Good: only includes when needed --%>
<% if (page === 'analytics') { %>
<%- include('partials/heavy-chart') %>
<% } %>
Minification
Minify your HTML output to reduce bandwidth. Use a middleware to compress rendered templates.
const minify = require('html-minifier').minify;
app.use((req, res, next) => {
const originalRender = res.render.bind(res);
res.render = (view, data, callback) => {
originalRender(view, data, (err, html) => {
if (err) return callback(err);
const minified = minify(html, {
collapseWhitespace: true,
removeComments: true,
minifyCSS: true
});
callback(null, minified);
});
};
next();
});
This removes whitespace and comments from your HTML output.
Try it Yourself →Measuring Performance
Profile your templates to find bottlenecks. Add timing middleware to track rendering speed.
app.use((req, res, next) => {
const start = Date.now();
const originalRender = res.render.bind(res);
res.render = (view, data, callback) => {
originalRender(view, data, (err, html) => {
const duration = Date.now() - start;
console.log(`Template ${view}: ${duration}ms`);
callback(err, html);
});
};
next();
});
Use this data to identify which templates need optimization.
<%-- Cache expensive computations --%>
<% const processedData = cachedComputation(rawData); %>
<%-- Use include caches for static content --%>
<%- cachedIncludes.footer %>