EJS
EJS(Embedded JavaScript templates)在 HTML 中嵌入 JavaScript,常用于 Express 服务端渲染(SSR)。
一、EJS 基础概念
- 什么是 EJS:Embedded JavaScript templates,是一款简单高效的嵌入式 JavaScript 模板引擎。
- 核心定位:允许在 HTML 中嵌入 JavaScript 代码,实现动态内容生成和复用。
- 主要优势:语法简单、可内嵌 JavaScript、与 Express 无缝集成。
- 模板文件后缀:
.ejs
二、安装与基础使用
1. 安装
npm install ejs
也可同时安装 Express(如需配合使用):
npm install express ejs
2. 核心 API
| 方法 | 说明 |
|---|---|
ejs.compile(str, options) | 编译模板字符串为可复用的渲染函数 |
ejs.render(str, data, options) | 渲染模板字符串,直接输出 HTML |
ejs.renderFile(filename, data, options, callback) | 读取并渲染模板文件 |
const ejs = require("ejs");
// 方式一:compile(适合多次使用同一模板)
const template = ejs.compile("<h1><%= name %></h1>");
const html = template({ name: "张三" });
// 方式二:render(一次性渲染)
const html2 = ejs.render("<h1><%= name %></h1>", { name: "李四" });
// 方式三:renderFile(从文件读取)
ejs.renderFile("./views/index.ejs", { title: "首页" }, (err, html) => {
if (err) throw err;
console.log(html);
});
三、核心标签语法
EJS 使用特殊的标签在 HTML 中嵌入 JavaScript 代码。
| 标签 | 说明 | 示例 |
|---|---|---|
<%= ... %> | 输出标签:输出变量值,自动 HTML 转义(防止 XSS) | <h1><%= title %></h1> |
<%- ... %> | 原始输出标签:输出未经转义的原始 HTML(慎用,需确保内容安全) | <div><%- article.content %></div> |
<% ... %> | 脚本标签:执行 JavaScript 逻辑(条件、循环等),不输出内容 | <% if (user) { %><% } %> |
<%# ... %> | 注释标签:添加注释,不会出现在最终输出中 | <%# 这是注释 %> |
<%_ ... _%> | 空白修剪标签:自动去除标签前后的空白字符 | <%_ for (...) { _%> |
<%% %%> | 原始标签:输出 <% 或 %> 字符本身,避免被解析 | <p>使用<%%= variable %%>输出</p> |
四、条件渲染
<% if (isLoggedIn) { %>
<p>欢迎回来,<%= user.name %>!</p>
<% } else { %>
<p>请先登录。</p>
<% } %>
五、循环
<ul>
<% products.forEach(product => { %>
<li><%= product.name %> - ¥<%= product.price %></li>
<% }) %>
</ul>
六、Include 机制(模块化)
<%- include('partial') %> 用于在模板中引入其他模板文件,实现代码复用。
- 基础用法:js
<%- include('header') %> <main>页面内容</main> <%- include('footer') %> - 传递参数给被包含的模板:js
<%- include('user/profile', { user: currentUser }) %> - 文件夹结构示例:text
views/ ├── index.ejs # 主模板 └── partials/ ├── header.ejs # 导航栏 └── footer.ejs # 页脚
七、Layout / 模板继承
EJS 原生不支持完整的模板继承(如 Jinja2 的 extends、block),需要通过以下方式实现:
- 使用 Include 组织 Layout(最常用):js
<!-- layout.ejs --> <!DOCTYPE html> <html> <head><title><%= title %></title></head> <body> <%- include('header') %> <%- body %> <%- include('footer') %> </body> </html> - 使用
express-ejs-layouts中间件:bashnpm install express-ejs-layoutsjavascriptconst expressLayouts = require("express-ejs-layouts"); app.use(expressLayouts); // 默认使用 views/layout.ejs - 手动传递 Layout 数据:通过局部变量或第三方库(如
ejs-locals)组织布局块。
八、与 Express 集成
const express = require("express");
const app = express();
// 1. 设置模板引擎为 ejs
app.set("view engine", "ejs");
// 2. 设置模板文件存放目录(默认可不写)
app.set("views", path.join(__dirname, "views"));
// 3. 在路由中使用 res.render() 渲染
app.get("/", (req, res) => {
res.render("index", {
title: "首页",
user: { name: "张三", isAdmin: true },
});
});
九、常用配置选项
通过 options 参数配置 EJS 行为:
| 选项 | 类型 | 说明 |
|---|---|---|
cache | Boolean | 是否缓存编译后的函数 |
filename | String | 必须在 cache 为 true 时指定,用于 Include 与缓存 |
root | String/Array | Include 文件的根路径 |
views | Array | 解析相对路径 Include 时使用的路径列表 |
compileDebug | Boolean | 为 false 时不编译调试信息(提升性能) |
client | Boolean | 为 true 时返回可在浏览器端独立运行的编译函数 |
debug | Boolean | 输出生成的函数体 |
strict | Boolean | 生成的渲染函数以严格模式运行 |
escape | Function | 自定义 HTML 转义函数 |
async | Boolean | 启用异步渲染 |
delimiter / openDelimiter / closeDelimiter | String | 自定义标签定界符 |
十、缓存机制
EJS 内置基础缓存(ejs.cache),用于存储编译后的模板函数。搭配 LRU 缓存可有效控制内存上限,避免缓存无限膨胀。
- 清除缓存:javascript
ejs.clearCache(); - 使用 LRU 缓存:javascript
const ejs = require("ejs"); const LRU = require("lru-cache"); ejs.cache = new LRU(100); // 最多缓存 100 个模板
十一、调试与常见问题
- 开启调试模式:javascript
ejs.render(str, { debug: true }); - 变量未渲染:检查是否误将输出内容放在
<% ... %>而非<%= ... %>中。 - Include 路径错误:确保
include路径相对于主模板,或通过options.views/options.root指定绝对路径。 - 安全性注意事项:不要直接渲染用户提交的模板,也不要将
req.query当成数据渲染,否则可能引发 XSS 或远程代码执行漏洞。
十二、EJS 适用场景
- 需要在服务端生成带动态内容的 HTML(利于 SEO)
- 快速原型开发,希望用最简单的方式实现模板化展示
- 与 Express 配合,实现传统的“后端 MVC”模式
补充说明:需要完整
extends/block继承时,可考虑 Pug 或 Nunjucks。
参考文献
以下链接在编写时均可正常访问:
| 资料 | 说明 |
|---|---|
| EJS 文档 | 官方 |
| express-ejs-layouts | Layout 中间件 |
| Express 模板引擎 | 集成方式 |
相关文章
后端入门概览
本目录覆盖 JavaScript/TypeScript 服务端运行时与框架、数据存储,以及 Rust 系统编程入门,提供从零到部署的完整学习路径。前置建议:JavaScript 基础、工程化 · 环境变量。
Bun 基础与核心命令
Bun 是用 Zig 编写的 JavaScript 运行时,内置包管理(bun install)、打包(bun build)、测试(bun test)等,并持续兼容 Node.js API。本文介绍核心特点、安装方式,以及日常最常用的命令与包管理功能。见 运行时对比。
HTTP 服务器
Bun 内置了高性能的 HTTP 服务器,通过 Bun.serve 可以轻松启动服务。从 Bun v1.2.3 开始,推荐使用 routes 对象来定义路由,更加直观和灵活。
文件系统
Node.js 的 fs 模块提供了与文件系统交互的 API,几乎涵盖了所有标准文件操作。它支持三种风格的 API:同步、回调式异步 和 Promise 式异步。下面详细介绍这些 API 的选择策略、流式读写、文件监视以及常用操作。
Deno 基础
Deno 是基于 V8 与 Rust 的 JavaScript/TypeScript 运行时,由 Node.js 原作者 Ryan Dahl 发起。官方文档:docs.deno.com。与 Node、Bun 的对比见 运行时对比。
异常处理器
Series
end
25 / 69