Reference 速查手册:EJS 模板引擎完全指南 —— 标签、核心 API、选项与 CLI
【免费下载链接】reference面向开发者的技术速查清单(Cheat Sheets)集合,整理常见技术、工具与开发流程,帮助快速查阅关键信息,提高开发效率。项目地址: https://gitcode.com/GitHub_Trending/referen/reference
EJS(Embedded JavaScript,嵌入式 JavaScript)是一种简单的模板语言,允许你用纯 JavaScript 生成 HTML 标记,是 Node.js 服务端渲染中最常用的模板引擎之一。本文基于本仓库(Quick Reference 中文速查清单)中的 EJS 备忘清单,系统整理 EJS 的标签语法、核心 API、选项参数与命令行用法,帮助你在服务端渲染、静态页面生成和浏览器端模板场景中快速上手并可复制运行。
一、安装与定位
EJS 通过 npm 安装:
$ npm install ejs本仓库将该清单收录在 README 的 Nodejs 分区(与 Express.js、Koa.js、Jest 等并列),图标资源见 assets/ejs.svg。一个典型的配套场景是 Express 应用:从 Express 速查 可以看到express生成器提供-e, --ejs参数用于添加 ejs 引擎支持,说明 EJS 常作为 Node.js Web 框架的默认视图层。
二、Hello World 快速开始
创建一个hello.ejs模板文件:
<% if (user.email) { %> <h1><%= user.email %></h1> <% } %>然后通过 EJS 自带的 CLI 直接渲染并指定输出文件:
$ ejs hello.ejs -o hello.html这一过程即「模板 + 数据 → 渲染后的 HTML」。数据可以来自命令行参数、JSON 数据文件,也可以来自程序代码。
三、用数据渲染(ejs.render)
向EJS传递模板字符串和一些数据,是最基础的编程式用法:
let ejs = require('ejs'); let people = ['geddy', 'neil', 'alex']; let tpl = '<%= people.join(", "); %>'; let html = ejs.render(tpl, { people: people }); console.log(html); // 输出:geddy, neil, alex注意<%= %>内的 JS 表达式结果会被转义后写入输出,因此这里生成的是安全的纯文本。
四、标签体系:EJS 语法的骨架
EJS 的全部能力都建立在 9 种标签之上,这是速查表中必须烂熟于心的部分:
| 标签 | 描述 |
|---|---|
<% | 'Scriptlet' 标签,用于控制流,无输出 |
<%_ | "Whitespace Slurping" Scriptlet 标签,删除其前面的所有空格 |
<%= | 将值输出到模板中(HTML 转义) |
<%- | 将未转义的值输出到模板中 |
<%# | 注释标签,不执行,不输出 |
<%% | 输出文字<% |
%> | 普通结束标签 |
-%> | 修剪模式('newline slurp')标签,修剪换行符后的内容 |
_%> | "Whitespace Slurping" 结束标签,删除其后的所有空格 |
其中三类标签最常用:
<%= %>:打印变量的值,输出前进行 HTML 转义,适合渲染用户输入;<%- %>:打印时不进行 HTML 转义,适合输出已拼好的 HTML 片段或 include 的模板内容;<% %>:执行任意 JavaScript 控制流语句(if/for/forEach 等),本身不产生输出。
关于转义差异的安全含义:<%=默认转义 XML 字符,能防注入;<%-则会原样输出,使用时要确保内容来源可信(官方清单中也明确两者「打印变量的值」与「打印时不进行 HTML 转义」的区别)。
五、注释
EJS 提供不输出、不执行的注释标签<%#:
<%# 该行将表示一条注释 %>也支持跨越多行,注释内容不会显示在最终的 HTML 输出中:
<%# 这是一个多行 EJS 注释。 它可以跨越多行, 但不会显示 在最终的 HTML 输出中。 %>调试模板时,可以用多行注释记录设计意图,而不必手动删除。
六、核心 API 方法
EJS 对外暴露三类核心方法,对应「编译复用」「一次性渲染」「文件渲染」三种场景:
let ejs = require('ejs'); let template = ejs.compile(str, options); template(data); // => 渲染的 HTML 字符串 ejs.render(str, data, options); // => 渲染的 HTML 字符串 ejs.renderFile(filename, data, options, function(err, str){ // str => 渲染的 HTML 字符串 } );ejs.compile(str, options):将模板字符串编译为可复用函数,适合在同一进程中多次渲染同一模板;ejs.render(str, data, options):一步完成编译 + 渲染,适合一次性场景;ejs.renderFile(filename, data, options, cb):从磁盘读取模板文件并渲染,回调返回渲染结果字符串,适合 Web 请求场景。
七、包括文件(include)
模板拆分是 EJS 组织大型页面的关键。基本用法:
<%- include('partials/navbar.ejs') %>包含时传递数据(第二个参数是传给子模板的局部数据对象):
<% include('header', { title: 'My Page' }) %>在循环中包含模板是典型用法:
<ul> <% users.forEach(function(user){ %> <%- include('item', {user: user}); %> <% }); %> </ul>重要约束:要包含模板,渲染时必须提供filename选项,include 的路径是相对于当前模板文件解析的。也就是说,直接ejs.render('<%- include("x") %>', data)会报错,需写成ejs.render(tpl, data, { filename: 'index.ejs' })或改用ejs.renderFile。
八、控制流:条件与循环
条件语句(原文档位于 docs/ejs.md 「文档 / 条件句」一节):
<% if (userLoggedIn) { %> <p>Welcome, <%= username %>!</p> <% } else { %> <p>Please log in.</p> <% } %>循环语句在<% %>标签内直接写 JS 迭代逻辑,上面「包括文件」中的forEach示例就是一个完整循环;更常见的写法:
<ul> <% users.forEach(function(user, i){ %> <li><%= i %>: <%= user %></li> <% }); %> </ul><% %>标签内是原生 JavaScript,因此if / for / while / map / filter等全部可用,这也是 EJS 被称作「嵌入式 JavaScript」的原因。
九、自定义分隔符
当<%与模板所在技术(如 PHP 的<?、Blade 语法等)冲突时,可以更换分隔符。两种方式:
let ejs = require('ejs'), users = ['geddy', 'neil', 'alex']; // 方式一:按次指定,只需一个模板 ejs.render('<?= users.join(" | "); ?>', {users: users}, {delimiter: '?'}); // => 'geddy | neil | alex' // 方式二:全局范围内修改 ejs.delimiter = '$'; ejs.render('<$= users.join(" | "); $>', {users: users}); // => 'geddy | neil | alex'对应的三个选项分别是delimiter(内部分隔符,默认%)、openDelimiter(开分隔符,默认<)、closeDelimiter(闭分隔符,默认>),CLI 端分别对应-m、-p、-c参数。注意:全局修改ejs.delimiter会影响之后所有渲染,生产代码建议优先使用按次传参的方式。
十、缓存编译结果
EJS 提供ejs.cache全局对象,用于缓存编译后的函数(前提是使用filename作为缓存键):
let ejs = require('ejs'), LRU = require('lru-cache'); // LRU 缓存具有 100 项限制 ejs.cache = LRU(100);配合cache: true选项后,同一模板文件在缓存有效期内只编译一次。速查表中给出的 LRU 用法还顺带限制了缓存条目上限,避免长时间运行的进程内存无限增长。
十一、布局(Layouts)
用 include 拼装 header / footer 是最常见的布局方式,并配合-%>行吸收标签去掉多余空行:
<%- include('header'); -%> <h1> Title </h1> <p> My page </p> <%- include('footer'); -%>这里include('header'); -%>的-%>会修剪 include 标签之后的换行,使输出的 HTML 更紧凑。若需要多目录解析,可结合root/views选项(见下方选项表)。
十二、自定义文件加载器
默认 EJS 从文件系统读取模板。若模板存放在数据库、对象存储或内存中,可以替换ejs.fileLoader:
let ejs = require('ejs'); let myFileLoader = function (filePath) { return 'myFileLoader: ' + fs.readFileSync(filePath); }; ejs.fileLoader = myFileLoader;fileLoader接收模板路径字符串,返回模板内容字符串,是 EJS 脱离本地文件系统的关键扩展点。
十三、浏览器端 / 客户端支持
EJS 提供浏览器构建(ejs.js/ejs.min.js),可以在页面中直接渲染模板字符串。
基础例子
<div id="output"></div> <script src="ejs.min.js"></script> <script> let people = ['geddy', 'neil', 'alex'], html = ejs.render('<%= people.join(", "); %>', {people: people}); // With jQuery: $('#output').html(html); // Vanilla JS: document.getElementById('output').innerHTML = html; </script>同样地,最简形式就是在脚本标签中引入ejs.js后直接调用ejs.render:
<script src="ejs.js"></script> <script> let people = ['geddy', 'neil', 'alex']; let html = ejs.render( '<%= people.join(", "); %>', { people: people } ); </script>client 模式与 include 回调
客户端无法读取本地文件,因此client: true编译出的独立函数需要自行提供 include 回调:
let str = "Hello <%= include('file', {person: 'John'}); %>", fn = ejs.compile(str, {client: true}); fn(data, null, function(path, d){ // include callback // path -> 'file' // d -> {person: 'John'} // 在这里实现你的逻辑,返回文件内容字符串 }); // 返回渲染后的字符串调用签名为fn(data, includePath, includeCallback):第三个参数是 include 回调,返回子模板内容字符串。服务端则不需要这个回调,EJS 会通过fileLoader自动解析。
十四、完整选项列表(Options)
以下为 EJS 备忘清单 中的全部渲染选项,建议直接收藏:
| 选项 | 描述 |
|---|---|
cache | 编译后的函数被缓存,需要文件名 |
filename | 由缓存用于关键缓存,并用于包含 |
root | 使用绝对路径(例如/file.ejs)设置包含项目的根目录。可以是一个数组来尝试解析来自多个目录的包含 |
views | 解析包含相对路径时要使用的路径数组 |
context | 函数执行上下文 |
compileDebug | 当false时,不编译任何调试工具 |
client | 返回独立编译的函数 |
delimiter | 用于内部分隔符的字符,默认为% |
openDelimiter | 用于打开分隔符的字符,默认为< |
closeDelimiter | 用于结束分隔符的字符,默认为> |
debug | 输出生成的函数体 |
strict | 当设置为true时,生成的函数处于严格模式 |
_with | 是否使用with() {}构造。如果为false,则局部变量将存储在局部变量对象中(暗示--strict) |
localsName | 不使用时(_with: false)用于存储局部变量的对象的名称,默认为 locals |
rmWhitespace | 删除所有可安全删除的空格,包括前导和尾随空格。它还为所有 scriptlet 标签启用更安全版本的-%>行吸收(不会在行中间去除换行标记行) |
escape | 与<%=构造一起使用的转义函数,用于渲染,并在生成客户端函数时进行.toString()处理(默认转义 XML) |
outputFunctionName | 设置为字符串(例如echo或print),以便函数在 scriptlet 标签内打印输出 |
async | 当true时,EJS 将使用异步函数进行渲染(取决于 JS 运行时中的 async/await 支持) |
几个高频组合:
- 生产环境:
cache: true+compileDebug: false+ 合理的escape函数; - 避免 with 污染:
_with: false(隐含 strict 模式)+localsName自定义局部对象名; - 模板压缩:
rmWhitespace: true清理多余空白; - 异步数据:
async: true让模板内可直接await表达式。
十五、CLI 完整选项
安装 EJS 后可直接使用ejs命令渲染模板文件。完整参数如下:
| 选项 | 描述 |
|---|---|
cache | 编译后的函数被缓存,需要文件名 |
-o / --output-file FILE | 将渲染的输出写入 FILE 而不是 stdout |
-f / --data-file FILE | 必须是 JSON 格式。使用来自 FILE 的解析输入作为渲染数据 |
-i / --data-input STRING | 必须采用 JSON 格式和 URI 编码。使用来自 STRING 的解析输入作为渲染数据 |
-m / --delimiter CHARACTER | 使用带有尖括号的 CHARACTER 来表示打开/关闭(默认为 %) |
-p / --open-delimiter CHARACTER | 使用 CHARACTER 而不是左尖括号来打开 |
-c / --close-delimiter CHARACTER | 使用 CHARACTER 而不是右尖括号来结束 |
-s / --strict | 当设置为true时,生成的函数处于严格模式 |
-n / --no-with | 对变量使用 locals 对象,而不是使用 with(隐含 --strict) |
-l / --locals-name | 不使用 with 时用于存储局部变量的对象的名称 |
-w / --rm-whitespace | 删除所有可安全删除的空格,包括前导和尾随空格 |
-d / --debug | 输出生成的函数体 |
-h / --help | 显示此帮助消息 |
-V / -v / --version | 显示 EJS 版本 |
使用示例(与速查表一致,可直接复制):
$ ejs hello.ejs -o hello.html $ ejs hello.ejs -f data.json -o hello.html $ ejs -p [ -c ] ./template_file.ejs -o ./output.html $ ejs ./test/fixtures/user.ejs name=Lerxst $ ejs -n -l _ ./some_template.ejs -f ./data_file.json要点解读:
- 不传
-o时结果打印到 stdout,可方便地重定向或管道处理; -f指定 JSON 数据文件、-i直接在命令行传 URI 编码的 JSON 字符串,二者都用于提供渲染数据;- 形如
name=Lerxst的key=value附加参数是 CLI 的轻量数据注入方式; -n -l _组合演示了关闭with并把局部对象命名为_,适合排查模板内变量作用域问题。
十六、小结与延伸阅读
EJS 的设计哲学是「简单 + 完整」:一套<% %>标签体系承载条件与循环,include与root/views承载模板复用,compile/render/renderFile与client/fileLoader/cache等扩展点覆盖从 CLI 生成、Node.js 服务端到浏览器端的完整链路。作为速查资料,本仓库中相关清单的相对路径为:
- EJS 备忘清单 —— 本文主体,标签/选项/CLI 全表;
- Express.js 速查 ——
-e, --ejs等生成器参数,EJS 最常见的宿主框架; - README —— Nodejs 分区入口,可发现 Jest、Koa 等相邻速查表。
【免费下载链接】reference面向开发者的技术速查清单(Cheat Sheets)集合,整理常见技术、工具与开发流程,帮助快速查阅关键信息,提高开发效率。项目地址: https://gitcode.com/GitHub_Trending/referen/reference
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考