Which strategy ensures zero-downtime migration to Pug for existing Node.js views?
0 reputation · 29 Oct 2021, 19:35 UTC
0 reputation · 29 Oct 2021, 19:35 UTC
A small application currently utilizing a standard HTML-based template engine needs to migrate to Pug to leverage its indentation-based syntax and reusable mixins. Because Pug requires a complete rewrite of view files rather than a simple syntax conversion, the migration cannot happen incrementally within a single file.
The primary constraint is maintaining 100% availability during the transition. Since the application serves live traffic, switching the view engine configuration globally in the application settings would cause an immediate failure for any views not yet converted to the .pug format.
What architectural approach allows for a phased rollout where both the legacy engine and Pug coexist during the transition? Does the Node.js environment support multiple view engines simultaneously based on file extensions?
35275 reputation · 29 Oct 2021, 22:47 UTC
Yes, Express can render multiple view engines simultaneously by mapping each engine to a distinct file extension. The safest, zero‑downtime approach is to keep the legacy views with their original extension (e.g., .html or .ejs) and register Pug for .pug. Then, for each route you migrate, change the view file name and route reference atomically, or guard the switch behind a feature flag or request header.
app.engine(ext, fn) registers a renderer for ext. The last registration wins for that extension.res.render('index') will look for index.pug if .pug is registered, otherwise index.html (or index.ejs) if that extension is registered.X-Use-Pug) or a feature‑flag environment variable to decide which file to render.const express = require('express');
const app = express();
// Legacy engine (e.g., EJS)
app.engine('html', require('ejs').__express);
app.set('view engine', 'html');
app.set('views', __dirname + '/views');
// Pug engine
app.engine('pug', require('pug').__express);
*.html (or *.ejs).*.pug..pug until the route that uses it is updated atomically.app.use((req, res, next) => {
const usePug = process.env.USE_PUG === 'true' || req.headers['x-use-pug'] === 'true';
req.usePug = usePug;
next();
});
app.get('/dashboard', (req, res) => {
const view = req.usePug ? 'dashboard' : 'dashboard'; // same name, different extension
res.render(view);
});
When req.usePug is true, Express will resolve dashboard.pug; otherwise dashboard.html.
Deploy a new version that:
dashboard.pug.dashboard (no extension in res.render).dashboard.html only after all traffic is routed to Pug.X-Use-Pug: true and confirm the Pug view renders.Once all routes use .pug and the legacy files are removed, you can drop the legacy engine registration or keep it for safety. The application will continue to serve traffic without downtime because the rendering logic is controlled by extensions and optional flags.
Use comments to ask for clarification. Post a solution as an answer.
No question comments on this page.