在express里使用Nodejs的doT模板引擎

在express里使用Nodejs的doT模板引擎

不知道doT模板是啥的请戳这里。这篇博文是基于截至目前最新的doT(v1.0.1)写的。

为什么使用 doT

doT是目前所有nodeJS模板引擎中最快的一个(实际上我也没测试过,但网上都这么说)。第一次注意到它,是因为无意中发现小米网的前端模板就是使用的它。

后来在项目中实际使用感觉爱不释手,果断撤掉了ejs。下一步,我就琢磨着将我这个博客的后台模板引擎也换成doT了。

将doT集成进express里?

后台使用的是express,所以当然是希望能将doT集成到express的模板引擎中去。 但后来我发现,鉴于doT独特的“预编译”(我不知道这么称呼是否准确)特性,似乎无法集成进去。

我所说的“预编译”是指,在调用

var dots = require( 'dot' ).process( { path : './views' } );

之后,doT会把 views 文件夹下的所有以 .dot 为后缀的模板都“编译”成一个函数。 例如如果你在上面的文件夹下有一个模板名叫 index.dot ,那么生成html的代码就是 dots.index();

是的,这意味着你的文件名要符合JavaScript的变量规范(例如文件名不能以数字开头)。

然而,在express里面的模板调用方法是 res.render( '这里是模板名' , { 这是数据对象 } ); ,每次调用都需要传入一个模板文件名,可是正如上面的例子所说,doT不是这么做的。

最后我发现,在 express 里面使用doT模板的方法是,把所有类似上面的代码改成:

res.send( dots[ '这里是模板名' ]( { 这里是数据对象 } ) );

同时,这意味着你没有将 doT 集成至 express 的模板引擎中,你生成的模板不会被缓存。

如果你原本使用的ejs,你还要在模板中的所有变量前加上 it. ,例如把 <%= some %>改成{{= it.some }}

使用doT引用子模板

doT的“预编译”除了支持 .dot 文件,另外还支持 .def 和 .jst 。这里只着重介绍下 .def 。

ejs里面有一个<% include some.ejs %> 语法用于加载子模板,那如何在 doT 里面实现呢?答案是:

第一步:将要被引用的模板的后缀名设为 .def ,假设它叫 some.def

第二步:在后缀名为 .dot 的模板中写 {{#def.some }} 。注意,这里不需要带上文件扩展名。

可是,doT的预编译只会将后缀名为 .dot 的文件名编译成函数。如果我既想让一个模板能成为被其他模板引用的子模板,又希望这个模板能成为一个函数呢?

答案是:为这个文件“同时使用两个扩展名”,例如 some.def.dot;至于这两个扩展名的顺序无关紧要。

这样,some.def.dot 既会成为一个函数 dots.some ,又能被其他模板使用 {{#def.some }} 引用进来。

一些提示

最后,给使用doT模板的人(以及我)的一些提示。

1、因为没有集成进 express 的模板引擎中,我需要自己进行一些优化(例如模板缓存)

2、doT“预编译”时会忽略所有子文件夹。即所有模板文件都要直接放在模板文件夹(例如./views/)下。

3、doT模板文件的文件名要遵循JavaScript变量名规范。

今天花了半天时间鼓捣了下doT,分享下结果,希望能帮到一些人,也希望能得到更好的解决方案!


8 回复

在express里使用Nodejs的doT模板引擎

为什么使用 doT

doT 是目前所有 Node.js 模板引擎中最快的一个(实际上我也没测试过,但网上都这么说)。第一次注意到它,是因为无意中发现小米网的前端模板就是使用的它。后来在项目中实际使用感觉爱不释手,果断撤掉了 ejs。下一步,我就琢磨着将我这个博客的后台模板引擎也换成 doT 了。

将doT集成进express里?

后台使用的是 Express,所以当然是希望能将 doT 集成到 Express 的模板引擎中去。 但后来我发现,鉴于 doT 独特的“预编译”(我不知道这么称呼是否准确)特性,似乎无法集成进去。

我所说的“预编译”是指,在调用以下代码后,doT 会把 views 文件夹下的所有以 .dot 为后缀的模板都“编译”成一个函数:

var dots = require('dot').process({ path: './views' });

例如,如果你在上面的文件夹下有一个模板名叫 index.dot ,那么生成 HTML 的代码就是 dots.index();

这意味着你的文件名要符合 JavaScript 的变量规范(例如文件名不能以数字开头)。

然而,在 Express 里面的模板调用方法是 res.render('这里是模板名', { 这是数据对象 }); ,每次调用都需要传入一个模板文件名,但是如上所述,doT 不是这么做的。

最后我发现,在 Express 里面使用 doT 模板的方法是,把所有类似上面的代码改成:

res.send(dots['这里是模板名']({ 这里是数据对象 }));

同时,这意味着你没有将 doT 集成至 Express 的模板引擎中,你生成的模板不会被缓存。

如果你原本使用的 ejs,你还要在模板中的所有变量前加上 it.,例如把 <%= some %> 改成 {{= it.some }}

使用doT引用子模板

doT 的“预编译”除了支持 .dot 文件,另外还支持 .def.jst。这里只着重介绍下 .def

EJS 里面有一个 <% include some.ejs %> 语法用于加载子模板,那如何在 doT 里面实现呢?

  1. 将要被引用的模板的后缀名设为 .def ,假设它叫 some.def
  2. 在后缀名为 .dot 的模板中写 {{#def.some }}。注意,这里不需要带上文件扩展名。

可是,doT 的预编译只会将后缀名为 .dot 的文件名编译成函数。如果我既想让一个模板能成为被其他模板引用的子模板,又希望这个模板能成为一个函数呢?

答案是:为这个文件“同时使用两个扩展名”,例如 some.def.dot;至于这两个扩展名的顺序无关紧要。

这样,some.def.dot 既会成为一个函数 dots.some,又能被其他模板使用 {{#def.some }} 引用进来。

一些提示

最后,给使用 doT 模板的人(以及我)的一些提示。

  1. 因为没有集成进 express 的模板引擎中,我需要自己进行一些优化(例如模板缓存)
  2. doT“预编译”时会忽略所有子文件夹。即所有模板文件都要直接放在模板文件夹(例如 ./views/)下。
  3. doT 模板文件的文件名要遵循 JavaScript 变量名规范。

今天花了半天时间鼓捣了下 doT,分享下结果,希望能帮到一些人,也希望能得到更好的解决方案!


ejs 习惯了,什么都一样。

和swig很像 有啥不同? swig的文档比较好~

https://github.com/olado/doT 官网提供的express栗子 里面似乎直接没用res.render?

最短的模板引擎是哪个,是不是 John Resig的 micro template

(function(){
var cache = {};

this.tmpl = function tmpl(str, data){ var fn = !/\W/.test(str) ? cache[str] = cache[str] || tmpl(document.getElementById(str).innerHTML) :

new Function(“obj”, “var p=[],print=function(){p.push.apply(p,arguments);};” + “with(obj){p.push(‘” +

str .replace(/[\r\t\n]/g, ” “) .split(“<%").join("\t") .replace(/((^|%>)[^\t])’/g, “$1\r”) .replace(/\t=(.?)%>/g, “‘,$1,’”) .split(“\t”).join(“‘);”) .split(“%>”).join(“p.push(‘”) .split(“\r”).join(“\’”)

  • “‘);}return p.join(”);”);

return data ? fn( data ) : fn; }; })();

用consolidate.js使用任意模版

还是喜欢swig,虽然已经不再维护了

要在Express中使用doT模板引擎,你需要手动处理模板的渲染过程,而不是通过Express的默认模板引擎机制。以下是一个简单的示例来展示如何在Express应用中使用doT。

示例代码

  1. 安装必要的依赖:

    npm install express dot
    
  2. 创建一个简单的Express应用,并配置doT:

const express = require('express');
const dot = require('dot');

// 初始化Express应用
const app = express();
const port = 3000;

// 加载并预编译所有 .dot 模板
const dots = dot.process({ path: './views' });

// 设置静态文件目录
app.use(express.static('public'));

// 渲染doT模板
app.get('/', (req, res) => {
    const data = {
        title: 'Hello World',
        message: 'This is a message from the server'
    };
    res.send(dots['index'](data));
});

app.listen(port, () => {
    console.log(`Server running on http://localhost:${port}`);
});
  1. views文件夹中创建一个名为index.dot的模板文件:
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>{{= it.title }}</title>
</head>
<body>
    <h1>{{= it.message }}</h1>
</body>
</html>
  1. 启动服务器:

    node app.js
    
  2. 访问 http://localhost:3000 查看结果。

解释

  • 预编译模板:使用dot.process函数预编译所有.dot模板文件。
  • 渲染模板:在路由处理函数中,使用预编译后的模板函数dots['index']来渲染模板,并传递数据对象。
  • 静态资源:可以使用express.static中间件来提供静态文件服务。

这种方式虽然没有集成到Express的模板引擎中,但可以通过手动方式实现模板的渲染和数据传递。

回到顶部