【转】在Express项目中使用Handlebars模板引擎

原文:http://fraserxu.me/2013/09/12/Using-Handlebarsjs-with-Expressjs/javascript

 

最近在用Expressjs作一个项目,先后端都用它来完成。本身以前有用过Express一段时间,可是大部分都是用它来编写Restful的API,而没有真正用它所提供的前端页面渲染功能。css

因此严格意义来说这是第一次完整的项目。开始作以后就遇到了一些须要作出决定的地方。众所周知,Express的默认模板引擎是Jade.我在以前学习Express的时候,由于它是默认的引擎,因此有接触和使用过一段时间,感受也还行。Jade在编写页面时所提供的嵌套功能比较实用,能够节省很大的代码量。html

Jade is a high performance template engine heavily influenced by Haml and implemented with JavaScript for node. For discussion join the Google Group.前端

上面是Jade Github所在页面的描述。能够得知它是一个注重性能,受Hamle影响,并特别针对Nodejs而编写的前端模板引擎。java

咱们先来看一下Jade官方页面所给的例子:node

doctype 5
html(lang="en")
  head
    title= pageTitle
    script(type='text/javascript').
      if (foo) {
        bar(1 + 5)
      }
  body
    h1 Jade - node template engine
    #container.col
      if youAreUsingJade
        p You are amazing
      else
        p Get on it!
      p.
        Jade is a terse and simple
        templating language with a
        strong focus on performance
        and powerful features.

 

咱们能够看到,对比原生的HTML, Jade明显的一个优点就是标签数量上的减小。不少地方只要按照约定的缩进规则编写,彻底能够避免使用原生HTML时标签忘记闭合的问题。同时Jade还提供了一些用于渲染判断的条件,能够根据数据来决定显示的内容等功能。git

另外Jade的遍历数据生成页面功能,配合使用Json数据时特别好用,能够很大程度上减小代码量。github

而另一个缘由,也是觉大多数人使用Jade的缘由,可能都跟我同样,由于是Express框架自带的模板引擎,而它的做者也是鼎鼎有名的TJ.express

看了标题也许会奇怪,既然Jade出自大神之手,并且简单易用,我为何还要去选择Handlebarsjs呢?npm

一样咱们看下官方描述:

Handlebars provides the power necessary to let you build semantic templates effectively with no frustration.

Mustache templates are compatible with Handlebars, so you can take a Mustache template, import it into Handlebars, and start taking advantage of the extra Handlebars features.

做为一个模板引擎,它继承于著名的Mustache模板引擎,具有了渲染页面的基础功能,并在其基础上进行拓展。

而另外一个值得关注的是其做者Yehuda Katz,熟悉的朋友可能知道,他是著名JavaScript MVC框架Emberjs代码的主要贡献者之一,并且在他的影响下也成为了Emberjs的默认模板引擎。而另外,Yehuda自己也是W3C规范制定小组的成员之一,其影响也不亚于TJ.

抛开框架的背景,咱们来看看实际的应用场景。工具无非好坏,顺手才是王道。评断一个东西好坏关键仍是看它是否知足本身的应用需求。

在开始作如今的项目以前,我已经用Jade完成了全部的功能,并且对于代码也还比较满意。可是在提交以后问题产生了。

由于这个项目不是我一我的在作,和我一块儿合做的同事以前没有接触过Jade,并且另一位负责编写样式的同事对于JavaScript的模板引擎也不是很熟悉。这样一来,因为个人缘由,致使团队成员之间没法协做。首先是JS开发人员须要时间来掌握和熟悉Jade语法,而另一个更为严重,Jade语法的特性决定了其不利于配套CSS的书写(这点经过编译以后能够解决,可是必定程度上增长了工做量)。

因而我开始思考使用Jade是否正确。这里的两个问题是我必须面对的,而项目的进度不能由于这个受到影响,因而我开始考虑选择其余的模板引擎。

前面提到Emberjs用到了Handlebarsjs,因此在选择时我很容易就想到了它。

Handlebars的官网给出了不少例子,并且上手也很容易,先后端通用,使用起来也很简单,这里就不对其使用多作介绍。

回到文章重点,由于Express并不提供对Handlerbarjs的直接支持,这样在使用时会面临必定问题。

要在Express中使用Handlerbars做为模板引擎,首先须要作出一下设置:

  1. 安装Express, Handlebars, Consolidate:

     "dependencies": {
       "express": "3.x",
       "consolidate": "0.4.0",
       "handlebars": "1.0.7"
     }
  2. 配置选择引擎:

     // Use handlebars as template engine
     app.engine("html", consolidate.handlebars);
     app.set("view engine", "html");
     app.set("views", __dirname + "/views");
  3. 注册模板:

     // Register partials
     var partials = "./views/partials/";
     fs.readdirSync(partials).forEach(function (file) {
       var source = fs.readFileSync(partials + file, "utf8"),
         partial = /(.+)\.html/.exec(file).pop();
         Handlebars.registerPartial(partial, source);
     })

这样咱们就能够在项目中使用Handlerbars来渲染页面。可是这样作后,我又遇到了另一个问题。经过以上的方法我能够很容易的单独去加载某个页面。可是实际应用中,通常会有多个页面,并且多个页面之间会共享页面的header和footer部分。这样会致使重复编写不少代码。

在使用Jade是咱们能够很容易的使用以下代码来实现页面模板功能:

include layout

可是因为Express并不是直接支持Handlerbars,因此要实现这个功能还须要必定的设置。在Handlerbars中,能够经过 来实现sub-template的功能。在查找了相关模块以后,我发现了hbs这个Express中间件。

这个模块使用起来很简单,能够完美解决我所遇到的问题。使用方法以下:

  1. 安装模块:

    npm install hbs --save
  2. 设置模板:

    app.set('view engine', 'html');
    app.engine('html', require('hbs').__express);
  3. 注册模板:

    var hbs = require('hbs');
    hbs.registerHelper('helper_name', function(...) { ... });
    hbs.registerPartial('partial_name', 'partial value');

若是须要注册整个文件夹,也可以使用以下命令:

var hbs = require('hbs');
hbs.registerPartials(__dirname + '/views/partials');

这样,咱们就能够作到页面模板的重复利用,能够显著减小代码量。

而另一个关键缘由,在于Handlerbars对比Jade,语法更加简单。最重要的仍是其普通元素一样使用原生HTML的写法,这样,对于编写样式的同事来说就会更加友好。使用传统的方式编写样式,能够显著下降学习成本,从而加快项目进度。

而Handerbars所带来的一些其余功能,也会让项目的开发变得更加轻松。

下面附上我项目的基本结构,但愿能对一样使用这种方案的同窗有必定帮助。

.
├── app.js
├── node_modules
│   ├── express
│   ├── handlebars
│   ├── hbs
│   ├── less-middleware
│   ├── nodemon
│   └── request
├── package.json
├── public
│   ├── images
│   ├── javascripts
│   │   └── app.js
│   ├── lib
│   │   ├── font
│   │   ├── js
│   │   └── stylesheets
│   └── stylesheets
│       ├── style.css
│       └── style.less
├── routes
│   ├── github.js
│   └── index.js
└── views
    ├── index.hbs
    ├── orgs.hbs
    └── partials
      ├── footer.hbs
      └── header.hbs
相关文章
相关标签/搜索