上个星期在慕课网上提了个问:Express4开发的动态页面访问好慢的说?不幸的是并没有得到可行的回答,周末自己折腾了一番,一并将小站(花满楼)的几个页面全部静态化了;事后想了想,虽不是什么特别标准好的搞法,但纠结这么久了,这个问题终于有办法了,还是有些欣慰的;
一开始页面都是动态的,由jade模板render出来的,可不明白为什么不论页面内容多少,打开都至少要一秒多。。。;后来专门弄个站点作为静态资源站,缓存加gzip(Nodejs打造静态资源服务器与文件上传);OK,静态资源现在没啥大问题了;可是页面打开速度并不理想,那后台再压一遍吧,来个app.use(compress());事实证明并没啥明显效果;郁闷的我刚学点Nodejs,咋就碰到这无语的问题呢,百度好久,呵呵。。。最后只想到一个办法了,参照静态资源站的搞法,将jade编译成html,把动态页面转成静态资源来对待,会不会像加载静态资源一样快呢!答案是肯定的!!!
就我的博客站点来说,现在面临两个问题:一是直接将原来的jade编译,保留动态数据;二是现将动态数据剔除,再编译为html,由ajax页面加载后请求数据;我选择了前者,因为这样能在静态页面上保留最新的数据,而后者由js后面渲染上去的对SEO很不好;呵呵,而实际上这两种方法我都没用,因为就这点水平来说,在express的框架里,并没听说这种搞法,我自然就无从下手了,只是理想上的可行方案;
那咋办呢?好吧,原谅我选择了放弃express内置的模板,稍作整理后,Gulp(gulp-jade模块)直接将那些jade全编译为html(前端自动化之神器 — Gulp),我是这样想的,将这些编译后的html做为一种类似模板的模块,在routes里还是原来那样拿数据,将拿到的数据作为变量传递到html类模板那个模块对应的接口,然后将返回的html生成一个真正的静态页面,这样,原来的jade,在router不变的情况下,直接生成到对应目录了;上面说过要像加载静态资源一样加载页面,才可能够快;
Gulpfile.js
var jade=require('gulp-jade');
gulp.task('jade',function() {
gulp.src('./views/bokeDetail.jade')
.pipe(jade({pretty:true}))
.pipe(gulp.dest('./public/famanoder/'));
});
bokeDetail.templ.js
var html=function(id,title,subtitle,time,from,contents){
//传递动态数据
return '<html><head></head><body>'+动态数据+'</body></html>';
}
//片段,实际情况而定
module.exports=html;
bokeDetail.js(router)
//......
//引入对应静态模块
var boketempl=require('./templs/bokeDetail.templ.js);
//依旧读取数据
//传递数据:如,id,title,content,comments
//生成静态页面到指定目录
function createStaticPage(id,title,content,comments,fn){
var path='./public/famanoder/';
var html=boketempl(id,title,content,comments);
var ws=fs.createWriteStream(path+id+'.html');
ws.write(html,function(err) {
console.log('writePage:'+path+id+'.html');
fn&&fn();
});
ws.on('drain',function() {
ws.end();
});
}
ok,程序执行后静态页面就会带着动态数据生成到public下的famanoder目录了;下面还是在bokeDetail.js(router)里将response直指上面生成的静态页面;
var pathname=url.parse(req.url).pathname;
var realpath='./public/famanoder/'+pathname.substr(pathname.lastIndexOf('/')+1)+'.html';
var type='text/html';
var extname='html';
fs.exists(realpath,function(exist){
if(!exist){console.log(101);
res.writeHead(404,{
'content-type':'text/plain'
});
res.write('The Resourse '+pathname+' was Not Found!');
res.end();
}else{
fs.readFile(realpath,'binary',function(err,file){
console.log(11);
if(err){
res.writeHead(500,{
'content-type':'text/plain'
});
res.end();
}
if(extname.match(config.fileMatch)){
var expires=new Date();
expires.setTime(expires.getTime()+config.maxAge*1000);
res.setHeader('Expires',expires.toUTCString());
res.setHeader('cache-control','max-age='+config.maxAge);
}
fs.stat(realpath,function(err,stat){
var lastModified=stat.mtime.toUTCString();
res.setHeader('Last-Modified',lastModified);
if(req.headers['if-modified-since']&&lastModified==req.headers['if-modified-since']){
console.log(0);
res.writeHead(304,{
'content-type':type
});
res.end();
}else{
var raw=fs.createReadStream(realpath);
var acceptEncoding=req.headers['accept-encoding']||'';
var matched=extname.match(/css|js|html/ig);
if(matched&&acceptEncoding.match(/\bgzip\b/)){
console.log(1);
res.writeHead(200,{
'content-type':type,
'Content-Encoding':'gzip'
});
raw.pipe(zlib.createGzip()).pipe(res);
}else if(matched&&acceptEncoding.match(/\bdeflate\b/)){
console.log(2);
res.writeHead(200,{
'content-type':type,
'Content-Encoding':'deflate'
});
raw.pipe(zlib.createDeflate()).pipe(res);
}else{
console.log(3);
res.writeHead(200,{
'content-type':type
});
raw.pipe(res);
}
}
});
});
}
});
再次访问详情页,看看秒开了吧,纯静态的,路由没变,url没改,维护也很简单,只要改下bokeDetail.templ.js就可以了;没办法啊,可能在大侠眼里这样很愚蠢,就当逗您一笑吧;类似这种搞法,现在小站全部页面都静态化了,而且完全照顾到了SEO;
好吧,其实还遗留了一个重要问题:就博客详情来说,原来如果有大批博客,现在怎么批量转呢,其实我是在博客编辑好后提交时顺便生成静态页面的,为了详情页再快点。。。;问题来了,在这之前如果我有几百上千篇博客(当然我这个小前端还远没达到这么丰硕的成果),我不得每篇博客重新编辑提交一次;吓死宝宝了啊,别急,新建一个update.js直接批量生成吧,快的很!
Artical
.find({}).exec(function(err,docs) {
update(err,docs);
});
function update(err,docs) {
err&&console.log(err);
for(var i=0;i<docs.length;i++){
(function(i){
createStaticFile(docs[i]._id,docs[i].title,docs[i].subtitle,docs[i].time,docs[i].from,docs[i].contents,function() {
console.log((i+1)+'/'+docs.length+':updated');
if (i==docs.length-1) {
res.render('page/fifity',{
title:'updateBokes',
docs:docs.length
});
};
})
})(i);
}
}
其他牛逼启动更新的方式就不多讲了,
那么该轮到优化服务器和数据库了吧;好吧。。。我后端渣渣,服务器更不谈了,暂且就这样吧,毕竟几十块钱的服务器;小前端刚学Nodejs,诸多不足,望大侠路过指导;晚安!
本文出自慕课网,转载请注明出处,侵权必究。
热门评论
有木有源码呀 后端渣渣学习
var boketempl=require('./templs/bokeDetail.templ.js);
这里是不是少了个单引号?后面的内容 全是string高亮 看得不太舒服
长得帅写得也好的人不多了。