在上一个 Express + pnpm + ESM + 静态文件服务 项目基础上,添加模板引擎支持(EJS 和 Pug 二选一,这里先教 EJS,再教 Pug)。
模板引擎让你可以:
✅ 动态渲染 HTML(比如循环列表、条件判断)
✅ 复用页面结构(布局、组件)
✅ 分离逻辑与视图,代码更清晰
🧩 方案一:添加 EJS 模板引擎(推荐初学者)
EJS = Embedded JavaScript,语法接近 HTML + JS,学习成本低
✅ 步骤1:安装 EJS
pnpm add ejs
✅ 步骤2:配置 Express 使用 EJS
修改 index.js,在 const app = express(); 之后添加:
// 设置模板引擎为 EJS
app.set('view engine', 'ejs');
// 设置模板文件存放目录(默认是 ./views)
app.set('views', path.join(__dirname, 'views'));
完整 index.js 示例(关键部分):
// index.js
import express from 'express';
import path from 'path';
import { fileURLToPath } from 'url';
const __filename = fileURLToPath(import.meta.url);
const __dirname = path.dirname(__filename);
const app = express();
const PORT = process.env.PORT || 3000;
// 👇 设置 EJS 模板引擎
app.set('view engine', 'ejs');
app.set('views', path.join(__dirname, 'views'));
// 静态文件服务(CSS/JS/图片等)
app.use(express.static(path.join(__dirname, 'public')));
// 解析 JSON 请求体
app.use(express.json());
// 👇 示例路由:渲染 EJS 模板
app.get('/', (req, res) => {
res.render('index', {
title: '欢迎来到我的 EJS 网站',
message: '这是从后端传入的数据!',
users: [
{ name: 'Alice', age: 25 },
{ name: 'Bob', age: 30 },
{ name: 'Charlie', age: 35 }
]
});
});
// API 示例
app.get('/api/hello', (req, res) => {
res.json({ message: 'Hello from API!' });
});
// 404 页面
app.use((req, res) => {
res.status(404).send('<h1>404 - 页面走丢了 😢</h1><a href="/">返回首页</a>');
});
app.listen(PORT, () => {
console.log(`✅ Server is running at http://localhost:${PORT}`);
console.log(`🌍 访问首页: http://localhost:${PORT}`);
});
✅ 步骤3:创建 views 目录和模板文件
mkdir views
📄 创建 views/index.ejs
<!DOCTYPE html>
<html lang="zh">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title><%= title %></title>
<link rel="stylesheet" href="/css/style.css">
</head>
<body>
<div class="container">
<h1><%= title %></h1>
<p><%= message %></p>
<h2>👥 用户列表:</h2>
<ul>
<% users.forEach(user => { %>
<li><strong><%= user.name %></strong> - <%= user.age %>岁</li>
<% }) %>
</ul>
<img src="/images/express.png" alt="Express" width="150">
</div>
<script src="/js/app.js"></script>
</body>
</html>
💡 EJS 语法说明:
<%= 变量 %>→ 输出转义后的 HTML<%- 变量 %>→ 输出原始 HTML(慎用,有 XSS 风险)<% JavaScript代码 %>→ 执行 JS 逻辑(如循环、判断)
✅ 步骤4:确保 public 目录结构(复用之前的静态资源)
public/
├── css/style.css
├── js/app.js
└── images/express.png
如果还没创建,请参考上一节创建。
注意: 若是在上一节基础上创建,请修改 public/index.html 为其它名称;否则,默认显示还是该页面。
✅ 步骤5:运行项目
pnpm dev
你将看到:
- 页面标题和消息从后端动态传入
- 用户列表通过
forEach循环渲染 - 样式和图片正常加载
🧩 方案二:添加 Pug 模板引擎(简洁语法,适合喜欢缩进风格)
Pug(原名 Jade)使用缩进语法,代码更简洁,但学习曲线稍陡
✅ 步骤1:安装 Pug
pnpm add pug
✅ 步骤2:配置 Express 使用 Pug
修改 index.js:
// 替换 EJS 配置部分
app.set('view engine', 'pug');
app.set('views', path.join(__dirname, 'views'));
示例路由:
app.get('/', (req, res) => {
res.render('index', {
title: '欢迎来到我的 Pug 网站',
message: 'Pug 语法更简洁!',
users: [
{ name: 'Alice', age: 25 },
{ name: 'Bob', age: 30 },
{ name: 'Charlie', age: 35 }
]
});
});
✅ 步骤3:创建 Pug 模板 views/index.pug
doctype html
html(lang="zh")
head
meta(charset="UTF-8")
meta(name="viewport" content="width=device-width, initial-scale=1.0")
title= title
link(rel="stylesheet" href="/css/style.css")
body
.container
h1= title
p= message
h2 👥 用户列表:
ul
each user in users
li
strong= user.name
| - #{user.age}岁
img(src="/images/express.png" alt="Express" width="150")
script(src="/js/app.js")
💡 Pug 语法说明:
- 缩进代表嵌套
标签名(属性)如img(src="...")=输出变量each ... in ...循环#{变量}在文本中插值
✅ 步骤4:运行并访问
pnpm dev
效果和 EJS 几乎一样,但模板代码更短、更干净!
📂 最终项目结构(以 EJS 为例)
express-esm-ejs/
├── index.js
├── package.json
├── pnpm-lock.yaml
├── .gitignore
├── public/
│ ├── css/style.css
│ ├── js/app.js
│ └── images/express.png
└── views/
└── index.ejs 👈 或 index.pug
🆚 EJS vs Pug 对比(初学者如何选?)
| 特性 | EJS | Pug |
|---|---|---|
| 语法 | 类似 HTML + <% %> 标签 | 缩进语法,无闭合标签 |
| 学习难度 | ⭐⭐ 容易(熟悉 HTML) | ⭐⭐⭐ 需适应缩进 |
| 可读性 | 一般 | 高(结构清晰) |
| 社区支持 | 广泛 | 较小但稳定 |
| 推荐人群 | 初学者、HTML 熟悉者 | 喜欢简洁、有 Python 经验者 |
✅ 初学者推荐 EJS —— 因为它像 HTML,容易上手,调试直观。
🎉 恭喜你!
你已掌握:
✅ 在 Express + pnpm + ESM 项目中集成 EJS / Pug
✅ 动态渲染数据、循环、条件
✅ 模板 + 静态资源协同工作