NodeJS中的静态资源管理服务

欢迎大家指导与讨论 : )

  一、什么是静态资源

  静态资源就是放在服务器中的特定的文件。比较常见的有.css,.png, .js的这一些后缀的文件。下图中的这个html页面便要获取到logo.png和asd.css这两个在服务器中的文件。而服务器呢,也要根据这些各种各样资源的请求,返回对应的MIME类型和对应的资源。分享一个查询MIMEType的地址 http://www.freeformatter.com/mime-types-list.html#mime-types-list  本文最后有实现代码~

  二、为什么需要静态资源管理服务

  那为什么我们需要资源管理服务呢?比如说上图的这个html文件,当我们进入到http://127.0.0.1/index.html(这里举个例子),这个文件不是会自己申请logo.png和asd.css资源了吗?我们还需要做其他的东西吗?对的。这个文件(html)确实会发出这两个资源的请求。如下图。但是各位注意哦~这两个请求资源的pathname我们没有在服务器中进行处理,因此html文件是无法获取到嵌套在html里面的这几个文件的~比如说,一位妈妈第一次带着她的两个小孩去图书馆,妈妈呢一早就有图书馆的通行证了(在服务器中对"妈妈"这个请求资源授予处理)~所以呢,管理员可以让妈妈同行。但是那两位小朋友呢,由于还没有办卡(服务器没有对该资源请求进行处理),所以呢那两位小朋友不让进去图书馆。因此,我们需要在服务器中额外增加一个静态资源管理服务,针对这些额外的资源请求来进行对应的处理(相当于在那个图书馆建一个办卡区,图书馆管理员: "hey! 你们两个! 先过去那边办卡就可以进去了!")。

  三、怎么构建静态资源管理服务

  解决方案是:根据不同请求的资源的后缀,返回不同的mime-type,并使用不同的资源的路径来返回对应资源。简单来说,就是根据某位同学的姓名,去到对应的宿舍,然后就能找到他/她。

  三 . 1 MIME-Type

  MIME-Type就是某个不同后缀的文件,会有其对应的MIME类型(比如说 .苹果是水果类, .生菜是蔬菜类)。我们返回资源的同时还要一起返回它对应的MIME类型,以便浏览器能够根据这个MIME资源,正确地解析出我们所返回的资源。(分享:上面有个需要FQ才能上,但是比较全的MIME查询网站)。通常呢,我们把这些后缀名称和它所对应MIME类型做出一个.json文件,以便服务器能够查询。

  三 . 2 构建静态资源管理服务

  让我们先理一下具体的操作步骤吧~

  1. 服务器接受到"/index"的请求  2. 服务器返回一个"index.html"页面  3. "index.html"发出"logo.png"和"asd.css"的资源请求  4. 服务器进入静态资源管理服务模块  5. 管理模块获取这两个资源请求的pathname和后缀名extname  6. 定义资源的具体路径(__dirname + ‘/xxx‘ + pathname或者__dirname + pathname这个根据不同架构会用略小的差别)  7. 根据mime_type.json获取这两个资源对应的MIME类型  8. 根据资源的路径,查询服务器上是不是存在这个资源  9. 不存在则返回404  10. 存在则读取资源并返回给客户端(到这步我们已经成功构建了静态资源的管理服务了)  11. 缓存部分 请继续往下看吧O(∩_∩)O)

  四、浏览器中的静态资源缓存

  当我们还没有设置资源缓存的时候(比如说刚刚的llogo.png和asd.css),即使浏览器已经通过服务器下载到了这两个资源,但是每当我们刷新浏览器的时候,浏览器还会继续从服务器中拉取所需要的资源,并增加了服务器的压力。我们需要做的是:当浏览器再次刷新时,让它从本地的缓存库(浏览器第一次访问服务器,并在服务器中所下载好的资源)中获取对应的资源,而不是又从服务器中重新下载一遍。

  四 . 1 资源的属性与If-Modified-Since

  每个浏览器所下载好的文件,浏览器都会知道这个文件(资源)的属性,包括这个文件创建时间、这个文件最后修改的时间(If-Modified-Since)等等一些信息。当浏览器的本地缓存中存在(比如是asd.css文件),但是不知道它还有木有效的时候,浏览器会发出一个条件get请求,而If-Modified-Since就包含在它的请求头中。我们所需要做的是进行判断:如果服务端文件在这个时间后发生过更改,则服务端发送文件给客户端,如果没有更改过,则返回304,不发送文件给客户端,而是让浏览器使用缓存中的同名资源。

  四 . 2 Expires和Cache-Control

  服务端在响应的时候带上expires头,浏览器会判断expires头,直到指定的日期过期,才会发起新的请求。

  、整体代码

/*static_module.js*/
var fs = require(‘fs‘);
var sys = require(‘util‘);
var http = require(‘http‘);
var url = require(‘url‘);
var path = require(‘path‘);

var BASE_DIR = __dirname;
var CONF = BASE_DIR + ‘/conf/‘;
var STATIC = BASE_DIR  ;
var mimeConf = getUrlConf();
var CACHE_TIME = 60*60*24*365;

exports.getStaticFile = function(pathname, res, req){
    var extname = path.extname(pathname);
    extname = extname ? extname.slice(1) : ‘‘;
    var realPath = STATIC + pathname;
    var mimeType = mimeConf[extname] ? mimeConf[extname] : ‘text/plain‘;
    console.log(extname);

    fs.exists(realPath, function(exists){
        if(!exists){
            console.log(realPath + " is not found.")
            res.writeHead(404, {‘Content-Type‘:‘text/plain‘});
            res.write(‘Sorry, Not Found This Source.‘);
            res.end();
        }else{
            var fileInfo = fs.statSync(realPath);
            var lastModified = fileInfo.mtime.toUTCString();

            if(mimeConf[extname]){
                var date = new Date();
                date.setTime(date.getTime() + CACHE_TIME * 1000);
                res.setHeader("Expires", date.toUTCString());
                res.setHeader("Cache-Control", "max-age=" + CACHE_TIME);
                res.setHeader("Last-Modified", lastModified);
            }
            if(req.headers[‘if-modified-since‘] && lastModified == req.headers[‘if-modified-since‘] ){
                res.writeHead(304, "Not Modified");
                res.end();
            }else{

                fs.readFile(realPath, "binary", function(err, file){
                    if(err){
                        res.writeHead(500, {‘Content-Type‘: ‘text/plain‘});
                        res.end(err);
                    }else{
                        res.writeHead(200, {‘Content-Type‘: mimeType});
                        res.write(file, "binary");
                        res.end();
                    }
                })
            }
        }
    })

}

function getUrlConf(){
    var routerMsg = {};
    try{
        var str = fs.readFileSync(CONF + ‘mime_type.json‘, ‘utf8‘);
        routerMsg = JSON.parse(str);
    }catch(e){
        sys.debug("JSON parse fails")
    }
    return routerMsg;
}

  参考资料

  《NodeJS开发实战详解》P96

时间: 2024-08-28 12:45:14

NodeJS中的静态资源管理服务的相关文章

nodejs中UDP服务的构建

nodejs中UDP服务的构建 by 伍雪颖 server.js var dgram = require('dgram'); var server = dgram.createSocket("udp4"); server.on("message",function(msg,rinfo) { console.log("Server got: "+msg+" from "+rinfo.address+":"+r

在NodeJS中玩转Protocol Buffer

Protocol Buffer入门教程 Protocol Buffer是个什么鬼 NodeJS开发者为何要跟Protocol Buffer打交道 在NodeJS中实践Protocol Buffer协议 选择支持protobuf的NodeJS第三方模块 一个栗子 书写proto文件 编译 proto 文件 编写 Writer 编写Reader 运行结果 再举一个栗子 编写proto 编写client 书写server 运行结果 其他高级特性 嵌套Message Import Message 总结一

Django -> debug模式下的静态文件服务(/media/)

正式发布django项目的时候,如果存在静态文件(一般会统一放在名称为media或static的目录下),则需要建立url到文件系统的映射,例如,使用nginx的时候我们需要进行这样的配置. # Django media location /media { alias /home/lyndon/github/Mathematician/dijkstra/media; } location /static { alias /home/lyndon/github/Mathematician/dijk

Etag缓存在PHP和NodeJS中的实现

HTTP 提供了许多页面缓存的方案,其中属 Etag 和 Last-Modified 应用最广.本文会先介绍 Etag 的应用场景,然后说说他在 php 和 node 中的使用. 本文地址:http://www.cnblogs.com/hustskyking/p/etag-in-node.html,转载请注明源地址. 一.Etag的使用 客户端和浏览器之间的交互: +---------+ 1 +---------+ | |---------------->| | | | 2(200,OK) |

Node.js 的Web 应用 静态资源管理

静态资源管理  html 页面中的.CSS文件会产生一个 HTTP 请求获取 css 文件资源,发出请求URL,但是 没有对这个资源发挥 .css 文件的信息.作为服务器端并不知道客户端请求的资源是 .css 文件, 服务器端没有逻辑去处理/xx.css 的请求.因此不会正常响应返回一个xx.css数据. 同样包含的 JavaScript 文件和图片也有同样问题. 使用静态资源管理加载图片和CSS样式文件 index.html style.css static.js

Andrdoid中实现静态的默认安装和卸载应用

最近好长时间都没有写blog了,主要是因为最近工作上的事以及下载Android源码的事耽误的(下载源码这件事会在后续的blog中写道,这个真的很有意义呀~~),那么今天来写点什么呢?主要的灵感来自于早上看新闻看到一篇文章说有一款应用在后台中卸载用户手机中的所有浏览器的app,不会被用户察觉,但是最后百度浏览器还是用反侦察技术找到这个邪恶的应用然后将其告上法庭了.那么我们就来看看怎么能够实现应用的静态安装和卸载呢?就是不让用户知道,下面就来一步一步的介绍一下实现步骤: 一.访问隐藏的API方式进行

Dotnet Core 在ASP.NET Core中使用静态文件

来自微软官网  在ASP.NET Core中使用静态文件:https://docs.microsoft.com/zh-cn/aspnet/core/fundamentals/static-files: 提供静态文件 静态文件通常位于web root(<content-root> / wwwroot)文件夹中.有关详细信息,请参阅内容根和Web根.您通常将内容根设置为当前目录,以便web root在开发过程中找到项目. public static void Main(string[] args)

在linux中设置静态ip地址

在linux中设置静态ip地址1.在终端中输入:vi /etc/sysconfig/network-scripts/ifcfg-eth0 2.开始编辑,填写ip地址.子网掩码.网关.DNS等[[email protected] 桌面]# cat /etc/sysconfig/network-scripts/ifcfg-eth0 DEVICE=eth0  #设备名称TYPE=Ethernet #网络类型UUID=bfafdad5-e1c9-4adf-864b-c772e4965ab7ONBOOT=

用nodejs搭建一个简单的服务监听程序

作为一个从业三年左右的,并且从事过半年左右PHP开发工作的前端,对于后台,尤其是对以js语言进行开发的nodejs,那是比较有兴趣的,虽然本身并没有接触过相关的工作,只是自己私下做的一下小实验,但是还是记录一下方便以后复习! 今天主要记录一下,很久以前用nodejs制作一个简单的服务监听程序的一些过程! 大家都知道,通过nodejs可以对前台请求进行监听,这里就放一个官网的hello world例子吧: var http = require('http'); http.createServer(