Dustjs是我个人更喜欢的JS模板引擎,原因有两个。首先,它同时支持客户端和服务器端渲染。模板编译成JS使用,性能良好;是的,在大公司的支持下,Linkedin有专门的Dustjs版本(本文都是这个版本),而且已经在线测试过了。Dustjs本文不赘述(见文档),直接进入正题。1、为什么要写一个中间件Dustjs作为Express的ViewEngine是官方支持的,但是我个人更喜欢用它来做客户端渲染,这样可以减少服务端的性能损失,充分利用客户端的机器性能。目前Dustjs没有类似less-middleware的插件,可以按需编译模板供客户端参考,所以才有了这个Dustjs中间件。2.显示代码2.1。中间件中间件代码很简单,只有几十行,无非就是拦截HTTP请求,如果发现获取模板,就按需编译。//引入依赖模块varurl=require('url'),fs=require('fs'),extend=require('node.extend'),dust=require('dustjs-linkedin'),beautify=require('js-beautify').js_beautify,iconv=require('iconv-lite'),path=require('path');//遵循模块定义,将模块暴露给用户module.exports=function(source,options){//使用node.extend模块提供默认值options=extend(true,{format:false,//是否格式化代码方便阅读encoding:'utf-8'//代码编码格式,支持中文},options||{});//source参数用于指定模板代码的存放路径,编译后的JS代码和模板源码放在一起if(!source){thrownewError('dustjs-middlewarerequires`source`directory');}returnfunction(req,res,next){if('GET'!=req.method.toUpperCase()&&'HEAD'!=req.method.toUpperCase()){//只处理Get和Head请求returnnext();}varpathname=url.parse(req.url).pathname;if(!/^\/dust\/[\S]+\.js$/.test(pathname)){//notforJSfiles这里不处理请求returnnext();}varjsPath=源+路径名;vardustPath=jsPath.replace(/\.js$/,'.dust');varerror=function(err){returnnext('ENOENT'==err.code?null:err);};//编译模板函数varcompile=function(){fs.readFile(dustPath,function(err,buf){if(err){returnerror(err);}//使用指定的编码解析出模板源码vardata=iconv.decode(buf,options.encoding);//将模板编译成文件名作为模板名varname=path.basename(dustPath,'.dust');vartemplate=dust.compile(数据,名称);if(options.format){//必要时格式化代码,基于js-beautifytemplate=beautify(template,{indent_size:2});}//写入指定编码的编译后JS代码buf=iconv.encode(template,options.encoding);fs.writeFile(jsPath,buf,next);});};fs.stat(dustPath,function(dustErr,dustStats){//判断模板代码是否存在,不存在则不处理请求if(dustErr){if('ENOENT'==dustErr.code){returnnext();}else{returnnext(dustErr);}}if(dustStats.isDirectory()){//模板代码为文件,不处理returnnext();}fs.stat(jsPath,function(jsErr,jsStats){if(jsErr){if('ENOENT'==jsErr.code){//JS文件不存在,直接编译returncompile();}else{returnnext(jsErr);}}elseif(dustStats.mtime>jsStats.ctime){//模板有变化,重新编译returncompile();}});});};};需要注意的是,中间件使用文件名作为模板的名称。使用模板时,需要指定模板名称,示例如下
