如何利用node实现静态文件缓存详解

目录
  • 缓存
    • 缓存位置分类
    • 缓存设置header
  • node实现静态文件缓存
    • 强缓存
      • 思路
      • 代码实现
      • 效果展示
    • 协商缓存
      • 思路
      • 代码实现
      • 效果展示
  • 总结

缓存

浏览器缓存(Brower Caching)是浏览器对之前请求过的文件进行缓存,以便下一次访问时重复使用,节省带宽,提高访问速度,降低服务器压力

缓存位置分类

memory cache:内存中的缓存,关闭浏览器则清空,一般存储一些js库

disk cache:硬盘中的缓存,关闭浏览器不会马上清空,一般存储大文件,比如 图片资源,iconFont这类的图标文件库

两者的区别:

1. 读取速度 :memory cache缓存的是当前解析过了的文件在浏览器tab进程里,下次运行使用时的可以快速读取;

disk cache直接将缓存写入硬盘文件中,读取缓存需要对该缓存存放的硬盘文件进行I/O(读取)操作,然后重新解析缓存内容,速度比内存缓存慢

2. 时效性:memory cache是存在tab的进程里,tab关闭,则清空;

disk cache:被清空的时机我还不知道(希望有人可以补充)

3. 优先级:memory cache大于disk cache

对于大文件来说,大概率是不存储在memory中的,反之优先,代码角度目前好像也无法控制浏览器缓存位置

缓存设置header

cache-control

1.   cache-control:max-age=10//10秒内重新发的请求都直接命中强缓存,无需向服务器发起请求,读取浏览器缓存即可
 2.   Cache-Control:no-cache //禁止强制缓存,每次都向服务器发起请求,同时也会存在浏览器缓存中 (走协商缓存了基本)
 3.   Cache-Control:no-store //每次都请求服务器,且不缓存在浏览器中,等同于没有缓存 
复制代码

Expires:

兼容低版本浏览器,这个就是设置绝对时间,获取的是服务器的当前时间和浏览器当前时间做比对(通常存在偏差,是http1.0的产物),和 cache-control同时存在时,cache-control优先级更高

  • last-modified:协商缓存的时候用 和If-Modified-Since,成对出现;If-Modified-Since请求头的值对应上一次服务器的响应头last-modified的值,拥有提供服务器比对请求资源修改时间,相等,则命中协商缓存返回304,浏览器读取缓存即可
  • Etag:资源标识(也有说时指纹,通常是一个md5值),协商缓存时候用,比较文件是否修改;和If-None-Match 成对出现

Etag主要为了解决 Last-Modified 无法解决的一些问题。

1. 一些文件也许会周期性的更改,但是他的内容并不改变(仅仅改变的修改时间),这个时候我们并不希望客户端认为这个文件被修改了,而重新GET;

2. 某些文件修改非常频繁,比如在秒以下的时间内进行修改,(比方说1s内修改了N次),If-Modified-Since无法检查到如此精细

3. 某些服务器不能精确的得到文件的最后修改时间;

4.Etag与Last-modify同时存在 Etag优先级比较

实际项目:html不允许缓存,html里引用的js有唯一的版本号做依据,再次访问的时候 访问最新的html,引用的js或其他文件版本号未修改则直接用本地缓存

node实现静态文件缓存

文件结构

public对应我们测试用的静态资源

强缓存

思路

  • 创建服务
  • 首次请求 解析请求路径, fs.createReadStream().pipe() 读取文件
  • 设置响应头Cache-Contro:max-age=10 强缓存的相对时间

代码实现

const http = require("http");
const url = require("url");
const fs = require("fs");
const path = require("path");
// 接收文件路径 返回该文件对应的文件类型格式
const mime = require("mime");//npm i mime 

const server = http.createServer((req, res) => {
  let { pathname, query } = url.parse(req.url, true);
  //__dirname 当前文件所在的文件夹所处的绝对路径 和请求路径拼接
  let filePath = path.join(__dirname, "public", pathname);
  console.log(req.url);//10s内反复刷新页面,查看是否持续打印,命中强缓存则10s打印一次
  // 设置头部 缓存信息,规定的缓存时间内,客户端无需再向服务器发起请求
  res.setHeader("Cache-Control", "max-age=10"); // 设置缓存时常;请求的当前时间+max-age 的相对时间内,优先级比Expires高
  res.setHeader("Expires", new Date(Date.now() + 10).toUTCString()); //兼容低版本浏览器,这个就是设置绝对时间,获取的是服务器的当前时间
  // 获取请求路径 判断是文件还是文件目录
  fs.stat(filePath, function (err, statObj) {
    // url解析错误,则请求错误 没有找到对应url资源 返回404
    if (err) {
      res.statusCode = 404;
      res.end("NOT FOUND");
    } else {
      // 如果是文件,用可读流+管道 pipe 进行文件内容读取,利用mime 获取文件内容格式,并设置编码规范为utf-8
      if (statObj.isFile()) {
        fs.createReadStream(filePath).pipe(res);
        res.setHeader(
          "Content-Type",
          mime.getType(filePath) + ";charset=utf-8"
        );
      } else {
        // 如果是文件目录 找到 目录下对应的index.html
        let htmlPath = path.join(filePath, "index.html");
        // fs.access判断拼接的路径是否可访问
        fs.access(htmlPath, function (err) {
          if (err) {
            // 不可访问 设置 状态码404
            res.statusCode = 404;
            res.end("NOT FOUND");
          } else {
            //可访问,用可读流加管道 pipe 进行文件内容读取
            fs.createReadStream(htmlPath).pipe(res);
            res.setHeader("Content-Type", "text/html;charset=utf-8");
          }
        });
      }
    }
  });
  // 写到这里 可以 nodemon cache.js  启动服务 查看 http://localhost:3000/
});
server.listen(3000, () => {
  console.log("server start 3000");
});

效果展示

协商缓存

成功

思路

  • 创建服务
  • 首次请求 解析请求路径, fs.createReadStream().pipe() 读取文件
  • 设置响应头Last-modified 返回浏览器
  • 再次请求,比较浏览器if-last-modified 和当前资源修改时间,相等则命中协商缓存,返回响应码304,反之返回路径对应的最新资源,和响应码200

代码实现

const http = require("http");
const url = require("url");
const fs = require("fs");
const path = require("path");
const mime = require("mime");

  let filePath = path.join(__dirname, "public", pathname);
  console.log(req.url);
  fs.stat(filePath, function (err, statObj) {
    if (err) {
      res.statusCode = 404;
      res.end("NOT FOUND");
    } else {
      if (statObj.isFile()) {
        // 判断 浏览器请求的文件路径 的change 时间 通过statObj.ctime
        const ctime = statObj.ctime.toUTCString();
        // 浏览器请求头if-modified-since ===文件上次的修改时间 ,命中协商缓存,则返回 304 浏览器缓存中请求资源
        if (req.headers["if-modified-since"] === ctime) {
          res.statusCode = 304; //去浏览器缓存中找
          res.end(); //
        } else {
          //  if-modified-since !==文件上次的修改时间,响应头Last-modified 设置 当前请求文件的 修改时间 做下次 浏览器请求的last-modify-since的对应值
          res.setHeader("Last-modified", ctime);
          fs.createReadStream(filePath).pipe(res);
          res.setHeader(
            "Content-Type",
            mime.getType(filePath) + ";charset=utf-8"
          );
        }
      } else {
        fs.access(htmlPath, function (err) {
          if (err) {
            // 不可访问 设置 状态码404
            res.statusCode = 404;
            res.end("NOT FOUND");
          } else {
            fs.createReadStream(htmlPath).pipe(res);
            res.setHeader("Content-Type", "text/html;charset=utf-8");
          }
        });
      }
    }
  });
  // 写到这里 可以 nodemon cache2.js       启动服务 查看 http://localhost:3000/
});
server.listen(3000, () => {
  console.log("server start 3000");
});

效果展示

每次刷新页面都会执行  console.log(req.url); 请求了服务器但服务器返回304 命中协商缓存 浏览器直接读取缓存资源即可

成功

总结

到此这篇关于如何利用node实现静态文件缓存的文章就介绍到这了,更多相关node静态文件缓存内容请搜索我们以前的文章或继续浏览下面的相关文章希望大家以后多多支持我们!

(0)

相关推荐

  • 如何利用node实现静态文件缓存详解

    目录 缓存 缓存位置分类 缓存设置header node实现静态文件缓存 强缓存 思路 代码实现 效果展示 协商缓存 思路 代码实现 效果展示 总结 缓存 浏览器缓存(Brower Caching)是浏览器对之前请求过的文件进行缓存,以便下一次访问时重复使用,节省带宽,提高访问速度,降低服务器压力 缓存位置分类 memory cache:内存中的缓存,关闭浏览器则清空,一般存储一些js库 disk cache:硬盘中的缓存,关闭浏览器不会马上清空,一般存储大文件,比如 图片资源,iconFont

  • 如何使用Node.js遍历文件夹详解

    目录 前言 获取的文件列表为数组格式 获取的文件列表为对象格式 异步方式 比较同步和异步两种方案 附node遍历文件夹并读取文件内容 参考资料 总结 前言 最近在写一个管理 markdown 文件的工具knowledge-center,需要读取指定文件夹内所有 markdown 文件.因此需要用 Node.js 来实现遍历一个文件夹内所有文件的功能. Node.js 中提供了这些有用的 API: fs.readdir:异步读取文件夹 fs.readdirSync:同步读取文件夹 fs.statS

  • 利用node.js如何创建子进程详解

    前言 node本身为单进程,并使用驱动模式处理并发,为了解决单进程在多核cpu上的资源浪费,node提供了cluster和child_process模块来创建多个子进程. Node.js是单线程的,对于现在普遍是多处理器的机器是一种浪费,怎么能利用起来呢?于是child_process模块出现了.child_process模块可以在其他进程上产生.派生,并执行工作. child_process模块提供了一个ChildProcess的新类,它可以作为从父进程访问子进程的表示形式.Process模块

  • Node.js基础入门之缓存区与文件操作详解

    目录 缓存区 1. 什么是缓存区? 2. 创建指定长度的缓存区 3. 通过数组创建缓存区 4. 通过字符串创建缓存区 5. 读写缓存区 6. 复制缓存区 文件操作 1. 异步直接读取 2. 同步直接读取 3. 流式读取 4. 写入文件 5. 流式写入文件 6. 读取文件信息 7. 删除文件 8. 管道 9. 链式流 经过前面三天的学习,Node.js的基础知识已逐渐掌握,今天继续学习缓存区和文件操作,并稍加整理加以分享,如有不足之处,还请指正. 缓存区 1. 什么是缓存区? JavaScript

  • Spring Boot Web 静态文件缓存处理的方法

    采用Spring Boot + Freemarker开发Web项目时,由于一些静态文件比较大,如果是在PC上访问影响不大,当在手机上访问时,特别是用流量访问时速度会慢很多,而且很耗流量. 通过对请求进行抓包,可以发现每次进入一个页面都需要加载静态文件,如果不差钱的公司可以将静态文件放在CDN上来加快访问速度,或者用Nginx来做静态文件的缓存. 今天给大家介绍一种其他的缓存优化方式,通过Spring的缓存机制来缓存静态文件,在Spring Boot中配置静态文件缓存只需要在配置文件中加入下面的配

  • Node.js折腾记一:读指定文件夹,输出该文件夹的文件树详解

    前言 用来干什么:想干嘛干嘛 为什么写:写来玩,学习node.js文件系统相关api:树结构这种东西还是挺不错的,会用会造才是真的会 用了什么: fs.readdir(dir), fs.stat(dir).isFile(), path处理路径等 思路: 读取当前文件夹(不是文件夹的另作处理),获得其下所有文件和目录组成的数组: 循环该数组,判断是文件夹还是文件,文件的话直接push到childFiles(对象有两个属性:short文件名,full完整文件路径) 文件夹的话,先把当前文件夹作为ke

  • Django实现静态文件缓存到云服务的操作方法

    一般与页面有关的系统都会有大量的静态文件,包括js.css以及图标图片等,这些文件一般是项目的相对路径,在加载的时候会从本地读取再转发出去.由于这类文件一般比较大,导致接口响应变长,但是这些文件一般很少改动,所以非常适合通过Nginx或者云服务来缓存.一般云服务与cdn无缝集成,能够更快下发到客户端.我们后台系统很多使用的是基于python的Django框架,该怎么来实现静态文件缓存呢? 这个过程简单的让人惊讶,但是开始一直搞不清楚关系,前前后后耽误了不少时间. 1.collectstatic命

  • 基于node.js之调试器详解

    1.在命令行窗口中,可以使用"node debug" 命令来启用调试器,代码如下: node debug<需要被执行的脚本文件名>接下来根据一个实例进行学习调试过程: 编写app.js文件进行调试: console.log('hello,word') function foo(){ console.log('hello,foo') return 100; } var bar = 'This is a pen'; var http = require('http') var

  • Asp.Net中MVC缓存详解

    本文通过介绍了Asp.Net中MVC缓存的种类,以及他们之间的区别等内容,让学习者能够深入的了解MVC缓存的原理机制,以下是具体内容: 缓存是一种保存资源副本并在下次请求时直接使用该副本的技术.当 web 缓存发现请求的资源已经被存储,它会拦截请求,返回该资源的拷贝. Web应用缓存技术大体上可以分为两类:服务端缓存和客户端缓存.两种目标都是减少重复性内容的生成和网络传输工作,因为缓存数据存储的位置不同,而分为服务端缓存和客户端缓存. 服务端缓存 服务端缓存技术关注于服务端数据查询,生成或者操作

  • node.js环境搭建图文详解

    身为一名Java开发者对前端充满无限的好奇,于是开始踏入前端的领地.要想先学习,搭建环境是必备,所以整理一篇node.js环境搭建教程. Node.js 是一个让 JavaScript 运行在服务端的开发平台 官网https://nodejs.org 下载 下载地址https://nodejs.org/en/download/ 本次下载LTS长期支持版,.zip解压版本(当然也可以使用安装版.msi),点击右侧[64-bit]即可下载. 解压 解压到自己所要存放的文件夹中,如图: 解压完成后会有

随机推荐