用 Express 和 Pug 构建 Node.js Web 应用(完整实战)
本文从零搭建一个 Express + Pug 的 Node.js Web 应用:服务器创建、开发热重载、Pug 模板渲染、静态文件服务、路由参数处理与错误处理,最后部署上线。
Express 负责路由与中间件,Pug 负责服务端模板渲染:npm i express pug 后 app.set('view engine', 'pug') 接入模板,路由里用 res.render('模板名', 数据) 输出 HTML,静态文件用 express.static 托管——这是 Node.js 服务端渲染的经典组合。
为什么是 Express + Pug
Express 是 Node.js 最流行的 Web 框架:路由、中间件、生态中间件库(表单、会话、安全头)应有尽有。Pug(前身 Jade)是缩进式模板引擎,消灭尖括号和闭合标签,与 Express 的视图系统开箱集成。这个组合适合内容型站点、管理后台、SEO 页面等服务端渲染场景。
搭建项目与服务器
mkdir hn-search && cd hn-search
npm init -y
npm install express pug
// index.js
const express = require('express');
const app = express();
app.set('view engine', 'pug');
app.set('views', './views');
app.use(express.static('public')); // 静态文件
app.get('/', (req, res) => {
res.render('index', { title: 'Hacker News 搜索' });
});
app.listen(3000, () => console.log('http://localhost:3000'));
开发期用 node --watch index.js(Node 20+ 内置热重载,无需 nodemon)。
Pug 模板:缩进即结构
//- views/index.pug
doctype html
html
head
title= title
link(rel='stylesheet', href='/style.css')
body
h1= title
form(action='/search', method='get')
input(type='text', name='q', placeholder='输入关键词')
button(type='submit') 搜索
= 输出转义内容(防 XSS),!= 原样输出(危险,仅限可信内容),#{} 在文本中插值。列表渲染用 each story in stories。
搜索路由与数据处理
app.get('/search', async (req, res) => {
const { q } = req.query;
if (!q) return res.redirect('/');
const response = await fetch(
`https://hn.algolia.com/api/v1/search?query=${encodeURIComponent(q)}`
);
const { hits } = await response.json();
res.render('search', {
q,
stories: hits.map(h => ({
...h,
created: new Date(h.created_at).toLocaleDateString('zh-CN')
}))
});
});
要点:req.query 取查询参数;外部请求用 Node 18+ 内置 fetch;日期在服务端格式化后再交给模板——模板里只放展示逻辑。
错误处理与 404
Express 的错误处理中间件固定四个参数,放在所有路由之后:
app.use((req, res) => {
res.status(404).render('404');
});
app.use((err, req, res, next) => {
console.error(err);
res.status(500).render('error', { message: '服务器开小差了' });
});
异步路由里的异常要显式 next(err) 传递(Express 4),或用 Express 5(自动捕获异步异常)。
部署要点
生产环境三件事:进程管理用 PM2(pm2 start index.js -i max 多实例);端口监听用环境变量 process.env.PORT;前面挡一层 Nginx 反向代理(静态资源、HTTPS 终止)。详细方案见本系列《PM2 完全指南》与《Nginx 反向代理 Node.js》。
验证接口上线后的延迟与错误
用 Express 和 Pug 构建 Node.js Web 应用(完整实战)完成开发验证后,可选一条包含数据库或外部调用的业务路径接入观测云。按 Node.js APM 文档确认探针初始化顺序与框架兼容性,检查请求及下游 Span 是否连续,再按文档注入日志关联字段。以路由模板或稳定的操作名聚合,避免用用户 ID、动态 URL 或完整 GraphQL 查询作为高基数标签。
接入文档:Node.js APM 接入 · 日志采集 · 日志与链路关联。
常见问题(FAQ)
Q:Pug 和 EJS、Handlebars 怎么选?
Pug 缩进语法最简洁但学习成本最高;EJS 就是嵌 JS 的 HTML,零学习成本;Handlebars 逻辑最少适合非开发协作。团队全栈 Node 选 Pug/EJS,模板要给设计师维护选 Handlebars。
Q:Express 4 的异步路由报错不进错误中间件?
Express 4 的异步 handler 抛异常需要 next(err) 显式传递,常见写法是包一层 asyncHandler 工具函数;升级到 Express 5 后异步异常自动进入错误中间件,推荐升级。
Q:这个组合适合做 SPA 后端吗?
不适合——前后端分离场景用 Express 出纯 JSON API 即可(res.json),不需要模板引擎。Pug 的价值在服务端直接产出 HTML 的场景。
参考文档
本文依据公开文档整理,示例需按项目依赖版本验证;不将文档中的性能描述视为本项目实测结果。