【SpringBoot】Gulp管理Thymeleaf前端资源

2019-05-26  本文已影响0人  瑞瑞余之

在Springboot web项目中,我们可以用Gulp对前端资源进行管理,比如revision、minify等等。今天用一个简单的demo来介绍管理思路和操作方法,demo中我们使用的模版引擎是Spring官方推荐的Thymeleaf。

开宗明义,什么是Gulp?

Gulp是一款基于流的前端构建化工具,首先我们先把它与脚手架工具区别开。个人认为,帮我们搭建项目结构,使项目从0-1的工具是脚手架。如果你使用过Spring initializr,就会有更深刻的体会。Gulp不是用来构建代码,而是构建任务,比如对前端文件的压缩、打包、revision等等。
我们通过脚手架工具Spring initializr,快速搭建Springboot web项目:

创建Web项目
demo项目会自动构建出Thymeleaf引擎所需要的目录结构:
Web项目结构
此时我们可以基于此进行开发,但是在开发的过程中,发现这样一个问题:每次html文件的改动,在前端要多次刷新才能看到更新,甚至完全没有变化。
解决方案1: 在application.properties中加入
spring.thymeleaf.cache=false

同时每次希望更改生效的时候cmd + F9,build project。
解决方案2: 开启热部署,具体方法可以参见另一篇文章:https://www.jianshu.com/p/1d6b5f70dc19
以上两种方案,能够解决html即时调试的问题,但是它们并不适用于项目中的静态资源:js css等。这是因为浏览器在第一次申请到前端资源后,为了不重复请求相同资源,会copy一份保存在浏览器,当第二次访问相同的资源url时,浏览器会根据缓存机制判断是否启用本地缓存。这里所提到的缓存规则,其实是在http请求header和html的meta标签中定义的。而它们分别是从“过期机制”和“验证机制”两个维度来供浏览器判断是否使用缓存:
过期机制:含有完整的过期时间信息头,且在有效期内
验证机制:根据meta判断cache是否开启
缓存机制不是讨论的重点,暂不深入研究。我们的目的是能够让浏览器每次都请求最新资源,最常用的办法就是不让每次资源url都一致,也就是说,我们给css、js文件加一个版本号,每次更改后都打一个新号,这样浏览器会视作一个新资源而再次向服务端申请。
解决方案:

  1. 引入常用模块:
const { series, parallel, src, dest, watch } = require('gulp')

series:串行执行任务
parallel:并行执行任务

  1. 引入revision模块:
terminal:
npm install gulp-revm, gulp-revm-collector --save-dev
gulpfile:
const rev = require('gulp-revm'),
    revCollector = require('gulp-revm-collector');
  1. 压缩js文件并revision
gulpfile:
function minifyJs() {
    return src(paths.jsSrc) // 要压缩的js文件
        .pipe(pi.uglify())  //使用uglify进行压缩,pi组件可以免除手动引入gulp组件,不做赘述,可上网查阅
        .pipe(pi.concat('application.min.js')) //将js文件合并,并命名
        .pipe(rev()) //revision application.min.js
        .pipe(dest(paths.jsTarget)) //目的地址,这里我直接指向项目的output path
        .pipe(rev.manifest()) //创建文件名与revision后的文件名的mapping文件,参见下图
        .pipe(dest('rev/js'));
}
manifest.json
  1. 替换原文件名
    经过上面的操作,我们已经将js文件压缩,重命名且revision。接下来我们根据revision的js文件,替换html中的多个js:
function revJs() {
    return src([paths.revPath, paths.htmlSrc]) //指定rev manifest文件夹路径,指定html文件路径
        .pipe(revCollector({
            replaceReved:true //确定替换
        }))
        .pipe(dest(paths.htmlSrc));
}
  1. 添加watch
    以上步骤,我们成功的revision了js文件,css文件同样操作,现在我们为js文件添加watch,这样一来,一旦js文件内容发生了改变,就会触发application.min.js重新打包,并且打上新的版本号:
function watchChange(){
    watch(paths.jsSrc, series(minifyJs, revJs)); //监听js src路径中的文件,一旦修改,串行执行minifyJs和revJs两个任务
}

这样我们对js和css乃至image文件都可以进行打包管理,这里顺带说一下html文件打包时常用操作:

function minifyHtml() {
    var options = {
        removeComments: true,  //清除HTML注释
        collapseWhitespace: true,  //压缩HTML
        collapseBooleanAttributes: true,  //省略布尔属性的值 <input checked="true"/> ==> <input checked />
        removeEmptyAttributes: true,  //删除所有空格作属性值 <input id="" /> ==> <input />
        removeScriptTypeAttributes: true,  //删除<script>的type="text/javascript"
        removeStyleLinkTypeAttributes: true,  //删除<style>和<link>的type="text/css"
        minifyJS: true,  //压缩页面JS
        minifyCSS: true  //压缩页面CSS
    };
    return src(paths.htmlSrc)
        .pipe(pi.htmlmin(options))
        .pipe(rev())
        .pipe(dest(paths.htmlTarget))
        .pipe(rev.manifest())
        .pipe(dest('rev/template'));
}

当一切配置完毕后,如果我们希望自定义组合任务,例如依次执行:minifyJs、revJs,则需要export:

exports.revJs = series(minifyJs, revJs);
在terminal中执行 gulp revJs

用同样的方式export default task

exports.default = series(
//第一步:同时分别对html和js进行压缩和版本化
    parallel(series(minifyHtml, revHtml), series(minifyJs, revJs)),
//第二步:打开监听
    watchChange
);
在terminal中执行gulp

通过对静态文件版本化,包括压缩、合并、重命名等一系列操作,可以使得前端调试更顺畅,同时,就浏览器端的用户体验和专业性来说也会更好。

上一篇下一篇

猜你喜欢

热点阅读