Labs ICT
Pro Login

Performance Tips

Caching, minification, and optimization.

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 %>