我是一枚小前端,前段时间开始学习Express4,并试着开发了一个博客站点,就个人站点来说,服务器配置并不是太差,可问题却很是伤脑筋:访问响应特别慢!原谅我非计算机专业出身,初入前端,后台并不太懂!后来使用HTML5的离线缓存加了个manifest,缓存后快的像本地静态文件样!然而小站由于个人自恋,动态内容不少,而技术强度又没达到,发现HTML5的这一套在这并不适用!所以该想其他办法了,于是想到了公司的项目,静态资源有另一个服务器打理,也就是静态资源服务器,静态资源既有压缩也有缓存,加载可快了;百度了一下,没想到基于Nodejs的静态资源服务器讲解文档不少呢,于是决定弄个折腾下;
其实静态资源的加载就是一个GET请求,客户端通过资源路径请求服务器的资源,服务器读取资源,返回状态码,设置响应头,调取资源响应到客户端,大致就这样一个过程;
下面开始搭建了:我是直接在同一个服务器下,开启了一个新站点,在主站点里,由Nodejs的反向代理,将静态资源的请求分发到静态资源的站点;原谅我前端出身,目前钟情于Nodejs,暂时还学不来大名鼎鼎的Nginx和阿帕奇;
case 'cdn.famanoder.com': //静态资源站的host
proxy.web(req, res, { target: 'http://localhost:4000' });//静态资源站在4000端口
break;
npm模块不可少,还是先通过npm init生成一个package.json吧;安装文件上传模块:npm install --save formidable,还需要用到的模块有http,url,path,fs,zlib,依次require进来,另外需要备一个mimeType模块;准备工作差不多了,如果也大概知道接下来怎么做了,那么开始正式搭建咱的静态服务器吧,第一次弄,难免粗糙,可是原理基本就是这样,具备了思维,写代码应该不会太难了,Bug尽管想我飞来吧!
粗步的分为GET和POST请求吧;GET处理静态资源的请求,POST处理接下来的文件上传,其他暂不做处理了,静态资源服务器嘛;处理静态资源的请求大概是这个路子:拿到请求的pathname,添加静态资源主目录dist,类似Express里的app.use(express.static(path.join(__dirname, 'public')));首先由fs.exists判断请求资源是否存在,不存在返回晦气的404,存在则读取该资源,不留神出错返回500,反之通过请求头的if-modified-since判断是否已缓存,已缓存返回304,反之由zlib压缩之,以管道方式返回资源,状态码自然是200了;下面是粗制的代码片段,仅供参考:
if (req.method=='GET') {
var pathname=url.parse(req.url).pathname;
var realpath='';
if (pathname==='/') {
realpath='welcome.html';
}else{
realpath=path.join('dist',path.normalize(pathname.replace(/\.\./g,'')));
}
var extname=path.extname(realpath);
extname=extname?extname.slice(1):'unknown';
var type=mime[extname]||'text/plain';
fs.exists(realpath,function(exist){
if(!exist){
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){
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']){
res.writeHead(304,'ok');
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/)){
res.writeHead(200,{
'Content-Encoding':'gzip'
});
raw.pipe(zlib.createGzip()).pipe(res);
}else if(matched&&acceptEncoding.match(/\bdeflate\b/)){
res.writeHead(200,{
'Content-Encoding':'deflate'
});
raw.pipe(zlib.createDeflate()).pipe(res);
}else{
res.writeHead(200,'ok');
raw.pipe(res);
}
}
});
});
}
});
}
}
勿取笑,看下重点,文件上传到静态资源服务器;这在另一个POST请求里:
else{
var pathname=url.parse(req.url).pathname;
if (pathname=='/upload.html') {
var mainId=new Date().getTime();
var form=new formidable.IncomingForm();
form.encoding='utf-8';
form.uploadDir = 'dist/'+url.parse(req.url,true).query.dir+'/';
form.keepExtensions = true;
form.maxFieldsSize = 1000 * 1024 * 1024;
var byted=null;
form.on('error',function(err){
console.log(err);
})
.on('aborted',function(){
console.log('aborted');
})
.on('progress',function(bytesReceived, bytesExpected){
console.log(bytesReceived, bytesExpected);
});
form.parse(req,function(err,field,files){
if(err){console.log(err);}
var files=files.editUploadFile;
var newPath='......';
console.log('uploaded:'+newPath);
fs.renameSync(files.path,newPath);
res.end();
});
};
}
那么现在现在静态资源的请求就涉及到跨域问题了,不多说了,设置如下响应头:
res.writeHead(200,{
'Access-Control-Allow-Origin':'*',
"Access-Control-Allow-Headers":"X-Requested-With",
"Access-Control-Allow-Methods":"PUT,POST,GET,DELETE,OPTIONS"
});
到此,静态资源服务器可以上线用了,加了缓存和压缩,更多对静态资源的处理,还在探索中……,
如果文件上传程序已搞定,基本上没什么大问题了,只是要注意跨域问题,主域和子域同时设置document.domain='famanoder.com';是一种方案,其他方案,尽情度娘吧!
npm社区如此火热强大,静态资源服务器自然少不了现成模块供君使用,推荐anywhere模块,只需安装模块,进入文件目录anywhere port即架起了一个静态服务器,方便不少呢!
本文为慕课网作者原创,转载请标明【原文作者及本文链接地址】。侵权必究,谢谢合作!
热门评论
棒棒哒!好久没见你更新文章了