脚本模板引擎
‘壹’ 模板引擎的相关推荐
Smarty的特点是将模板编译成php脚本,然后执行这些脚本。很快,非常灵活。
是一个模板类,一般也简称为模板。Smarty里面有专门的模板引擎。模板的主要功能就是逻辑与显示的分离,也就是PHP和HTML的分离。 一个简单易用的类,可以让你的整个网站布局基于模板文件,修改模板就能改变整个站点。
STP Simple Template Parser
一个简单、轻量级并且易于使用的模板分析类。它可以从多个模板中组装一个页面,把结果页面输出到浏览器或者文件系统。 一个强大且轻量级的PEAR兼容模板系统。它是非编译型的,使用PHP语言本身做为它的模板语言。
ETS - easy template system
可以使用完全相同数据重组模板的模板系统。 多字节安全的模板引擎,占用很少系统资源。它支持变量替换,内容块可以设置显示或隐藏。
Grafx Software’s Fast Template
一个修改版本的Fast Template系统,它包括缓存功能,调试控制台以及沉默去除为赋值块。 这个库的功能被设计来使用模板文件,同时允许你从HTML文件检索信息。
htmltmpl: templating engine
一个适用于Python和PHP的模板引擎。它面向希望在项目中分离代码和设计的web应用开发人员。
PHP Parsing Dreamweaver templates
一个分析Dreamweaver模板的简单类,被用于Gallery 2 和WordPress的自定义模块中。
MiniTemplator (Template Engine)
针对HTML文件的一个紧凑型模板引擎。对于模板变量和块定义它具有简单的语法。其中块可以嵌套。 一个PHP下面的XML/XHTML模板库。
‘贰’ freemarker thymeleaf哪个好
我也是来问这个问题的。。。目前了解,性能方面thymeleaf更差。但是thymeleaf由于使用了标签属性做为语法,模版页面直接用浏览器渲染,使得前端和后端可以并行开发。freemarket使用</>这样的语法,就无法直接使浏览器渲染出原本页面的样子。
thymeleaf的性能一直是大家痛击之处。有人说thymeleaf开启缓存后,性能会比freemarker更好,但是开启缓存有什么弊端我就不知道了。(会不会更新了模版后,页面没变化?)
很难说两个谁好谁坏,都有不足都有优点。目前两者都还有更新,有团队支持。不像velocity已经6年没更新了。但是我看的sprint 实战 第4版中,有一小节专门讲了thymeleaf,为什么不讲freemarker,我也不懂,要问作者。为什么IDEA中直接提供了thymeleaf的framework支持??综上,但是为什么网友诟病thymeleaf性能问题的更多,而夸奖的人没有几个??我也是迷糊了。
我是因为我的项目需要用到这些所以今天花了一天的时间,找这些资料,目前,我个人比较倾向thymeleaf。
‘叁’ 项目复盘:通过动态脚本,实现按需加载语言包
大家好,我是前端西瓜哥,是一名前端开发。
最近做了一个将按需加载语言包的需求,有不少收获,这里记录一下。
原来项目是将所有的语言包合并在一起,放到一个 JSON 文件里然后被引入。
打包后的脚本里,有完整的语言包的代码,导致打包文件非常大。理论上用户只会使用一种语言,其他的语言没有加载的必要。
目前来说项目只支持两种语言,每个语言有文案 4000 多条。如果还是使用全量加载的话,以后支持的语言每多一个,打包后的文件就要膨胀一圈。
做语言包的拆分还是很有必要的。它可以减少加载资源的大小,减少首次页面加载时间,提高用户体验。
实现按需加载语言包的方式很多,我了解到的有三种:
请求 HTML 时,后端做渲染工作,给 HTML 加上语言包的内容。
前端没有什么改造的工作量,但问题是不能利用缓存。但这个问题其实也可以解决,就是后端生成好语言包 js 文件,将嵌入语言包内容的方式改为 cdn 引入的方式,可以利用好缓存。
但这让模板引擎的逻辑变得很重,cdn 上传到哪里,如何维护也是个问题。
使用 React 等框架打包出来单页面应用的文件通常很大,下载需要不少时间。
动态 import 必须在脚本整个下载完后,再执行,所以这是一个串行下载的逻辑。
如果可以的话,我们希望语言包可以和业务代码同时下载。此外,更重要的一点是,在 动态 import 前,我们不能调用获取文案的方法 getText 。
我在改造项目代码时,发现在我动态 import 语言包并 ReactDOM.render() 之前,有些模块文件调用了getText 方法,因为它们作为枚举指直接暴露出来,没有用函数封装,被 import 时就直接执行了。
语言包都没加载,你执行 getText 是拿不到文案的,这个方案我果断放弃。
这种方案利用了脚本里创建脚本的方式。能在更前面的位置加载语言包脚本。
优点是我们可以不需要做后端渲染的工作,让选择语言包的逻辑交给前端。但涉及到前端工程化,需要写插件改变原来的加载脚本形式。
我们的项目使用了 webpack,如果用这个方案,就需要写一个 webpack 插件去改造 HtmlWebpackPlugin 的构建流程。
目前来说,方案 1 和 方案 3 都是不错的。
但考虑到我们公司的前后端是分离的,后端的代码实现对我来说其实是黑盒,我没有权限也没有能力去写后端代码。而项目是前端项目,最好还是让前端来掌控维护。所以我最终选择了方案 3。
方案1 和方案 2 的更具体介绍,可以看我的这篇文章:前端国际化,该如何实现按需加载语言包?
原来项目打包后的 html 文件大致如下。
app.js 里有全量语言包的内容。
改造后的 html 文件如下:
我们语言包将 app.js 从中提取出来,并且分为多个语言包放到 js 文件,如 zh-CN.js、en-US.js,在 app.js 之前执行。
我们先确认用户使用的语言是什么。
如果我们不支持持久化设置,可以通过 navigator.language 或前端的其他地方获取。
但通常用户可以设置语言,这个语言标识就要后端给,再请求一次用户信息可太离谱了,所以这里还是需要后端给我们往 html 里嵌入用户选择的语言。然后我们从语言 cdn 列表里选我们需要的语言。
script 元素默认会将 async 设置为 true,效果是脚本下载完立即执行。需要将其改为 false,保证多个动态脚本顺序执行。
文件名使用了哈希,是为了解决浏览器缓存问题。
执行后,就会将语言包文案暴露在全局变量中。
业务代码 app.js 也得改成动态加载形式,如果原来的非动态写法,执行时机就会早于语言包脚本 。
这里涉及到了 script 的执行时机,具体规则可以看我的这篇文章:script 的三种加载模式:默认加载、defer、async
这样我们就能保证先执行语言包脚本,再执行 app.js。
app.js 中的业务代码执行时,使用 getText 方法就能正常通过 key 获取到对应的文案。
这里 app.js 改为动态的写法后,需要脚本解析执行后才下载脚本,可以考虑加个 link preload 提前下载脚本。
link 的 preload 作用可以看我的这篇文章。
思路并不复杂,但改造过程中做了很多工作,遇到了不少问题。这里简单列举一下,不展开讲了,到时候会考虑另写文章讨论。
行文有点仓促,想到什么写什么,希望对你做按需加载语言方案有一定的帮助。
我是啥都写写的前端西瓜哥,欢迎关注我。
‘肆’ nodejs鍐呯疆妯″潡链夊摢浜
涓銆丒xpress妗嗘灦
鍓嶉溃镄勭珷鑺傚凡缁忎粙缁嶈繃浜嗭纴鍙浠ヤ娇鐢╪pm𨱒ュ畨瑁卬ode.js妯″潡銆傚叿浣撴搷浣滆峰弬镦т互鍓嶅啓镄刵odejs姒傝恒
Express鏄涓涓猲odejs镄剋eb寮婧愭嗘灦锛岀敤浜庡揩阃熺殑鎼寤簑eb椤圭洰銆傚叾涓昏侀泦鎴愪简web镄删ttp链嶅姟鍣ㄧ殑鍒涘缓銆侀润镐佹枃链绠$悊銆佹湇锷″櫒URL鍦板潃璇锋眰澶勭悊銆乬et鍜宲ost璇锋眰澶勭悊鍒嗗彂銆乻ession澶勭悊绛夊姛鑳姐
浣跨敤鏂规硶锛屽湪cmd涓镓揿紑浣犳墍𨱍冲垱寤簑eb椤圭洰镄勮矾寰勚傜劧钖庤緭鍏
Express appname
鍗冲彲鍒涘缓涓涓钖崭负appname镄剋eb椤圭洰銆傛带鍒跺彴镓揿嵃缁撴灉
鍦╦ada鏂囦欢涓鏄鍙浠ヤ娇鐢╢or寰鐜鍜宨f鍒ゆ柇璇鍙ョ殑锛屽彲浠ヨ╀綘浣扑细绫讳技JSP镄<%%>鍜宲hp镄<php></php>鍦ㄧ绣椤典笂杈揿嚭鏁版嵁镄勫揩镒熴
涓夈乫orever妯″潡
nodejs浣滀负http链嶅姟鍣锛岄渶瑕佺‘淇濇湇锷¢‘鍒╄繘琛岋纴瑕佹敞镒忎竴涓嬩袱镣癸细
1.钖庡彴链嶅姟杩愯岋纴鐩戞带杩愯屾棩蹇楋纴浠ュ强http杩愯屾棩蹇楋绂
2.纭淇濋”鐩镄勬e父瀹夊叏杩愯岋纴Node.js镄勫惎锷ㄥ懡浠node锛屽緢澶х▼搴︽棤娉曟弧瓒宠繍琛岄渶姹傦绂
Node.js镄刦orever妯″潡鍦ㄧ浜岀偣灏卞彲浠ヨ捣鍒板緢澶х殑浣灭敤锛屽悓镞跺叾𨰾ユ湁鐩戞带鏂囦欢镟存敼銆佽嚜锷ㄩ吨钖绛夊姛鑳姐
forever妯″潡镄勪娇鐢ㄦ柟娉曟湁涓ょ嶏细1.鍦ㄥ懡浠よ屼腑浣跨敤
forever -l forever.log -o out.log -e err.log app.js
-l forever.log -o out.log -e err.log鍒嗗埆鎸囧畾浜唂orever镄勮繍琛屾棩蹇楋纴鑴氭湰娴佹按镞ュ织锛岃剼链杩愯岄敊璇镞ュ织锛屽惎锷ㄥ悗灏嗗湪链鏂囦欢澶逛笅浜х敓out.log銆乪rr.log鏂囦欢銆
2.鍦ㄧ紪镰佷腑require forever妯″潡浣跨敤銆
锲涖丼ocket.IO妯″潡
Socket.IO妯″潡涓昏佸姛鑳芥槸灏哤ebSocket鍗忚搴旂敤鍒版墍链夋祻瑙埚櫒銆备富瑕佺敤浜庡疄镞剁殑闀胯繛鎺ュ氭眰𨱍呴”鐩涓銆
渚嫔傦细鍦ㄧ嚎镵旂绣娓告垙锛屽疄镞惰亰澶┿佸疄镞惰偂绁ㄦ煡鐪嬨佷簩缁寸爜镓鎻忕橱褰旷瓑銆
瀹夎呮柟娉曚粛铹舵槸鍦╟md鍦ㄤ腑杈揿叆npm install socket.io
濡备綍浣跨敤Socket.IO𨱒ュ垱寤轰竴涓椤圭洰銆
闇瑕佸垎鍒瀹炵幇链嶅姟绔鍜屽㈡埛绔镄勯昏緫锛
鍏埚垱寤轰竴涓链嶅姟绔镄刵ode.js鑴氭湰index_server.js
var app = require('http').createServer(handler)//鍒涘缓链嶅姟鍣╝pp
, io = require('socket.io').listen(app)//寮旷敤socket.io妯″潡鐩戝惉app
, fs = require('fs')//寮旷敤鏂囦欢澶勭悊妯″潡
app.listen(80);//鎸囧畾app鐩戝惉镄勭鍙o纴绗浜屼釜鍙傛暟127.0.0.1鍙鐪佺暐
function handler (req, res) {
fs.readFile(__dirname + '/index.html', function (err, data) { if (err) {
res.writeHead(500); return res.end('Error loading index.html');
}
res.writeHead(200);
res.end(data);
});
}
io.sockets.on('connection', function (socket) {
socket.emit('news', { hello: 'world' });
socket.on('my other event', function (data) {
console.log(data);
});
});
鍏朵腑锛宻ocket.emit()涓篠ocket鍙戦佹秷鎭镄勫嚱鏁帮纴绗涓涓鍙傛暟琛ㄧず鍙戦佹秷鎭镄刱ey鍊硷纴绗浜屼釜鍙傛暟涓哄彂阃佹秷鎭镄勫唴瀹癸纴涔熷氨鏄鍙戦佺殑鏁版嵁銆
Socket銆俹n()涓篠ocket鎺ユ敹娑堟伅镄勫嚱鏁帮纴绗涓涓鍙傛暟涓烘帴鏀舵秷鎭镄勫彲浠ュ硷纴绗浜屼釜鍙傛暟涓哄洖璋冨嚱鏁帮纴鍏朵腑锲炶皟鍑芥暟鎼哄甫镄勫弬鏁颁负鎺ユ敹娑堟伅镓鍙戦佺殑鏁版嵁銆
鎺ヤ笅𨱒web鍓岖濡备綍浣跨敤javaScrit 𨱒ヨ繛鎺Socket链嶅姟鍣ㄣ
鏂板缓涓涓猧ndex_client.html
<script type="text/javascript" src="socket.js"></script>
<script type="text/javascript"> var socket = io.connect('http://localhost');//鍒涘缓链鍦皊ock杩炴帴
socket.on('news',function (data) {//Socket鎺ユ敹news娑堟伅镞舵墽琛屽洖璋冨嚱鏁 console.log(data);
socket.emit('my other event',{my:'data'});
});</script>
<script type="text/javascript" src="socket.js"></script>锷犺浇宸茬粡瀹夎呭ソ镄凷ocket.io镄勬湰鍦癑avaScrit鏂囦欢銆
var socket = io.connect('http://localhost');锲犱负绔鍙d负80锛屾墍链夎繖閲屽彲浠ヤ笉绔鍙e彿
socket.on('news',function (data)锝涳綕//瀹㈡埛绔鎺ユ敹news娑堟伅鎴愬姛钖庯纴鍙戦乵y other event娑堟伅鍒版湇锷$锛屽彂阃佺殑娑堟伅鍐呭逛负json瀵硅薄{my:'data'}
鎺ヤ笅𨱒ュ彧闇瑕佽繍琛屾湇锷$镄刬ndex_server.js鏂囦欢𨱒ュ惎锷╯ocket链嶅姟
鏁堟灉锛氩湪娴忚埚櫒杈揿叆http://127.0.0.1鎸塅12璋冨嚭娴忚埚櫒镄勬带鍒跺彴console鍗冲彲鐪嬭佹墦鍗板嚭浜嗕竴涓猳bject瀵硅薄銆
镓ц屽畬姣曞悗鍙鑳戒细鎶ラ敊锛歝atnot find mole socket.io锛岃存槑浣犵殑socket.IO娌℃湁瀹夎咃纴鎴栧凡缁忓畨瑁呭苟閰岖疆涓哄叏灞锛屼絾浣犵殑瀹夎呰矾寰勫苟娌℃湁閰岖疆鍒板湪path涓锛屾墍链夋棤娉曞紩鐢ㄣ
浣犲彲浠ラ夋嫨閰岖疆path锛屾垨钥呭畨瑁呭埌椤圭洰鍐呫傝繖閲屽缓璁瀹夎呭埌浣犵殑椤圭洰鐩褰曚笅锛岃屼笉鏄绠鍗旷矖𨱌寸殑閰岖疆涓哄叏灞銆傚厛鍗歌浇npm uninstall socket.io 杩涘叆鎸囧畾鐩褰曞悗瀹夎卬ode index_server.js
socket.io璇︾粏璇峰弬阒 http://cnodejs.org/topic/50a1fcc7637ffa4155b5a264
浜斻乺equest妯″潡
request妯″潡涓哄紑鍙戣呮彁渚涗简涓绉岖亩鍗曡块梾HTTP璇锋眰镄勬柟娉曘俽equest杩樻敮鎸丠TTPS镄勮块梾鏂规硶銆
瀹夎咃细
npm install requset
request妯″潡锘烘湰涓婅嗙洊浜嗘墍链夌殑HTTP璇锋眰鏂瑰纺濡侴ET锛孭OST锛孒EAD锛娈EL绛夈备絾鍏舵渶锘烘湰镄勪袱涓鏂规硶鏄痳equest.get()鍜宺equest.post().
get鍜宲ost镄勫尯鍒
get锛
1.浣跨敤get钖戞湇锷″櫒鍙戝嚭鍜屾帴鏀剁殑璇锋眰浼氶梼鍦╱rl涔嫔悗銆傜被浼硷细http://www..com锛焛d=1221&name=5555杩欎釜url涓浼犻掍简涓や釜鍙傛暟锛屼竴涓涓篿d锛屼竴涓涓簄ame銆
2.get璇锋眰涓嶈兘瓒呰繃1024涓瀛楄妭銆
post娌℃湁闄愬埗锛屼篃涓崭细闄勫湪url涓娿
鎺ヤ笅𨱒ュ仛涓涓绠鍗旷殑瀹炰緥
get瀹炰緥锛
棣栧厛鏂板缓涓涓链嶅姟鍣╝pp_get.js
var http= require("http");
http.createServer(function(req,res){
res.writeHead(200,{'content-Type':'text/plain'});
res.end('Hello world
'+req.method);
}).listen(1337,"127.0.0.1");
鍐嶅缓涓涓鍙戦佹眰𨱍呯殑request_get.js鏂囦欢
var request=require('request');
request.get("http://127.0.0.1:1337",function(error,response,result){
console.log(result);
});
鍦–MD涓杩愯宎pp_get.js锛岃繍琛屾垚锷熷悗锛屽啀镓揿紑涓涓猚md锛堜箣鍓岖殑cmd涓嶈佸叧闂锛夛纴镓ц宺equest_get.js鏂囦欢銆
镓ц屽悗镄勭粨鏋滃备笅
hello world
GET
鍙浠ョ湅鍑猴纴阃氲繃request.get鏂规硶璁块梾
http://127.0.0.1:1337 杩斿洖镄勭粨鏋滃氨鏄痳es.end锛堬级镄勫弬鏁
post瀹炰緥锛
鍜屼笂闱涓镙凤纴鍏堟柊寤烘湇锷″櫒app_post.js
var http= require("http"),
querystring=require('querystring');
http.createServer(function(req,res){ var postData=""; //寮濮嫔纾姝ユ帴鏀跺㈡埛绔痯ost镄勬暟鎹
req.addListener("data",function (postDataChunk) {
postData += postDataChunk;
}); //寮傛post鏁版嵁鎺ユ敹瀹屾瘯钖庢墽琛屽尶钖嶅洖璋冨嚱鏁
req.addListener("end",function(){ var postStr=JSON.stringify(querystring.parse(postData));
res.writeHead(200,{'content-Type':'text/plain'});
res.end(postStr+'
'+req.method);
});
}).listen(1400,"127.0.0.1");
铹跺悗鍐嶆柊寤轰竴涓猺equest_post.js
var request=require("request");
request.post('http://127.0.0.1:1400',{form:{'name':'ermu','book':'node.js'}},function (error,response,result) {
console.log(result);
})
镀忎笂闱涓镙峰湪cmd涓镓ц屽悗鏄剧ず镄勭粨鏋滃备笅锛
D:
odejssrc
equest>node request_post.js
{"name":"ermu","book":"node.js"}
POST
request post鎻愪氦浜嗕竴涓猨son瀵硅薄{"name":"ermu","book":"node.js"}钥屾湇锷″櫒鎺ラ氲繃銮峰彇璇POST鏁版嵁锛岀劧钖庤繑锲炲㈡埛绔锛屽悓镞跺皢http璇锋眰鏂瑰纺涔熷搷搴斿埌瀹㈡埛绔銆
request post鍙傛暟鍙浠ユ湁涓ょ崭紶阃掓柟寮忋
鍏朵腑锛岀涓绉嶆槸灏唘rl鍜宖orm琛ㄥ崟镄勬暟鎹浣滀负json鍙傛暟鍦╮equest post浼犻掋备妇渚嫔备笅锛
request.post('url':'http://127.0.0.1:1400',form:{'name':'ermu','book':'node.js'}},function (error,response,result) {
console.log(result);
})
鍙︿竴绉嶆槸灏唘rl鍜宖orm浣滀负涓や釜鍙傛暟锛屼笂闱㈢殑瀹炰緥灏辨槸浣跨敤杩欑嶆柟娉曘
鍏銆 Formidable妯″潡
璇ユā鍧楃殑鐩镄勬槸涓轰简瑙e喅鏂囦欢涓娄紶銆
鍦ㄥ师鐢熺殑node.js妯″潡涓锛屾彁渚涗简銮峰彇post鏁版嵁镄勬柟娉曪纴浣嗘槸骞舵病链夌洿鎺ヨ幏鍙栦笂浼犳枃浠躲