请使用firefox,chrome等最新浏览器浏览本站。

前端开发规范-gulp实现前端自动化

css3 阿豹 519次浏览 0个评论 扫描二维码

我们使用gulp实现的功能有:
html压缩
css压缩合并
js压缩合并
sass/less编译css
图片压缩(包括PNG、JPEG、GIF和SVG图片)
静态资源添加版本号
上传ftp/sftp
建立web服务器

文件结构如下图:

package.json配置:

{
  "name": "projectName",
  "version": "1.0.0",
  "description": "",
  "main": "gulpfile.js",
  "author": "maicon",
  "license": "ISC",
  "devDependencies": {
    "gulp": "^3.9.1",
    "gulp-clean": "^0.3.2",
    "gulp-clean-css": "^2.0.7",
    "gulp-concat": "^2.6.0",
    "gulp-connect": "^4.1.0",
    "gulp-ftp": "^1.1.0",
    "gulp-htmlmin": "^2.0.0",
    "gulp-imagemin": "^3.0.2",
    "gulp-less": "^3.1.0",
    "gulp-rename": "^1.2.2",
    "gulp-rev": "^7.0.0",
    "gulp-rev-collector": "^1.0.3",
    "gulp-sass": "^2.3.2",
    "gulp-sequence": "^0.4.5",
    "gulp-sftp": "^0.1.5",
    "gulp-uglify": "^1.5.3",
    "imagemin-pngquant": "^5.0.0"
  }
}

gulpfile.js配置:

//定义输出文件夹名称
var distFolderH5 = "distH5";
var distFolderMofang = "distMofang";

//定义根目录路径
var baseUrl = "../";
//定义html目录路径
var tplUrl = "../tpl/";
//定义js目录路径
var jsUrl = "../js/";
//定义css目录路径
var cssUrl = "../css/";
//定义sass目录路径
var sassUrl = "../sass/";
//定义less目录路径
var lessUrl = "../less/";
//定义font目录路径
var fontUrl = "../fonts/";
//定义img目录路径
var imgUrl = "../img/";
//定义媒体目录路径
var mediaUrl = "../media/";
//定义第三方库目录路径
var libUrl = "../lib/";
//定义版本号文件输出根目录
var revDist = "../rev/";
//定义html版本号输出目录路径
var revTplUrl = "../rev/tpl/";
//定义js版本号输出目录路径
var revJsUrl = "../rev/js/";
//定义css版本号输出目录路径
var revCssUrl = "../rev/css/";
//定义font版本号输出目录路径
var revFontUrl = "../rev/fonts/";
//定义img版本号输出目录路径
var revImgUrl = "../rev/img/";
//定义媒体文件版本号输出目录路径
var revMediaUrl = "../rev/media/";
//定义第三方库版本号输出目录路径
var revLibUrl = "../rev/lib/";

setDistFolder(distFolderH5);

function setDistFolder(distFolder){
    //定义输出目录名称
    distName = distFolder;
    //定义输出根目录
    dist = "../"+distFolder+"/";
    //定义html输出目录路径
    distTplUrl = "../"+distFolder+"/tpl/";
    //定义js输出目录路径
    distJsUrl = "../"+distFolder+"/js/";
    //定义css输出目录路径
    distCssUrl = "../"+distFolder+"/css/";
    //定义font输出目录路径
    distFontUrl = "../"+distFolder+"/fonts/";
    //定义img输出目录路径
    distImgUrl = "../"+distFolder+"/img/";
    //定义媒体输出目录路径
    distMediaUrl = "../"+distFolder+"/media/";
    //定义第三方库输出目录路径
    distLibUrl = "../"+distFolder+"/lib/";
}

var gulp = require('gulp'),
    //压缩html,可以压缩页面javascript、css,去除页面空格、注释,删除多余属性等操作
    html = require('gulp-htmlmin'),
    //sass编译
    sass = require('gulp-sass'),
    //less编译
    less = require('gulp-less'),
    //css压缩
    minifycss = require('gulp-clean-css'),
    //js压缩
    uglify = require('gulp-uglify'),
    //文件合并
    concat = require('gulp-concat'),
    //文件重命名
    rename = require('gulp-rename'),
    //清空文件夹
    clean = require('gulp-clean'),
    //压缩图片文件(包括PNG、JPEG、GIF和SVG图片)
    imagemin = require('gulp-imagemin'),
    pngquant = require('imagemin-pngquant'),
    //对文件名加MD5后缀
    rev = require('gulp-rev'),
    //路径替换
    revCollector = require('gulp-rev-collector'),
    //上传ftp服务器
    //ftp = require('gulp-ftp'),
    //上传sftp服务器
    //sftp = require('gulp-sftp'),
    //控制task顺序
    gulpSequence = require('gulp-sequence');
    //创建服务器
    //connect = require('gulp-connect');

//gulp-html参数配置
var htmlOptions = {
    //清除HTML注释
    removeComments: true,
    //压缩HTML
    collapseWhitespace: true,
    //省略布尔属性的值 <input checked="true"/> ==> <input />
    collapseBooleanAttributes: true,
    //删除所有空格作属性值 <input id="" /> ==> <input />
    removeEmptyAttributes: true,
    //删除<script>的type="text/javascript"
    removeScriptTypeAttributes: true,
    //删除<style>和<link>的type="text/css"
    removeStyleLinkTypeAttributes: true,
    //压缩页面JS
    //minifyJS: true,
    //压缩页面CSS
    minifyCSS: true
};

//tpl模板压缩
gulp.task('tpl',function(){
   gulp.src(baseUrl+'index.html')
    .pipe(html(htmlOptions))
    //文件名加MD5后缀
    .pipe(rev())
    //输出路径
    .pipe(gulp.dest(dist))
    //生成一个rev-manifest.json
    .pipe(rev.manifest())
    //定义rev-manifest.json输出路径
    .pipe(gulp.dest(revDist))

   gulp.src(tplUrl+'**/*.html')
    .pipe(html(htmlOptions))
    //文件名加MD5后缀
    .pipe(rev())
    //输出路径
    .pipe(gulp.dest(distTplUrl))
    //生成一个rev-manifest.json
    .pipe(rev.manifest())
    //定义rev-manifest.json输出路径
    .pipe(gulp.dest(revTplUrl))
});

//css压缩添加版本号
gulp.task('cssMin', function() {
    return gulp.src(cssUrl+'*.css')
        //压缩css
        .pipe(minifycss())
        //文件名加MD5后缀
        .pipe(rev())
        //输出路径
        .pipe(gulp.dest(distCssUrl))
        //生成一个rev-manifest.json
        .pipe(rev.manifest())
        //定义rev-manifest.json输出路径
        .pipe(gulp.dest(revCssUrl));
});

//css合并添加版本号
gulp.task('cssCon', function() {
    //需要处理的css文件,放到一个字符串数组里
    return gulp.src(cssUrl+'*.css')
        //合并后的文件名
        .pipe(concat('build.min.css'))
        //压缩处理成一行
        .pipe(minifycss())
        //文件名加MD5后缀
        .pipe(rev())
        //输出路径
        .pipe(gulp.dest(distCssUrl))
        //生成一个rev-manifest.json
        .pipe(rev.manifest())
        //定义rev-manifest.json输出路径
        .pipe(gulp.dest(revCssUrl+'combine/'));
});

//复制不需要压缩的js文件并添加版本号
gulp.task('jsNotMin', function () {
    return gulp.src([jsUrl+'config.js'])
        //文件名加MD5后缀
        .pipe(rev())
        //输出路径
        .pipe(gulp.dest(distJsUrl))
        //生成一个rev-manifest.json
        .pipe(rev.manifest())
        //定义rev-manifest.json输出路径
        .pipe(gulp.dest(revJsUrl+'notmin/'));
});

//js压缩添加版本号
//"!"+jsUrl+'config.js'指定不需要压缩的js文件
gulp.task('jsMin', function () {
    return gulp.src([jsUrl+'*.js', "!"+jsUrl+'config.js'])
        //js压缩
        .pipe(uglify())
        //文件名加MD5后缀
        .pipe(rev())
        //输出路径
        .pipe(gulp.dest(distJsUrl))
        //生成一个rev-manifest.json
        .pipe(rev.manifest())
        //定义rev-manifest.json输出路径
        .pipe(gulp.dest(revJsUrl+'min/'));
});

//js合并添加版本号
//"!"+jsUrl+'config.js'指定不需要合并的js文件
gulp.task('jsCon', function () {
    return gulp.src([jsUrl+'*.js', "!"+jsUrl+'config.js'])
        //js压缩
        .pipe(uglify())
        //js合并
        .pipe(concat('build.min.js'))
        //文件名加MD5后缀
        .pipe(rev())
        //输出路径
        .pipe(gulp.dest(distJsUrl))
        //生成一个rev-manifest.json
        .pipe(rev.manifest())
        //定义rev-manifest.json输出路径
        .pipe(gulp.dest(revJsUrl+'combine/'));
});

//图片压缩添加版本号
gulp.task('img',function() {
    return gulp.src(imgUrl+'**/*')
        //图片压缩
        .pipe(imagemin({progressive: true, svgoPlugins:[{removeViewBox:false}], use:[pngquant({quality: '70'})]}))
        //文件名加MD5后缀
        .pipe(rev())
        //输出路径
        .pipe(gulp.dest(distImgUrl))
        //生成一个rev-manifest.json
        .pipe(rev.manifest())
        //定义rev-manifest.json输出路径
        .pipe(gulp.dest(revImgUrl))
});

//sass编译
gulp.task('sass', function () {
    return gulp.src(sassUrl+'*.scss')
        .pipe(sass({outputStyle: 'compressed'}))
        .pipe(gulp.dest(cssUrl))
});

//less编译
gulp.task('less', function () {
    return gulp.src(lessUrl+'*.less')
        .pipe(less())
        .pipe(gulp.dest(cssUrl));
});

//添加版本号
//index.html内部链接添加版本号
gulp.task('revIndex', function () {
    return gulp.src([revDist+'**/*.json', dist+'index.html'])
        .pipe(revCollector({ replaceReved:true }))
        .pipe(gulp.dest(dist))
});
//tpl下的html内部链接添加版本号
gulp.task('revTpl', function () {
    return gulp.src([revDist+'**/*.json', distTplUrl+'**/*.html'])
        .pipe(revCollector({ replaceReved:true }))
        .pipe(gulp.dest(distTplUrl))
});
//css内部链接添加版本号
gulp.task('revCss', function () {
    return gulp.src([revDist+'**/*.json', distCssUrl+'**/*.css'])
        .pipe(revCollector({ replaceReved:true }))
        .pipe(gulp.dest(distCssUrl))
});
//js内部链接添加版本号
gulp.task('revJs', function () {
    return gulp.src([revDist+'**/*.json', distJsUrl+'**/*.js'])
        .pipe(revCollector({ replaceReved:true }))
        .pipe(gulp.dest(distJsUrl))
});

//复制媒体文件和lib文件和字体文件并添加版本号
gulp.task('copyFile', function () {
    gulp.src([mediaUrl+'**/*'])
        .pipe(rev())
        .pipe(gulp.dest(distMediaUrl))
        .pipe(rev.manifest())
        .pipe(gulp.dest(revMediaUrl));

    gulp.src([fontUrl+'**/*'])
        .pipe(rev())
        .pipe(gulp.dest(distFontUrl))
        .pipe(rev.manifest())
        .pipe(gulp.dest(revFontUrl));

    gulp.src([libUrl+'**/*'])
        .pipe(rev())
        .pipe(gulp.dest(distLibUrl))
        .pipe(rev.manifest())
        .pipe(gulp.dest(revLibUrl));
});

//清空输出目录及rev版本号目录并删除
gulp.task('clean', function() {
    return gulp.src([baseUrl+distName, baseUrl+'/rev'], {read: false})
        .pipe(clean({force: true}));
});

//var ftpConfig = {
//    "localPath": {
//        "base": "../dist/"
//    },
//    "remotePath": {
//        "base": "dreamGame",
//        "project": "/var/disk/web/dev_local/app_web0/m.huanhuba.com/h5dev/dreamGame"
//    },
//    "project":{
//        "ftpTest": {
//            "use": true,
//            "host": "120.55.102.1",
//            "port":"220",
//            "user": "web",
//            "pass": "web123!@#"
//        }
//    }
//}
////上传ftp服务器
//gulp.task('ftp', function () {
//    return gulp.src(ftpConfig)
//            .pipe(sftp({
//                host: '120.55.102.1',
//                port: 220,
//                user: 'web',
//                pass: 'web123!@#'
//            }));
//})

//使用connect启动一个Web服务器
gulp.task('connect', function () {
  connect.server({
    //服务器根目录
    root: baseUrl,
    //访问IP
    ip: '127.0.0.1',
    //访问端口
    port: '8080',
    //是否启用热加载
    livereload: true
  });
});

//定义打包任务
//[]中的是异步,
gulp.task("buildH5", function(cb){
    setDistFolder(distFolderH5);
    gulpSequence(['clean'], ['tpl'], ['copyFile', 'cssMin', 'cssCon', 'jsNotMin', 'jsMin', 'jsCon', 'img'], ['revIndex', 'revTpl', 'revCss', 'revJs'])(cb)
});

gulp.task("buildMofang", function(cb){
    setDistFolder(distFolderMofang);
    gulpSequence(['clean'], ['tpl'], ['copyFile', 'cssMin', 'cssCon', 'jsNotMin', 'jsMin', 'jsCon', 'img'], ['revIndex', 'revTpl', 'revCss', 'revJs'])(cb)
});

//定义监听任务
gulp.task('watch',function(){
    //gulp.watch(tplUrl+'*.html', ['html']);
    gulp.watch(sassUrl+'**/*.scss', ['sass']);
    //gulp.watch(cssUrl+'**/*.css', ['cssMin', 'cssCon']);
    //gulp.watch(jsUrl+'**/*.js', ['jsMin', 'jsCon']);
});

图片使用及压缩说明:

对于图片压缩,先使用https://tinypng.com/压缩。然后在打包时,再使用gulp-imagemin压缩。
图片无透明图要求, 尽量使用jpg图片,压缩质量为70%,如果精度不够,可以提高到80%。

版本号文件配置:

使用gulp-rev, gulp-rev-collector给静态资源添加版本号:默认格式是将main.js, 修改为main-b8dba3f55b.min.js, 然后页面中的引入也被修改成了main-b8dba3f55b.js。通常情况下我们不希望修改文件名称, 而是直接在引入的地方将main.js修改为main.js?v=b8dba3f55b。
这时候需要修改gulp-rev, gulp-rev-collector模块代码。修改如下:

1. 打开 node_modules\gulp-rev\index.js
第144行 manifest[originalFile] = revisionedFile;
更新为: manifest[originalFile] = originalFile + '?v=' + file.revHash;

2.打开 nodemodules\gulp-rev\nodemodules\rev-path\index.js
10行 return filename + '-' + hash + ext;
更新为: return filename + ext;

3.打开 node_modules\gulp-rev-collector\index.js
31行if ( !_.isString(json[key]) || path.basename(json[key]).replace(new RegExp( opts.revSuffix ), '' ) !==  path.basename(key) ) {
更新为: if ( path.basename(json[key]).split('?')[0] !== path.basename(key) ) {

使用方式:

1.安装node, 注意node版本不能过低,否则安装依赖模块时会报错。目前建议使用5.9.0版本。
2.安装依赖模块, 在_build目录下打开终端,执行cnpm install ,如果没有安装cnpm,就是用npm install安装。
3.执行gulp watch,监听sass编译
4.开发过程中引入未压缩合并的css, js文件。便于代码调试。
5.上线时,引入压缩合并的css, js文件。执行gulp buildH5。
6.打包完成,将distH5上传。

安装可能遇到的问题:

使用npm安装经常遇到安装失败的情况,因为npm安装插件是从国外服务器下载,受网络影响大,可能出现异常。我们可以用cnpm代替安装。cnpm是一个淘宝开发的完整 npmjs.org 镜像,服务器在国内,同步频率目前为 10分钟一次以保证尽量与官方服务同步。
安装方式:

npm install cnpm -g --registry=https://registry.npm.taobao.org

注:cnpm跟npm用法完全一致,只是在执行命令时将npm改为cnpm。


喜欢 (22)or分享 (0)
发表我的评论
取消评论
表情 贴图 加粗 删除线 居中 斜体 签到