Reference 速查手册:EJS 模板引擎完全指南 —— 标签、核心 API、选项与 CLI
2026/9/14 3:53:29 网站建设 项目流程

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函数执行上下文
compileDebugfalse时,不编译任何调试工具
client返回独立编译的函数
delimiter用于内部分隔符的字符,默认为%
openDelimiter用于打开分隔符的字符,默认为<
closeDelimiter用于结束分隔符的字符,默认为>
debug输出生成的函数体
strict当设置为true时,生成的函数处于严格模式
_with是否使用with() {}构造。如果为false,则局部变量将存储在局部变量对象中(暗示--strict
localsName不使用时(_with: false)用于存储局部变量的对象的名称,默认为 locals
rmWhitespace删除所有可安全删除的空格,包括前导和尾随空格。它还为所有 scriptlet 标签启用更安全版本的-%>行吸收(不会在行中间去除换行标记行)
escape<%=构造一起使用的转义函数,用于渲染,并在生成客户端函数时进行.toString()处理(默认转义 XML)
outputFunctionName设置为字符串(例如echoprint),以便函数在 scriptlet 标签内打印输出
asynctrue时,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

要点解读:

  1. 不传-o时结果打印到 stdout,可方便地重定向或管道处理;
  2. -f指定 JSON 数据文件、-i直接在命令行传 URI 编码的 JSON 字符串,二者都用于提供渲染数据;
  3. 形如name=Lerxstkey=value附加参数是 CLI 的轻量数据注入方式;
  4. -n -l _组合演示了关闭with并把局部对象命名为_,适合排查模板内变量作用域问题。

十六、小结与延伸阅读

EJS 的设计哲学是「简单 + 完整」:一套<% %>标签体系承载条件与循环,includeroot/views承载模板复用,compile/render/renderFileclient/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),仅供参考

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询