码迷,mamicode.com
首页 > Web开发 > 详细

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

时间:2016-01-20 00:59:17      阅读:577      评论:0      收藏:0      [点我收藏+]

标签:

      上个星期在慕课网上提了个问: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‘:type
35                             });
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‘:type
59                                 });
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.length
16                         });
17                     };
18                 })
19             })(i);
20         }
21     }

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

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

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

标签:

原文地址:http://www.cnblogs.com/hufeng/p/5143744.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!