这次给大家带来怎样操作Node静态资源服务器,操作Node静态资源服务器的注意事项有哪些,下面就是实战案例,一起来看一下。

http服务器是继承自tcp服务器 http协议是应用层协议,是基于TCP的

http的原理是对请求和响应进行了包装,当客户端连接上来之后先触发connection事件,然后可以多次发送请求,每次请求都会触发request事件

let server = http.createServer(); let url = require('url'); server.on('connection', function (socket) { console.log('客户端连接 '); }); server.on('request', function (req, res) { let { pathname, query } = url.parse(req.url, true); let result = []; req.on('data', function (data) { result.push(data); }); req.on('end', function () { let r = Buffer.concat(result); res.end(r); }) }); server.on('close', function (req, res) { console.log('服务器关闭 '); }); server.on('error', function (err) { console.log('服务器错误 '); }); server.listen(8080, function () { console.log('server started at :8080'); });

req 代表客户端的连接,server服务器把客户端的请求信息进行解析,然后放在req上面

res 代表响应,如果希望向客户端回应消息,需要通过 res

req和res都是从socket来的,先监听socket的data事件,然后等事件发生的时候,进行解析,解析出请头对象,再创建请求对象,再根据请求对象创建响应对象

req.url 获取请求路径

req.headers 请求头对象

接下来我们对一些核心功能进行讲解

深刻理解并实现压缩和解压

为什么要压缩呢?有什么好处?

可以使用zlib模块进行压缩及解压缩处理,压缩文件以后可以减少体积,加快传输速度和节约带宽代码

压缩和解压缩对象都是transform转换流,继承自duplex双工流即可读可写流

zlib.createGzip:返回Gzip流对象,使用Gzip算法对数据进行压缩处理

zlib.createGunzip:返回Gzip流对象,使用Gzip算法对压缩的数据进行解压缩处理

zlib.createDeflate:返回Deflate流对象,使用Deflate算法对数据进行压缩处理

zlib.createInflate:返回Deflate流对象,使用Deflate算法对数据进行解压缩处理

实现压缩和解压

因为压缩我文件可能很大也可能很小,所以为了提高处理速度,我们用流来实现

let fs = require("fs"); let path = require("path"); let zlib = require("zlib"); function gzip(src) { fs .createReadStream(src) .pipe(zlib.createGzip()) .pipe(fs.createWriteStream(src + ".gz")); } gzip(path.join(dirname,'msg.txt')); function gunzip(src) { fs .createReadStream(src) .pipe(zlib.createGunzip()) .pipe( fs.createWriteStream(path.join(dirname, path.basename(src, ".gz"))) ); } gunzip(path.join(dirname, "msg.txt.gz"));

gzip方法用于实现压缩

gunzip方法用于实现解压

其中文件msg.txt是同级目录

为什么需要这么写:gzip(path.join(dirname,'msg.txt'));

因为console.log(process.cwd());打印出当前工作目录是根目录,并不是文件所在目录,如果这么写gzip('msg.txt');找不到文件就会报错

basename 从一个路径中得到文件名,包括扩展名的,可以传一个扩展名参数,去掉扩展名

extname 获取扩展名

压缩的格式和解压的格式需要对上,否则会报错

有些时候我们拿到的字符串不是一个流,那怎么解决呢

let zlib=require('zlib'); let str='hello'; zlib.gzip(str,(err,buffer)=>{ console.log(buffer.length); zlib.unzip(buffer,(err,data)=>{ console.log(data.toString()); }) });

有可能压缩后的内容比原来还大,要是内容太少的话,压缩也没什么意义了

文本压缩的效果会好一点,因为有规律

在http中应用压缩和解压

下面实现这样一个功能,如图:

客户端向服务器发起请求的时候,会通过accept-encoding(比如:Accept-Encoding:gzip,default)告诉服务器我支持的解压缩的格式

服务器端需要根据Accept-Encoding显示的格式进行压缩,没有的格式就不能压缩,因为浏览器无法解压

如果客户端需要的Accept-Encoding中的格式服务端没有,也无法实现压缩

let http = require("http"); let path = require("path"); let url = require("url"); let zlib = require("zlib"); let fs = require("fs"); let { promisify } = require("util"); let mime = require("mime"); //把一个异步方法转成一个返回promise的方法 let stat = promisify(fs.stat); http.createServer(request).listen(8080); async function request(req, res) { let { pathname } = url.parse(req.url); let filepath = path.join(dirname, pathname); // fs.stat(filepath,(err,stat)=>{});现在不这么写了,异步的处理起来比较麻烦 try { let statObj = await stat(filepath); res.setHeader("Content-Type", mime.getType(pathname)); let acceptEncoding = req.headers["accept-encoding"]; if (acceptEncoding) { if (acceptEncoding.match(/\bgzip\b/)) { res.setHeader("Content-Encoding", "gzip"); fs .createReadStream(filepath) .pipe(zlib.createGzip()) .pipe(res); } else if (acceptEncoding.match(/\bdeflate\b/)) { res.setHeader("Content-Encoding", "deflate"); fs .createReadStream(filepath) .pipe(zlib.createDeflate()) .pipe(res); } else { fs.createReadStream(filepath).pipe(res); } } else { fs.createReadStream(filepath).pipe(res); } } catch (e) { res.statusCode = 404; res.end("Not Found"); } }

mime:通过文件的名称、路径拿到一个文件的内容类型, 可以根据不同的文件内容类型返回不同的Content-Type

acceptEncoding:全部写成小写是为了兼容不同的浏览器,node把所有的请求头全转成了小写

filepath:得到文件的绝对路径

启动服务后,访问:8080/msg.txt 可看到结果

深刻理解并实现缓存

为什么要缓存呢,缓存有什么好处?

减少了冗余的数据传输,节省了网费。

减少了服务器的负担, 大大提高了网站的性能

加快了客户端加载网页的速度

缓存的分类

强制缓存:

强制缓存,在缓存数据未失效的情况下,可以直接使用缓存数据
在没有缓存数据的时候,浏览器向服务器请求数据时,服务器会将数据和缓存规则一并返回,缓存规则信息包含在响应header中

对比缓存:

浏览器第一次请求数据时,服务器会将缓存标识与数据一起返回给客户端,客户端将二者备份至缓存数据库中

再次请求数据时,客户端将备份的缓存标识发送给服务器,服务器根据缓存标识进行判断,判断成功后,返回304状态码,通知客户端比较成功,可以使用缓存数据

两类缓存的区别和联系