Nodejs基于Express4的动态页面静态化

来源:互联网 发布:nginx mac 安装 编辑:程序博客网 时间:2024/05/12 13:15

Nodejs基于Express4的动态页面静态化

上个星期在慕课网上提了个问: 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

1 var jade=require('gulp-jade');2 3 gulp.task('jade',function() {4     gulp.src('./views/bokeDetail.jade')5         .pipe(jade({pretty:true}))6         .pipe(gulp.dest('./public/famanoder/')); 7 });

bokeDetail.templ.js

1 var html=function(id,title,subtitle,time,from,contents){2          //传递动态数据3          return '<html><head></head><body>'+动态数据+'</body></html>';4 }5 //片段,实际情况而定

bokeDetail.js(router)

 1 //...... 2 //引入对应静态模块 3 var boketempl=require('./templs/bokeDetail.templ.js); 4  5 //依旧读取数据 6 //传递数据:如,id,title,content,comments 7 //生成静态页面到指定目录 8 function createStaticPage(id,title,content,comments,fn){ 9                 var path='./public/famanoder/';10                 var html=boketempl(id,title,content,comments);11                 var ws=fs.createWriteStream(path+id+'.html');12         ws.write(html,function(err) {13             console.log('writePage:'+path+id+'.html');14             fn&&fn();15         });16         ws.on('drain',function() {17             ws.end();18         });19 }

ok,程序执行后静态页面就会带着动态数据生成到public下的famanoder目录了;下面还是在bokeDetail.js(router)里将response直指上面生成的静态页面;

 1         var pathname=url.parse(req.url).pathname; 2         var realpath='./public/famanoder/'+pathname.substr(pathname.lastIndexOf('/')+1)+'.html'; 3         var type='text/html'; 4         var extname='html'; 5         fs.exists(realpath,function(exist){ 6             if(!exist){console.log(101); 7                 res.writeHead(404,{ 8                     'content-type':'text/plain' 9                 });10                 res.write('The Resourse '+pathname+' was Not Found!');11                 res.end();12             }else{13                 fs.readFile(realpath,'binary',function(err,file){14                     console.log(11);15                     if(err){16                         res.writeHead(500,{17                             'content-type':'text/plain'18                         });19                         res.end();20                     }21                     if(extname.match(config.fileMatch)){22                         var expires=new Date();23                         expires.setTime(expires.getTime()+config.maxAge*1000);24                         res.setHeader('Expires',expires.toUTCString());25                         res.setHeader('cache-control','max-age='+config.maxAge);26                     }27                     fs.stat(realpath,function(err,stat){28                         var lastModified=stat.mtime.toUTCString();29                         res.setHeader('Last-Modified',lastModified);30                         31                         if(req.headers['if-modified-since']&&lastModified==req.headers['if-modified-since']){32                             console.log(0);33                             res.writeHead(304,{34                                 'content-type':type35                             });36                             res.end();37                         }else{38                             var raw=fs.createReadStream(realpath);39                             var acceptEncoding=req.headers['accept-encoding']||'';40                             var matched=extname.match(/css|js|html/ig);41                             if(matched&&acceptEncoding.match(/\bgzip\b/)){42                                 console.log(1);43                                 res.writeHead(200,{44                                     'content-type':type,45                                     'Content-Encoding':'gzip'46                                 });47                                 raw.pipe(zlib.createGzip()).pipe(res);48                             }else if(matched&&acceptEncoding.match(/\bdeflate\b/)){49                                 console.log(2);50                                 res.writeHead(200,{51                                     'content-type':type,52                                     'Content-Encoding':'deflate'53                                 });54                                 raw.pipe(zlib.createDeflate()).pipe(res);55                             }else{56                                 console.log(3);57                                 res.writeHead(200,{58                                     'content-type':type59                                 });60                                 raw.pipe(res);61                             }62                         }63                     });64                 });65             }66         });

再次访问详情页,看看秒开了吧,纯静态的,路由没变,url没改,维护也很简单,只要改下bokeDetail.templ.js就可以了;没办法啊,可能在大侠眼里这样很愚蠢,就当逗您一笑吧;类似这种搞法,现在小站全部页面都静态化了,而且完全照顾到了SEO;

好吧,其实还遗留了一个重要问题:就博客详情来说,原来如果有大批博客,现在怎么批量转呢,其实我是在博客编辑好后提交时顺便生成静态页面的,为了详情页再快点。。。 ;问题来了,在这之前如果我有几百上千篇博客(当然我这个小前端还远没达到这么丰硕的成果),我不得每篇博客重新编辑提交一次;吓死宝宝了啊,别急,新建一个update.js直接批量生成吧,快的很!

 1 Artical 2     .find({}).exec(function(err,docs) { 3         update(err,docs); 4     }); 5  6     function update(err,docs) { 7         err&&console.log(err); 8         for(var i=0;i<docs.length;i++){ 9             (function(i){10                 createStaticFile(docs[i]._id,docs[i].title,docs[i].subtitle,docs[i].time,docs[i].from,docs[i].contents,function() {11                     console.log((i+1)+'/'+docs.length+':updated');12                     if (i==docs.length-1) {13                         res.render('page/fifity',{14                             title:'updateBokes',15                             docs:docs.length16                         });17                     };18                 })19             })(i);20         }21     }

其他牛逼启动更新的方式就不多讲了,

那么该轮到优化服务器和数据库了吧;好吧。。。我后端渣渣,服务器更不谈了,暂且就这样吧,毕竟几十块钱的服务器;小前端刚学Nodejs,诸多不足,望大侠路过指导


0 0
原创粉丝点击