前端项目在版本迭代的时候,难免会遇到静态缓存的问题,明明开发的是ok的,但是一部署到服务器上,发现页面变得乱七八糟,这是由于静态缓存引起的。

从上面这张图片可以看出,浏览器加载css,js等资源时,size一栏是from cache,也就是直接使用了本地的资源,而没有向服务器请求。这样做的好处是提升页面渲染速度,坏处是当服务器的对应的文件发生变化时,浏览器却还是使用缓存,造成布局混乱的问题。

解决办法

一个比较原始的办法是在修改了文件之后,手动改变文件名称,然后再在html手动更新资源的path名称。打个比方,你有一天更新了a.css的样式,然后加个日期后缀,把它重命名为a-1221.css,同时在应用这个css的html中改成:

<link href="./css/a-1221.css" rel="stylesheet"/>

这时,但浏览器发现需要加载这个样式时,发现自己只有a.css,没有a-1221.css,就会向服务器发起请求了。不过,很明显,这种活大家是都不愿意干的,尤其是css文件一多的时候,绝对懵逼,所幸我们可以让gulp来帮我们完成这些乏味的工作。

gulp-rev 和 gulp-rev-collector

这是两个gulp的插件,gulp-rev可以根据静态资源的得出文件的hash值,当文件内容发生改变时,这个hash值也会发生变化。并生成一个json文件,大概长这个样子:

{
"base/index.css": "base/index-c52f09f203.css"
}

文件的后缀变成了这个文件的hash值。gulpfile.js中的代码如下:

var rev = require('gulp-rev');
var gulp = require('gulp');
gulp.task('revCss', function(){
return gulp.src(cssUrl)//你存放css的目录
.pipe(rev())
.pipe(rev.manifest())
.pipe(gulp.dest('rev/css'));//在rev/css目录下生成json文件
});

这个插件只解决了问题的一部分,也就是,把文件变动和hash值关联了起来,另一部分改变html的请求路径还要靠第二个插件gulp-rev-collector来完成。这个插件完成的事情也很简单,就是把html中的资源路径,通过正则匹配,替换成更新后的路径。代码如下:

var gulp = require('gulp');
var revCollector = require('gulp-rev-collector');
gulp.task('revHtml', function () {
return gulp.src(['rev/**/*.json', 'views/*.html'])
.pipe(revCollector())
.pipe(gulp.dest('views/inc/'));
});

所以这两个插件就解决问题了吗?可惜并不是这样。因为你的css文件名并没有更改,还是原来的a.css,所以还需要一个插件帮我们解决重命名的问题。比如用来重命名文件的gulp-rename。

var rename = require("gulp-rename");
var json = require('./rev-manifest.json');//rev生成的文件 gulp.task('rename',function(){
var json = require('./rev/css/rev-manifest.json');
var Path = require('path');
gulp.src("static/css/*.css")
.pipe(rename(function (path) {
path.basename = json[path.basename + '.css'].replace('.css', '');//改掉css文件名为含有hash值的文件名
}))
.pipe(gulp.dest("./dist"));
})

查询参数管理缓存

查询参数这种方法适用于前后端不分离的项目,因为这时再去重命名静态文件就会显得很麻烦。所以出现了这种做法,就是在静态资源发生变化时,文件名不改变,但是html中请求路径的查询参数会发生变化,像下面这样:

<link rel="stylesheet" href="/css/style.css?v=2h3h2ar">

这个查询参数v对于后台来说,没有什么意义,你完全可以改成a,b,c。但是当查询参数的hash值发生变化时,却会让浏览器去向服务器发起请求,从而更新缓存。如果你想用这种方式,可以使用gulp-rev-querygithub)插件和gulp-rev-collector-query,将文件名转换成查询字符串。(插件的一个bug是对于.min.css会解析错误)

{
"base/index.css": "base/index.css?v=1ead88a42c"
}

下面是我参考作者的写的一个,解决了min.js的问题,其实就是改了正则:


var through = require('through2'); module.exports = function(ver) {
var ver = ver || 'v'
// convert a-xxxxxxxx.css to a.css?ver=xxxxxxxx
function hashToQuery(file) {
var content = new String(file._contents);
content = content.replace(/(.+)\-(.{7,10})(\..+)"/g, function(match, p1,p2,p3,offset,string){
return `${p1}${p3}?${ver}=${p2}"`
});
file._contents = new Buffer(content);
file.ver = ver;
return file;
}
return through.obj(function(file, encoding, callback) {
callback(null, hashToQuery(file));
});
};

最后,祝大家圣诞快乐!

gulp管理静态资源缓存的更多相关文章

  1. gulp之静态资源防缓存处理

    最近,因为校友网项目开始有些规模了.开始就要考虑对静态资源进行工程自动化的管理.一讲到前端的自动化工具,大家或许都会想到Grunt,Gulp,或者百度的FIS.这三个都有各自的特点,大家可以依据自己的 ...

  2. nginx静态资源缓存与压缩

    一.静态资源缓存 参考文章 (1)apache设置max-age或expires 这里需要修改.htaccess文件. <IfModule mod_headers.c> <Files ...

  3. 清除nginx静态资源缓存

    之前写过一篇如何配置nginx缓存及手动清除缓存的文章: http://www.cnblogs.com/Eivll0m/p/4921829.html 但如果有大量缓存需要清理,手动一条条清理就比较慢了 ...

  4. SpringBoot cache-control 配置静态资源缓存 (以及其中的思考经历)

    昨天在部署项目时遇到一个问题,因为服务要部署到外网使用,中间经过了较多的网络传输限制,而且要加载arcgis等较大的文件,所以在部署后,发现页面loading需要很长时间,而且刷新也要重新从服务器下载 ...

  5. Jenkins管理静态资源

    这里我们的前端是使用webpack来管理静态资源的,把静态资源上传到svn上面来管理 这里我们把项目和静态资源剥离开来,然后静态资源接入CDN 我们的svn的结构是这样的 我们需要把这些目录都进行打包 ...

  6. Nginx 静态资源缓存配置

    示例 # Media: images, icons, video, audio, HTC location ~* \.(?:jpg|jpeg|gif|png|ico|cur|gz|svg|svgz|m ...

  7. Nginx的静态资源缓存以及压缩

    Nginx是一款轻量级的网页服务器.反向代理器以及电子邮件代理服务器.Nginx采用的是异步非阻塞的通信机制(epoll模型),支持更大的并发连接.所谓的epoll模型:当事件没有准备好时,就放入ep ...

  8. zmNgFrameWork 架构升级ng1.5和md5静态资源缓存方案【angular1.x】

    前言: 在我前面的博客,angular项目总结——angular + browserify + gulp + bower + less 架构分享  把我开发angular的架构进行了分享,并上传到了g ...

  9. Django项目引入NPM和gulp管理前端资源

    前言 之前写了一篇<Asp-Net-Core开发笔记:使用NPM和gulp管理前端静态文件>,现在又来用Django开发项目了,之前我搞了一个Django的快速开发脚手架「DjangoSt ...

随机推荐

  1. 实现基于Keepalived高可用集群网站架构的多种方法

    实现基于Keepalived高可用集群网站架构 随着业务的发展,网站的访问量越来越大,网站访问量已经从原来的1000QPS,变为3000QPS,目前业务已经通过集群LVS架构可做到随时拓展,后端节点已 ...

  2. 基于Cef内核的多店铺登录器(含源码)

    公司是做电商的,在速卖通平台上开了若干店铺,每天都需要登录店铺打理,如:发货提交.获取运单号等.多个店铺的情况下,同时使用浏览器就会非常繁琐,如:要记住帐户名和密码,还要在不同店铺间切换.如果能够制作 ...

  3. Duilib XML嵌套

    duilib使用嵌套xml可以简化代码的书写,有利于模块化的页面布局分解,duilib库的xml嵌套主要有两种方式 方式一.以创建控件的方式嵌套xml 在CreateControl(LPCTSTR p ...

  4. sysbench

    安装 http://www.cnblogs.com/zhoujinyi/archive/2013/04/19/3029134.html http://space.itpub.net/758322/vi ...

  5. 腾讯课堂web零基础

    utf是国际编码 gb2312 国人发明的 gbk 补充集 想看网站源代码可以按F12 <meta name ='keywords' content='设置关键字'> <meta n ...

  6. js的数组方法整理

    slice 从已有的数组中返回选定的元素.该方法不会修改数组,而是返回一个子数组. 语法:arr.slice(start,end) start: 必须,规定从何处开始选取.如果是负数,就是从尾部开始算 ...

  7. HTML5技术分享 ES2017继发与并发

    大家都知道,async函数的返回值是 Promise 对象,这比 Generator 函数的返回值是 Iterator 对象方便多了.你可以用then方法指定下一步的操作. 进一步说,async函数完 ...

  8. javaweb-2-Tomcat初步学习与使用

    一.Tomcat服务器简介(此点网上官方有详尽的解释,故此不赘述,以学习使用为主) Apache Jakarta的开源项目 JSP/Servlet容器 二.Tomcat的目录结构 三.启动和停止Tom ...

  9. LSF-SCNN:一种基于 CNN 的短文本表达模型及相似度计算的全新优化模型

    欢迎大家前往腾讯云社区,获取更多腾讯海量技术实践干货哦~ 本篇文章是我在读期间,对自然语言处理中的文本相似度问题研究取得的一点小成果.如果你对自然语言处理 (natural language proc ...

  10. 机器学习算法 - 最近邻规则分类KNN

    上节介绍了机器学习的决策树算法,它属于分类算法,本节我们介绍机器学习的另外一种分类算法:最近邻规则分类KNN,书名为k-近邻算法. 它的工作原理是:将预测的目标数据分别跟样本进行比较,得到一组距离的数 ...