<%= EJS %>

高效的嵌入式 JavaScript 模板引擎

EJS 是什么?

"E" 代表 "effective",即【高效】。EJS 是一套简单的模板语言,帮你利用普通的 JavaScript 代码生成 HTML 页面。EJS 没有如何组织内容的教条;也没有再造一套迭代和控制流语法;有的只是普通的 JavaScript 代码而已。

使用原生 JavaScript

我们热爱 JavaScript,他是一门友好的编程语言。所有模板语言都要成长为图灵完备的语言,也就是说要增加一个中间层。何必呢,直接用 JS 吧!

快速开发

无需浪费时间钻研那些所谓“优雅”的神秘语法,也不用研究数据究竟如何能够被正确处理。

简单语法

EJS 支持直接在标签内书写简单、直白的 JavaScript 代码。只需让 JavaScript 输出你所需要的 HTML ,完成工作很轻松!

执行迅速

我们都知道 V8 以及类似 JavaScript 引擎的速度有多快。EJS 能够缓存 JS 函数的中间代码,从而提升执行速度。

易于调试

调试 EJS 错误(error)很容易:所有错误都是普通的 JavaScript 异常,并且还能输出异常发生的位置。

社区活跃

EJS 背后是一个活跃用户组成的大规模社区,能够为 EJS 的演进提供大力支持。我们同时很高兴回答你的问题或提供帮助。

EJS 特性

开始使用

安装

利用 NPM 安装 EJS 是非常简单。

$ npm install ejs

使用

将模板字符串和一些数据作为参数传递给 EJS,Duang,HTML 出来了。

let ejs = require('ejs');
let people = ['geddy', 'neil', 'alex'];
let html = ejs.render('<%= people.join(", "); %>', {people: people});

CLI

给定一个目标文件和数据文件,并且指定输出文件

ejs ./template_file.ejs -f data_file.json -o ./output.html

浏览器支持

从这里下载 最新的浏览器版本, 然后引入页面即可.

<script src="ejs.js"></script>
<script>
  let people = ['geddy', 'neil', 'alex'];
  let html = ejs.render('<%= people.join(", "); %>', {people: people});
</script>

文档

示例

<% if (user) { %>
  <h2><%= user.name %></h2>
<% } %>

用法

let template = ejs.compile(str, options);
template(data);
// => Rendered HTML string

ejs.render(str, data, options);
// => Rendered HTML string

ejs.renderFile(filename, data, options, function(err, str){
    // str => Rendered HTML string
});

Options

  • cache 缓存编译后的函数,需要提供 filename
  • filenamecache 参数用做键值,同时也用于 include 语句
  • root Set project root for includes with an absolute path (e.g, /file.ejs). Can be array to try to resolve include from multiple directories.
  • views An array of paths to use when resolving includes with relative paths.
  • context Function execution context
  • compileDebug When false no debug instrumentation is compiled
  • client Returns standalone compiled function
  • delimiter Character to use for inner delimiter, by default '%'
  • openDelimiter Character to use for opening delimiter, by default '<'
  • closeDelimiter Character to use for closing delimiter, by default '>'
  • debug Outputs generated function body
  • strict When set to `true`, generated function is in strict mode
  • _with Whether or not to use with() {} constructs. If false then the locals will be stored in the locals object. (Implies `--strict`)
  • localsName Name to use for the object storing local variables when not using with Defaults to locals
  • rmWhitespace Remove all safe-to-remove whitespace, including leading and trailing whitespace. It also enables a safer version of -%> line slurping for all scriptlet tags (it does not strip new lines of tags in the middle of a line).
  • escape The escaping function used with <%= construct. It is used in rendering and is .toString()ed in the generation of client functions. (By default escapes XML).
  • outputFunctionName Set to a string (e.g., 'echo' or 'print') for a function to print output inside scriptlet tags.
  • async When true, EJS will use an async function for rendering. (Depends on async/await support in the JS runtime.

Tags

  • <% 'Scriptlet' tag, for control-flow, no output
  • <%_ ‘Whitespace Slurping’ Scriptlet tag, strips all whitespace before it
  • <%= Outputs the value into the template (HTML escaped)
  • <%- Outputs the unescaped value into the template
  • <%# Comment tag, no execution, no output
  • <%% Outputs a literal '<%'
  • %> Plain ending tag
  • -%> Trim-mode ('newline slurp') tag, trims following newline
  • _%> ‘Whitespace Slurping’ ending tag, removes all whitespace after it

Includes

Includes are relative to the template with the include call. (This requires the 'filename' option.) For example if you have "./views/users.ejs" and "./views/user/show.ejs" you would use <%- include('user/show'); %>.

You'll likely want to use the raw output tag (<%-) with your include to avoid double-escaping the HTML output.

<ul>
  <% users.forEach(function(user){ %>
    <%- include('user/show', {user: user}); %>
  <% }); %>
</ul>

CLI

EJS ships with a full-featured command-line interface. Options are similar to those used in JavaScript code:

  • cache Compiled functions are cached, requires filename
  • -o / --output-file FILE Write the rendered output to FILE rather than stdout.
  • -f / --data-file FILE Must be JSON-formatted. Use parsed input from FILE as data for rendering.
  • -i / --data-input STRING Must be JSON-formatted and URI-encoded. Use parsed input from STRING as data for rendering.
  • -m / --delimiter CHARACTER Use CHARACTER with angle brackets for open/close (defaults to %).
  • -p / --open-delimiter CHARACTER Use CHARACTER instead of left angle bracket to open.
  • -c / --close-delimiter CHARACTER Use CHARACTER instead of right angle bracket to close.
  • -s / --strict When set to `true`, generated function is in strict mode
  • -n / --no-with Use 'locals' object for vars rather than using `with` (implies --strict).
  • -l / --locals-name Name to use for the object storing local variables when not using `with`.
  • -w / --rm-whitespace Remove all safe-to-remove whitespace, including leading and trailing whitespace.
  • -d / --debug Outputs generated function body
  • -h / --help Display this help message.
  • -V/v / --version Display the EJS version.

Some examples of use:

$ 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

Custom delimiters

Custom delimiters can be applied on a per-template basis, or globally:

let ejs = require('ejs'),
    users = ['geddy', 'neil', 'alex'];

// Just one template
ejs.render('<?= users.join(" | "); ?>', {users: users},
    {delimiter: '?'});
// => 'geddy | neil | alex'

// Or globally
ejs.delimiter = '$';
ejs.render('<$= users.join(" | "); $>', {users: users});
// => 'geddy | neil | alex'

Caching

EJS ships with a basic in-process cache for caching the intermediate JavaScript functions used to render templates. It's easy to plug in LRU caching using Node's `lru-cache` library:

let ejs = require('ejs'),
    LRU = require('lru-cache');
ejs.cache = LRU(100); // LRU cache with 100-item limit

If you want to clear the EJS cache, call ejs.clearCache. If you're using the LRU cache and need a different limit, simple reset `ejs.cache` to a new instance of the LRU.

Custom file loader

The default file loader is fs.readFileSync, if you want to customize it, you can set ejs.fileLoader.

let ejs = require('ejs');
let myFileLoader = function (filePath) {
  return 'myFileLoader: ' + fs.readFileSync(filePath);
};

ejs.fileLoader = myFileLoader;

With this feature, you can preprocess the template before reading it.

Layouts

EJS does not specifically support blocks, but layouts can be implemented by including headers and footers, like so:

<%- include('header'); -%>
<h1>
  Title
</h1>
<p>
  My page
</p>
<%- include('footer'); -%>

Client-side support

Go to the latest release, download ./ejs.js or ./ejs.min.js. Alternately, you can compile it yourself by cloning the repository and running jake build (or $(npm bin)/jake build if jake is not installed globally).

Include one of these files on your page, and ejs should be available globally

Example

<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>

Caveats

Most of EJS will work as expected; however, there are a few things to note:

  1. Obviously, since you do not have access to the filesystem, `ejs.renderFile` won't work.
  2. For the same reason, includes do not work unless you use an include callback. Here is an example:
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'}
  // Put your code here
  // Return the contents of file as a string
}); // returns rendered string

Using EJS with Express

This GitHub Wiki page explains various ways of passing EJS options to Express.

Support

Stack Overflow

Ask questions about specific problems you have faced, including details about what exactly you are trying to do. Make sure you tag your question with ejs. You can also read through existing ejs questions.

GitHub issues

The issue tracker is the preferred channel for bug reports, features requests and submitting pull requests.

License

EJS is licensed under the Apache License, version 2.0. Information can found here: http://www.apache.org/licenses/.