一个周末掌握IT前沿技术之node.js篇<三>:Node.js与服务端模板引擎

“变化”是永恒不变的。你并不能为“变化”做规划,但你可以提前为此做准备。真正的力量是放弃任何概念,振作起来面对改变。你能够适应你当前正处于的环境,这是最关键的。换句话说,接受变化总会发生这个实事,你要不停地学习。

《Node.js发展简史》
2009年2月,Ryan Dahl在博客上宣布准备基于V8创建一个轻量级的Web服务器并提供一套库。
2009年5月,Ryan Dahl在GitHub上发布了最初版本的部分Node.js包,随后几个月里,有人开始使用Node.js开发应用。
2009年11月和2010年4月,两届JSConf大会都安排了Node.js的讲座。
2010年年底,Node.js获得云计算服务商Joyent资助,创始人Ryan Dahl加入Joyent全职负责Node.js的发展。
2011年7月,Node.js在微软的支持下发布Windows版本。

在web2.0的时代,也就是Facebook的时代,为了满足动态网页的需求,出现了一些优秀的HTML内嵌式的语言(php/jsp/asp)。什么是HTML内嵌式语言,读懂下面这段php代码就能明白。
index.php如下:

 1 <html>
 2 <body>
 3 
 4 <?php
 5 $arr=array("one", "two", "three");
 6 
 7 foreach ($arr as $value)
 8 {
 9   echo "Value: " . $value . "<br />";
10 }
11 ?>
12 
13 </body>
14 </html>

在所有HTML内嵌式语言中,在1995年出现的php,无论是在性能、语言特性,还是开发效率、运维成本等方面,都是最优秀的。这也就是php是web2.0的时代最流行的web开发语言的原因。用PHP做出的动态页面与其他的编程语言相比,PHP是将程序嵌入到HTML文档中去执行,执行效率比完全生成HTML标记的CGI要高许多;PHP还可以执行编译后代码,编译可以达到加密和优化代码运行,使代码运行更快。大家对它是这么赞扬的:

“如果你希望在软件设计上做出明智的决定,PHP是你开发Web应用程序的最佳选择。顺便说一下,如果你确信要使用PHP来开发下一个Web应用,请试一试CodeIgniter。它是一个轻量级的,普通的,超级快的PHP框架。对于CodeIgniter,我是个粉丝。”

Facebook的前端也是由php构建,并使用HipHop技术,把PHP转成C++并用g++编译,提高服务器的性能。推荐阅读下面两篇文章,它们代表着web2.0时代web技术的最高水平:
《揭秘Facebook的系统架构》
《Tumblr网站架构:15 Billion Page Views a Month 》

HTML内嵌式语言,是一种服务器模板语言。要掌握它们之中的任意一种,都需要几本书的学习内容,掌握它们的一些概念和框架,比方说,tomcat,Servlet,Zend,.net,com组件,ActiveX组件,连接池等等。如果你没听过上面这些名词,没关系。因为随着技术的发展,我们可以用更好的方法来实现它们可以实现的功能。那么Node.js如何输出动态网页呢?接下来我们就去学习。


三. Node.js与 服务器模板语言


什么是动态网页呢?顾名思义,动态网页就是网页的内容不是一成不变的,它会根据用户、时间、内容以及用户操作的不同,呈现不同的网页显示。技术上我们可以这么理解,将一堆数据扔给一段逻辑,这段逻辑会依据这些数据生成相应的HTML编码,再显示在用户网页上。这段HTML编码会根据数据的变化而变化,这就是动态网页。而这段逻辑代码就是模板语言。JavaScript因为语言特性强大,200行代码就可以实现一个优秀的模板引擎。所以JavaScript模板语言只有一个特征那就是:混乱。我们可能听说过一些有名的JavaScript模板语言:jade、jQueryTemplate、doTtemplate、ejs还有很多。下面这个链接是一些Javascript模板引擎性能对比在线测试:
《JavaScript template language shootoff》
你有两块手表时,就不知道时间了,何况是十块八块。我们只挑选一种来学习。


3.1 Node.js与nTenjin

nTenjin是基于jsTenjin修改的高性能的支持Node.js的模板解析引擎 (A template engine base on jsTenjin’s and more fase and support Node.js )
项目主页:《nTenjin》
高性能,清晰的模板结构,强大的模板功能是nTenjin的3个优点。nTenjin的源代码清晰,阅读代码可以发现,它的高性能正是来自于项目主页上所说的两点原因:1.将模板语言剪辑翻译,再调用“new Function(‘it’, buf);”,生成JavaScript函数;2.生成JavaScript函数在被调用时,使用“String += str”拼接字符串,输出应的HTML编码。
我们看下面这一段nTenjin模板:

 1 <div>
 2     <h1 class='header'>#{ it.header }</h1>
 3     <h2 class='header2'>#{ it.header2 }</h2>
 4     <h3 class='header3'>#{ it.header3 }</h3>
 5     <h4 class='header4'>#{ it.header4 }</h4>
 6     <h5 class='header5'>#{ it.header5 }</h5>
 7     <h6 class='header6'>#{ it.header6 }</h6>
 8     <ul class='list'>
 9         <?js for (var i = 0, l = it.list.length; i < l; i++) { ?>
10             <li class='item'>#{ it.list[i] }</li>
11         <?js } ?>
12     </ul>
13 </div>

其中“#{}包”含就是变量名,“<?js >”标签包含的就是模板逻辑,会在模板编译的时候导入到生成的JavaScript函数中。
在Node.js中,安装tenjin:

1 C:>cd "Program Files
odejs"
2 C:Program Files
odejs>npm install tenjin

我们来分析下面这个例程:
例程4:
demo4.js如下:

 1 /**
 2  * Date: 12-3-24
 3  * 演示程序4
 4  * 说明: 使用服务端模板nTenjin
 5  */
 6 var http = require("http");
 7 var tenjin = require('tenjin');
 8 
 9 var i = 1;
10 
11 http.createServer(
12     function (request, response) {
13 
14     response.writeHead(200, {
15         "Content-Type" : "text/html; charset=UTF-8"
16     });
17 
18     response.write("欢迎您第" + i + "次访问服务器!<br>Welcome!<br>");
19 
20     testTenjin(response);
21     i++;
22     console.log("服务器访问被访问次数: i = " + i);
23     response.end();
24 
25 }).listen(80);
26 
27 var sharedVariables = {
28     header : "Header",
29     header2 : "Header2",
30     header3 : "Header3",
31     header4 : "Header4",
32     header5 : "Header5",
33     header6 : "Header6",
34     list : ['1', '2', '3', '4', '5', '我是6', '7', '8', '9', ' 你好10'],
35     o : {
36         a : ['我是1啊', {
37                 b : {
38                     p : '我是p'
39                 }
40             }, '3', '4', '5', '6', '7', '8', '9', ' 你好10']
41     }
42 };
43 
44 function testTenjin(response) {
45     //第一个case,nTenjin最简单的应用。
46     var result1 = tenjin.render('Hello #{it.name}!', {
47             name : 'nTenjin'
48         });
49     console.log("result1是" + result1);//log显示“result1是Hello nTenjin!”
50     //第二个case,nTenjin编译html模板。
51     var nTenjinTemplate = "<div><h1 class='header'>#{ it.header }</h1><h2 class='header2'>#{ it.header2 }</h2><h3 class='header3'>#{ it.header3 }</h3><h4 class='header4'>#{ it.header4 }</h4><h5 class='header5'>#{ it.header5 }</h5><h6 class='header6'>#{ it.header6 }</h6><ul class='list'><?js for (var i = 0, l = it.list.length; i < l; i++) { ?><li class='item'>#{ it.list[i] }</li><?js } ?></ul></div>";
52     var convertednTenjinTemplate = new tenjin.Template();
53     convertednTenjinTemplate.convert(nTenjinTemplate);//编译html模板, 生成JavaScript函数
54     var result2 = '';
55     for (var i = 0; i < 1000; i++) {
56         result2 = convertednTenjinTemplate.render(sharedVariables);//根据数据sharedVariables,生成html编码
57         sharedVariables.o.a[1].b.q += "+" + i + "+";
58     }
59 
60     response.write(result2);//输出网页内容
61     console.log("result2是" + result2);
62     console.log("sharedVariables.o.a[1].b.q" + sharedVariables.o.a[1].b.q);
63 
64 }
65 console.log("服务器开启");

别忘了在Run/Debug Configuration中,加入环境变量:“NODE_PATH=C:Program Files odejs ode_modules”。否则webstorm会提示错误找不到模块。例程4的运行结果如下图所示。可以看到sharedVariables的数据,已根据模板的要求显示在了网页上。


3.2 使用nTenjin输出动态轻博客内容

我们可以使用nTenjin输出动态轻博客内容,网页框架、图片、css的拔取方法,只要用熟了chrome浏览器,都非常容易。下面只介绍例程的重点部分,所有例程的源代码都会给出。
例程5:
使用nTenjin网页模板的content.html的部分内容如下:

 1 <!-- 省去很多内容 -->
 2 <div class="feed-list" id="feed-list">
 3     <?js for (var i = 0, l = it.length; i < l; i++) { ?>
 4         <!-- 省去很多内容 -->
 5         <div class="feed-txt-full rich-content">
 6             <div class="feed-txt-summary">
 7                 <p>#{ it[i] }</p>
 8             </div>
 9         </div>
10         <!-- 省去很多内容 -->
11     </div>
12     <?js } ?>
13 </div>
14 <!-- 省去很多内容 -->

将content.html保存在demo5文件夹下,demo5.js将会读取该模板,输出结果。
demo5.js如下:

 1 /**
 2  * Date: 12-3-24
 3  * 演示程序5
 4  * 说明: 使用服务端模板nTenjin输出动态轻博客内容
 5  */
 6 var http = require("http");
 7 var tenjin = require('tenjin');
 8 var fs = require('fs');
 9 
10 var htmlTemplete = {
11     html:{},
12     loadTemplete:function () {
13         this.html['content']={};
14         this.html['content'].string= fs.readFileSync('./demo5/content.html', encoding = 'utf8');
15         this.html['content'].template = new tenjin.Template();
16         this.html['content'].template.convert(this.html['content'].string);//我们需要在初始化时编译html模板, 生成JavaScript函数,而不是每次访问调用模板时编译一遍。
17     }
18 };
19 var i = 1;
20 htmlTemplete.loadTemplete();
21 
22 http.createServer(
23     function (request, response) {
24 
25         response.writeHead(200, {
26             "Content-Type":"text/html; charset=UTF-8"
27         });
28 
29         testTenjin(response);
30         i++;
31         console.log("服务器访问被访问次数: i = " + i);
32         response.end();
33 
34     }).listen(8080);
35 
36 var articles = ["这是第一篇文章", "这是第二篇文章", "这是第3篇文章"];
37 function testTenjin(response) {
38 
39     var result = htmlTemplete.html['content'].template.render(articles);//调用模板,输出结果
40     response.write(result);
41     response.write(result);
42 }
43 console.log("服务器开启");

例程5的运行结果如下图所示。js数组articles,对应着每一条记录。

本文目录:《一个周末掌握IT前沿技术之node.js篇》
1.《Node.js与javascript》
2.《Node.js与redis》
3.《Node.js与服务端模板引擎》
4.《Node.js与Restful API》
5.《Node.js与Nginx》
6.《Node.js与客户端模板引擎》
7.《Node.js与HBase》
文本粗陋,欢迎斧正!欢迎投稿!原创文章,转载请链接。
联系邮箱:(it.Web.technical#gmail.com)
IT技术精研院
原文地址:https://www.cnblogs.com/joe1545134/p/node-js-and-server-side-template.html