0
# Express.js Integration
1
2
Native Express.js view engine support for seamless web application integration. Pug provides a built-in Express view engine that handles template rendering within the Express middleware pipeline.
3
4
## Capabilities
5
6
### Express View Engine Function
7
8
The `__express` function provides Express.js view engine interface compatibility.
9
10
```javascript { .api }
11
/**
12
* Express.js view engine interface
13
* @param path - Template file path
14
* @param options - View options from Express including locals
15
* @param fn - Express callback function
16
*/
17
function __express(path, options, fn);
18
```
19
20
**Usage Examples:**
21
22
```javascript
23
const express = require('express');
24
const pug = require('pug');
25
26
const app = express();
27
28
// Set Pug as the view engine
29
app.set('view engine', 'pug');
30
app.set('views', './views');
31
32
// Express routes using Pug templates
33
app.get('/', (req, res) => {
34
res.render('index', {
35
title: 'Home Page',
36
message: 'Welcome to our site!'
37
});
38
});
39
40
app.get('/user/:id', (req, res) => {
41
const user = getUserById(req.params.id);
42
res.render('user-profile', {
43
user: user,
44
isOwner: req.user && req.user.id === user.id
45
});
46
});
47
48
app.listen(3000);
49
```
50
51
### Express Configuration
52
53
**Basic Setup:**
54
55
```javascript
56
const express = require('express');
57
const app = express();
58
59
// Configure Pug as view engine
60
app.set('view engine', 'pug');
61
app.set('views', path.join(__dirname, 'views'));
62
63
// Optional: Configure Pug-specific settings
64
app.locals.pretty = true; // Pretty-print HTML (development only)
65
app.locals.cache = process.env.NODE_ENV === 'production';
66
```
67
68
**Advanced Configuration:**
69
70
```javascript
71
const express = require('express');
72
const pug = require('pug');
73
74
const app = express();
75
76
// Custom Pug configuration
77
app.engine('pug', (filePath, options, callback) => {
78
// Custom options for all Pug templates
79
const pugOptions = {
80
...options,
81
basedir: app.get('views'),
82
cache: app.get('env') === 'production',
83
compileDebug: app.get('env') !== 'production',
84
filters: {
85
markdown: (text) => require('markdown-it')().render(text),
86
currency: (amount) => '$' + parseFloat(amount).toFixed(2)
87
}
88
};
89
90
return pug.renderFile(filePath, pugOptions, callback);
91
});
92
93
app.set('view engine', 'pug');
94
```
95
96
### Template Directory Structure
97
98
Typical Express + Pug project structure:
99
100
```
101
project/
102
├── views/
103
│ ├── layout.pug # Base layout template
104
│ ├── index.pug # Home page
105
│ ├── error.pug # Error page
106
│ ├── partials/
107
│ │ ├── header.pug # Header component
108
│ │ ├── footer.pug # Footer component
109
│ │ └── nav.pug # Navigation
110
│ └── users/
111
│ ├── profile.pug # User profile
112
│ └── settings.pug # User settings
113
├── public/ # Static assets
114
├── routes/ # Express routes
115
└── app.js # Main application
116
```
117
118
### Template Inheritance with Express
119
120
**Layout Template (views/layout.pug):**
121
122
```pug
123
doctype html
124
html
125
head
126
title= title || 'My App'
127
link(rel='stylesheet', href='/css/style.css')
128
block head
129
body
130
include partials/header
131
main.container
132
block content
133
include partials/footer
134
script(src='/js/app.js')
135
block scripts
136
```
137
138
**Page Template (views/index.pug):**
139
140
```pug
141
extends layout
142
143
block head
144
meta(name='description', content='Welcome to our homepage')
145
146
block content
147
h1= title
148
p= message
149
150
if user
151
p Welcome back, #{user.name}!
152
else
153
a(href='/login') Please log in
154
155
block scripts
156
script(src='/js/homepage.js')
157
```
158
159
### Express Middleware Integration
160
161
**Template Variables Middleware:**
162
163
```javascript
164
// Add common variables to all templates
165
app.use((req, res, next) => {
166
res.locals.currentUser = req.user;
167
res.locals.currentPath = req.path;
168
res.locals.environment = app.get('env');
169
res.locals.moment = require('moment'); // Date utility
170
next();
171
});
172
173
// Now available in all templates
174
app.get('/dashboard', (req, res) => {
175
res.render('dashboard', {
176
title: 'Dashboard'
177
// currentUser, currentPath, environment, moment are automatically available
178
});
179
});
180
```
181
182
**Error Handling Middleware:**
183
184
```javascript
185
// Custom error page rendering
186
app.use((err, req, res, next) => {
187
res.status(err.status || 500);
188
189
if (req.accepts('html')) {
190
res.render('error', {
191
title: 'Error',
192
error: app.get('env') === 'development' ? err : {},
193
message: err.message,
194
status: err.status || 500
195
});
196
} else if (req.accepts('json')) {
197
res.json({ error: err.message });
198
} else {
199
res.type('txt').send(err.message);
200
}
201
});
202
```
203
204
### Advanced Express Features
205
206
**Conditional Rendering:**
207
208
```javascript
209
app.get('/products', (req, res) => {
210
const products = getProducts();
211
const viewMode = req.query.view || 'grid';
212
213
res.render('products', {
214
title: 'Products',
215
products: products,
216
viewMode: viewMode,
217
showFilters: products.length > 10,
218
isAdmin: req.user && req.user.role === 'admin'
219
});
220
});
221
```
222
223
**Template Caching Strategy:**
224
225
```javascript
226
const express = require('express');
227
const app = express();
228
229
// Environment-based caching
230
if (app.get('env') === 'production') {
231
app.enable('view cache'); // Enable Express view caching
232
app.locals.cache = true; // Enable Pug template caching
233
app.locals.compileDebug = false;
234
} else {
235
app.locals.pretty = true; // Pretty HTML in development
236
app.locals.compileDebug = true;
237
}
238
```
239
240
**Custom Helper Functions:**
241
242
```javascript
243
// Add helper functions to templates
244
app.locals.formatDate = (date) => {
245
return new Date(date).toLocaleDateString();
246
};
247
248
app.locals.truncate = (text, length = 100) => {
249
return text.length > length ? text.substring(0, length) + '...' : text;
250
};
251
252
app.locals.asset = (path) => {
253
// Asset versioning helper
254
const version = app.get('env') === 'production' ? '?v=1.0.0' : '';
255
return path + version;
256
};
257
258
// Usage in templates:
259
// p= formatDate(post.createdAt)
260
// p= truncate(post.content, 150)
261
// link(rel='stylesheet', href=asset('/css/style.css'))
262
```
263
264
### Performance Optimization
265
266
**Production Configuration:**
267
268
```javascript
269
const express = require('express');
270
const app = express();
271
272
if (process.env.NODE_ENV === 'production') {
273
// Enable all Express optimizations
274
app.enable('view cache');
275
app.set('trust proxy', 1);
276
277
// Pug optimizations
278
app.locals.cache = true;
279
app.locals.compileDebug = false;
280
app.locals.pretty = false;
281
282
// Precompile critical templates
283
const criticalTemplates = ['layout', 'index', 'error'];
284
criticalTemplates.forEach(template => {
285
pug.compileFile(`./views/${template}.pug`, { cache: true });
286
});
287
}
288
```
289
290
**Memory Management:**
291
292
```javascript
293
// Monitor template cache size in production
294
if (process.env.NODE_ENV === 'production') {
295
setInterval(() => {
296
const cacheSize = Object.keys(pug.cache).length;
297
console.log(`Template cache size: ${cacheSize}`);
298
299
if (cacheSize > 100) {
300
console.warn('Template cache is large, consider cleanup');
301
}
302
}, 300000); // Check every 5 minutes
303
}
304
```
305
306
### Error Handling
307
308
**Template Rendering Errors:**
309
310
```javascript
311
app.get('/user/:id', (req, res, next) => {
312
try {
313
const user = getUserById(req.params.id);
314
315
if (!user) {
316
return res.status(404).render('404', {
317
title: 'User Not Found',
318
message: 'The requested user could not be found.'
319
});
320
}
321
322
res.render('user-profile', { user });
323
} catch (err) {
324
// Template rendering error
325
console.error('Template error:', err);
326
next(err);
327
}
328
});
329
```
330
331
**Development Error Pages:**
332
333
```javascript
334
if (app.get('env') === 'development') {
335
app.use((err, req, res, next) => {
336
res.status(err.status || 500);
337
res.render('error', {
338
title: 'Development Error',
339
message: err.message,
340
error: err, // Full error object in development
341
stack: err.stack
342
});
343
});
344
}
345
```
346
347
### Testing Templates with Express
348
349
**Template Testing Setup:**
350
351
```javascript
352
const request = require('supertest');
353
const express = require('express');
354
355
const app = express();
356
app.set('view engine', 'pug');
357
app.set('views', './test/fixtures/views');
358
359
app.get('/test', (req, res) => {
360
res.render('test-template', { message: 'Hello Test' });
361
});
362
363
// Test template rendering
364
describe('Template Rendering', () => {
365
it('should render test template', (done) => {
366
request(app)
367
.get('/test')
368
.expect(200)
369
.expect(/<p>Hello Test<\/p>/)
370
.end(done);
371
});
372
});
373
```
374
375
**Mocking Template Data:**
376
377
```javascript
378
const mockData = {
379
users: [
380
{ id: 1, name: 'Alice', email: 'alice@example.com' },
381
{ id: 2, name: 'Bob', email: 'bob@example.com' }
382
]
383
};
384
385
app.get('/test-users', (req, res) => {
386
res.render('users', {
387
title: 'Test Users',
388
users: mockData.users
389
});
390
});
391
```
392
393
This completes the Express.js integration documentation, providing comprehensive coverage of how to use Pug as an Express view engine with practical examples and best practices.