gulp静态资源缓存问题(css、js、img)

我不得不先吐槽一下csdn,这篇博客是我前几天就写的,当时是写完的,但今天发现发布出去的内容只有前面几行文字,其余内容都删掉了,小编也是很无奈呀,无奈之举我只能重写一遍,不知其他小编是否也遇到同样的事情,怀疑以后每次发布之前是不是都要提前复制一份出来了。。。
---------------------------------------------------------------------------------------------

其实小编刚开始是没有在意静态资源(css、js、img)的缓存问题的,开发中虽然也会遇到缓存但只要手动清除一下完全可以解决,所以一直没有搭理。但前几天buuuuuug告诉我清缓存的必要性,特别是微信内置浏览器。一般浏览器还好,缓存没有那么厉害,页面一上线访问一般是没有问题的,但倘若你做的页面是要在微信中打开,我还是劝诫你做一下清缓存,否则html上去了,css还是上一个版本的内容,我想页面出来也该不忍直视吧。言归正传look下面:

一、安装插件

npm install gulp-rename gulp-clean  gulp-rev  gulp-rev-collector   --save-dev (其中gulp-rename起到重新命名的作用不是必须的);

我分别说一下每个插件的作用:

1)、gulp-clean:故名思议它的作用是清除文件,利用它我们可以清除前一次的css、js、img等静态资源,防止冗余。{read:false}: 是不读取文件加快程序;.pipe(clean({force: true})): 是强制删除文件。

代码如下:

gulp.task('dayplay_clean', function () {
  return gulp.src(['../static/css/dayplay', '../static/js/dayplay'], {read: false}).pipe(clean({force: true}))
})

2)、gulp-rename:作用是重命名,不是必须,可自行选择;

3)、gulp-rev:这是一个很重要的插件,我们都知道之所以有缓存是因为新生成的css、js没有被替换上去。我们通常会给css、js文件加序列号,通过更新序列号的方式让浏览器察觉静态资源有所改变。gulp-rev便起到了这个作用,执行gulp-rev时它会检测css、js是否发生变化,倘若有检测到变化它会给文件生成一个新的序列号,即对文件进行DM5处理(如图一、图二), 同时会生成一个rev-manifest.json文件记录css、js 文件的对应关系(如图三、图四),方便后续的后替换。

  

      

代码如下:

gulp.task('dayplay_css', function () {
  gulp.src(['dayplay/less/*.less', '!dayplay/less/base.less'])
    .pipe(less())
    .pipe(cssmin())
    .pipe(rename(function (path) {
      path.basename += '.min'
      path.extname = '.css'
    }))
    .pipe(rev()) // 文件名加MD5后缀
    .pipe(gulp.dest('../static/css/dayplay')) // 输出文件本地
    .pipe(rev.manifest()) // 生成一个rev-manifest.json文件,记录MD5的文件改名前后的对应关系
    .pipe(gulp.dest('../static/rev/dayplay/css')) // 将 rev-manifest.json 保存到 rev
})

4)、gulp-rev-collector :有同学会想生成了带有序列号的css、js、img,还有记录对应关系的rev-manifest.json文件,但真的要手动替换html内的引入吗?一个一个替换?那不得累死??这时gulp-rev-collector的作用就彰显出来了。它的作用便是自动的替换html内的作用引入。是不是感觉很开心

代码如下(主要是对html的处理):

gulp.task('dayplay_rev', ['dayplay_css', 'dayplay_js'], function () {
  var htmlData = {
    removeComments: true, // 清除HTML注释
    collapseWhitespace: true, // 压缩HTML
    removeEmptyAttributes: true, // 删除所有空格作属性值 <input id="" /> ==> <input />
    removeScriptTypeAttributes: true, // 删除<script>的type="text/javascript"
    removeStyleLinkTypeAttributes: true, // 删除<style>和<link>的type="text/css"
    ignoreCustomFragments: [/<%[\s\S]*?%>/, /<\?[\s\S]*?\?>/, /<\/body>/, /<\/html>/], // 正则表达式数组,匹配的标签将不被处理。 (如 <?php ... ?>, {{ ... }}。
    includeAutoGeneratedTags: false, // 插入 HTML 解析器自动生成的标签。
    minifyJS: true, // 压缩页面JS
    minifyCSS: true // 压缩页面CSS
  }
  return gulp.src(['../static/rev/dayplay/**/*.json', 'dayplay/html/*.html'])
    .pipe(revCollector({
      replaceReved: true // 必须增加这个参数,否则更改了源文件之后不会热更新,设置replaceReved标识, 用来说明模板中已经被替换的文件是否还能再被替换,默认是false
    }))
    .pipe(htmlmin(htmlData))
    .pipe(gulp.dest('../views/dayplay'))
})
备注1:rev-collector的操作必须在rev之后,必须确保生成了rev-manifest.json。我试图用gulp的task控制但是失败了,它并不能确保是在上一个任务执行完后再执行第二个任务。我的处理方式是写了一个.sh文件(如果你是window系统,你可以写一个.bat文件)

备注2:img也会存在缓存问题,它也可以用上面的操作做相应的处理,但是css引入的背景图rev-collector是无法添加序列号的。我现在还没有想到处理方式,倘若你知道怎么解决请告知。

二、完整代码(注释很清楚了)

gulp.task('dayplay', ['dayplay_watch'])
gulp.task('dayplay_init', ['dayplay_clean', 'dayplay_img', 'dayplay_js', 'dayplay_css', 'dayplay_rev'])
gulp.task('dayplay_clean', function () {
  return gulp.src(['../static/css/dayplay', '../static/js/dayplay'], {read: false}).pipe(clean({force: true}))
})
gulp.task('dayplay_css', function () {
  gulp.src(['dayplay/less/*.less', '!dayplay/less/base.less'])
    .pipe(less())
    .pipe(cssmin())
    .pipe(rename(function (path) {
      path.basename += '.min'
      path.extname = '.css'
    }))
    .pipe(rev()) // 文件名加MD5后缀
    .pipe(gulp.dest('../static/css/dayplay')) // 输出文件本地
    .pipe(rev.manifest()) // 生成一个rev-manifest.json文件,记录MD5的文件改名前后的对应关系
    .pipe(gulp.dest('../static/rev/dayplay/css')) // 将 rev-manifest.json 保存到 rev
})
gulp.task('dayplay_rev', ['dayplay_css', 'dayplay_js'], function () {
  var htmlData = {
    removeComments: true, // 清除HTML注释
    collapseWhitespace: true, // 压缩HTML
    removeEmptyAttributes: true, // 删除所有空格作属性值 <input id="" /> ==> <input />
    removeScriptTypeAttributes: true, // 删除<script>的type="text/javascript"
    removeStyleLinkTypeAttributes: true, // 删除<style>和<link>的type="text/css"
    ignoreCustomFragments: [/<%[\s\S]*?%>/, /<\?[\s\S]*?\?>/, /<\/body>/, /<\/html>/], // 正则表达式数组,匹配的标签将不被处理。 (如 <?php ... ?>, {{ ... }}。
    includeAutoGeneratedTags: false, // 插入 HTML 解析器自动生成的标签。
    minifyJS: true, // 压缩页面JS
    minifyCSS: true // 压缩页面CSS
  }
  return gulp.src(['../static/rev/dayplay/**/*.json', 'dayplay/html/*.html'])
    .pipe(revCollector({
      replaceReved: true // 必须增加这个参数,否则更改了源文件之后不会热更新,设置replaceReved标识, 用来说明模板中已经被替换的文件是否还能再被替换,默认是false
    }))
    .pipe(htmlmin(htmlData))
    .pipe(gulp.dest('../views/dayplay'))
})
gulp.task('dayplay_js', function () {
  var jsData = {
    mangle: {
    except: ['require' , 'exports' , 'module' ]} // 排除混淆关键字
  }
  gulp.src(['dayplay/js/*.js'])
    .pipe(jsmin(jsData))
    .pipe(rev())
    .pipe(gulp.dest('../static/js/dayplay'))
    .pipe(rev.manifest())
    .pipe(gulp.dest('../static/rev/dayplay/js'))
})
gulp.task('dayplay_img', function () {
  gulp.src('dayplay/img/**/*.{png,jpg,gif,svg,ico}') // 指明源文件路径、并进行文件匹配
    .pipe(changed('../static/images/dayplay')) // 对比文件是否有过改动(此处填写的路径和输出路径保持一致)
    .pipe(gulp.dest('../static/images/dayplay')); // 输出路径
  gulp.src('dayplay/img/*.{png,jpg,gif,svg,ico}').pipe(gulp.dest('../static/images/dayplay'))
})

有些小编说加载的序列号会有一次延迟,css、js序列号总是错后一次,我没有遇到,但是我发现有时文件执行后样式等没有上去,此时不要着急,只要再执行一次就好了。

备注:有些小编可能喜欢 href="../css/default.css?v=5a636d79c4"这种hash形式
可以参考 https://segmentfault.com/a/1190000012217659 这个文档。但小编不提倡这么做。因为它需要修改插件内容感觉不利于团队交接。



好了,文章就写到这里了,如果哪里有问题帮忙指出来,互相进步哈!

猜你喜欢

转载自blog.csdn.net/weixin_37242696/article/details/80095763