编程/21 分钟阅读

打造自己的 gulp 前端自动化任务

本博客注:现在已不再使用,地址在这里是使用 Nodejs 的 es6/7 特性开发的,线上部署的是编译过后的文件,所以本地开发的时候我将开发环境的文件和生产环境的文件分为两个文件夹。而前端使用 gulp 构建,前期只是简单的压缩了一下文件,随着静态资源迁移到七牛之后,越来越觉得不方便。因为服务端开启了强缓存,每次更新完之后都要强制刷新才能更新客户端的缓存记录。而之前一直是手动修改静态资源版本号的,但是太不方便,为了提升逼格,还是好好的写一个属于自己的 gulp 任务吧!

资源压缩

这里我主要使用了 gulp-minify-css,gulp-uglify,gulp-minify-ejs 来压缩 css,js,和esj 模版。 版本控制

一般来说现在有两种方式来做静态资源版本控制,第一种处理静态资源时给静态资源文件按照文件 md5 修改一个唯一的名字,并修改 html 文件中的引用,如下:

{
    "css/a.css": "css/a-d41d8cd98f.css",
    "css/b.css": "css/b-d41d8cd98f.css",
    ...
    "js/a.js": "js/a-273c2cin3f.js""js/b.js": "js/b-273c2cin3f.js"
}

这样服务端更新完之后客户端也会强制更新,现在大多数都是使用的这种方式。使用 gulp-rev 配合 gulp-rev-collector 即可达到这种效果,比较正式的项目推荐使用。

由于这种部署方式会产生冗余文件,所以我的博客就没有才用这种方式,而是才用追加版本号的方式来通知客户端刷新,如下:

{
    "css/a.css": "css/a.css?v=d41d8cd98f",
    "css/b.css": "css/b.css?v=d41d8cd98f",
    ...
    "js/a.js": "js/a.js?v=273c2cin3f""js/b.js": "js/b.js?v=273c2cin3f"
}

这种方式也可以达到刷新缓存的作用,但是据说问题多多,正式项目不推荐使用。

因为静态资源放在七牛,所以我去 github 搜到了一个插件 gulp-cdn-replace 挺适合,并对插件做了一些修改,达到自己想要的效果:替换七牛链接并追加时间戳作为版本号。

把 gulp-cdn-replace/index.js 中 getNewUrl 修改为

function getNewUrl(url,type){
        var basename=path.basename(url);
        //添加suffix
        if(option.suffix&&basename.indexOf(option.suffix)==-1){
            var arr=basename.split('.');
            basename=arr[0]+option.suffix+'.'+arr[1];
        }        
        var newurl=option.root+'/'+basename;
        //添加时间戳
        if(basename.indexOf('?')==-1){
            newurl+='?v='+new Date().getTime();
        }
        return newurl;
    }

执行任务即可将 html 文件中中对静态资源的引用替换为 cdn 地址,并追加时间戳为版本号。 资源同步

如果每次更新都要手动上传到七牛岂不是太累,所以又去 github 搜了一下,发现一个 gulp-qndn 基本上可以满足要求,但是使用的时候发现一个问题,就是这个插件只做了上传,但是七牛是不会自动覆盖同名文件的,于是小小的改动一下,在上传之前先删除同名文件,并增加一个配置项来控制这个功能。

把 gulp-qn-dn/index.js 中 client.upload 之前增加删除操作

if(options.qn.delete){
      client.delete(fileKey, function(err, result) {
        if (err) {
          log('Error', colors.red(new PluginError(PLUGIN_NAME, err).message));
        } else {
          log('Delete:', colors.green(options.qn.domain+'/'+fileKey));
        }
      });
    }

这样每次执行 gulp 任务就可以同步到七牛。 实例

完整依赖

"devDependencies": {
    "gulp": "^3.9.1",
    "gulp-cdn-replace": "^0.2.0",
    "gulp-minify-css": "^1.2.4",
    "gulp-minify-ejs": "^1.0.3",
    "gulp-qndn": "0.0.4",
    "gulp-rename": "^1.2.2",
    "gulp-uglify": "^1.5.3"
  }

任务

var gulp = require('gulp'),                 //基础库
    minifycss = require('gulp-minify-css'), //css压缩
    uglify = require('gulp-uglify'),        //js压缩     
    rename = require('gulp-rename'),        //文件重命名
    minifyejs = require('gulp-minify-ejs'), //压缩html[esj模版]
    upload = require('gulp-qndn').upload,   //七牛上传
    cdn = require('gulp-cdn-replace');      //替换CDN链接

var qnOptions = {
  accessKey: 'xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx',
  secretKey: 'xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx',
  bucket: 'hersface',
  domain: 'http://xxxxxxxxxx.glb.clouddn.com',
  delete:false   //是否清除同名文件
};
gulp.task('script', function() {
    console.log('压缩并上传js...');
    return gulp.src('www/static/js/easyou.js') 
        .pipe(rename({ suffix: '.min' }))
        .pipe(uglify())
        .pipe(upload({qn: qnOptions}))
        .pipe(gulp.dest('www/static/js'));        
});
gulp.task('css', function() {
    console.log('压缩并上传css...');
    return gulp.src(['www/static/css/easyou.css','www/static/css/admin.css'])
        .pipe(rename({ suffix: '.min' }))
        .pipe(minifycss())
        .pipe(upload({qn: qnOptions}))
        .pipe(gulp.dest('www/static/css'));
});
gulp.task('html', function() {
    console.log('压缩html...');
    console.log('更新版本号...');
    return gulp.src('view/development/*/*.html')
        .pipe(cdn({suffix: '.min',root: 'http://xxxxxxxxxxxx.glb.clouddn.com'}))    
        .pipe(minifyejs())
        .pipe(gulp.dest('view/production'))
});
gulp.task('default', ['script','css','html']); //定义默认任务

可能还有许多问题需要自己去发现,也希望大神看到错误之处及时指出,感激不尽!最后感谢 github 上开源的同学,好人出门捡钱!

发表评论

1 条评论

已加载全部评论