文章转载至[gulp排除已压缩文件思路]

gulp默认排除语法的弊端

有个时候我们需要时用gulp排除已经压缩过的js,css等。如果以压缩文件是以".min.js"之类命名规范的还好,如果不是呢?而且还有其他一些场景也会有需要。
gulp默认支持glob格式,排除语法为!
举几个例子:
排除目录

gulp.src([
baseDir + '/**', // Include all
'!' + baseDir + '/excl1{,/**}', // Exclude excl1 dir
'!' + baseDir + '/excl2/**/!(.gitignore)', // Exclude excl2 dir, except .gitignore
], { dot: true });

排除文件:

gulp.src(['css/**/!(ignore.css)*.css'])
gulp.src([
'!css/ignnore.css',
'css/*.css'
])

这确实能够排除一些文件。但是还不算强大,不能满足一些复杂的场景。而且还存在这样一个问题:当我有一个jquery.min.js,在压缩js时,我不想对它进行压缩,但同时我又想将其输出到dist目录下。单纯采用上面这种方式需要"曲线救国",场景如下:

gulp.task('jsmin', function (cb) {
return gulp.src([SRC_DIR+'/**/*.js',,'!'+SRC_DIR+'/**/*.min.js'])
.pipe(sourcemaps.init())
.pipe(uglify({mangle: {except: ['require' ,'exports' ,'module' ,'$']}})) //排除混淆关键字
.pipe(sourcemaps.write('.'))
.pipe(gulp.dest(DEST_DIR)); });

很遗憾地告诉你,*.min.js并没有被拷贝到DEST_DIR,当然曲线救国可以如下:

gulp.task('copy', () =>{
return gulp.src([SRC_DIR+'/**/*.min.js'])
.pipe(gulp.dest(DEST_DIR));
}
);

但是,这不是很优雅。而且上面我们也说了只是采用glob语法对文件进行排除不适用于复杂的场景。

Vinyl文件系统

详细说明,请参考探究Gulp的Stream
现在这里贴出,后面会说明其目的。
虽然Gulp使用的是Stream,但却不是普通的Node Stream,实际上,Gulp(以及Gulp插件)用的应该叫做Vinyl File Object Stream。
这里的Vinyl,是一种虚拟文件格式。Vinyl主要用两个属性来描述文件,它们分别是路径(path)及内容(contents)。具体来说,Vinyl并不神秘,它仍然是JavaScript Object。Vinyl官方给了这样的示例:

var File = require('vinyl');
var coffeeFile = new File({
cwd: "/",
base: "/test/",
path: "/test/file.coffee",
contents: new Buffer("test = 123")
});

从这段代码可以看出,Vinyl是Object,path和contents也正是这个Object的属性。

解决方案描述:

可以采用gulp插件来实现更为强大的排除。主要有以下几个插件:
gulp-ignore,支持通过boolean,stat对象,函数来判断是否排除与包含。判断函数接受一个Vinyl文件对象,返回一个boolean值。
gulp-filter,支持glob模式、函数过滤,以及过滤后恢复
gulp-if,支持条件判断(支持函数条件)来控制相关流程。
下面具体说明如何使用

gulp-ignore:

API
exclude(condition [, minimatchOptions])
Exclude files whose file.path matches, include everything else
include(condition [, minimatchOptions])
Include files whose file.path matches, exclude everything else
参数说明:
condition:类型可以为 boolean or stat object or function
当为函数是接受一个vinyl file返回boolean值

下面贴出官方例子:

var gulpIgnore = require('gulp-ignore');
var uglify = require('gulp-uglify');
var jshint = require('gulp-jshint'); var condition = './gulpfile.js'; gulp.task('task', function() {
gulp.src('./**/*.js')
.pipe(jshint())
.pipe(gulpIgnore.exclude(condition))
.pipe(uglify())
.pipe(gulp.dest('./dist/'));
}); var gulpIgnore = require('gulp-ignore');
var uglify = require('gulp-uglify');
var jshint = require('gulp-jshint'); var condition = './public/**.js'; gulp.task('task', function() {
gulp.src('./**/*.js')
.pipe(jshint())
.pipe(gulpIgnore.include(condition))
.pipe(uglify())
.pipe(gulp.dest('./dist/'));
});

实现:

var condition = function(f){
if(f.path.endswith('.min.js')){
return true;
}
return false
}; gulp.task('jsmin', function (cb) {
return gulp.src([SRC_DIR+'/**/*.js'])
.pipe(gulpIgnore.exclude(condition))
.pipe(sourcemaps.init())
.pipe(uglify({mangle: {except: ['require' ,'exports' ,'module' ,'$']}})) //排除混淆关键字
.pipe(sourcemaps.write('.'))
.pipe(gulp.dest(DEST_DIR)); });

优点:很明显,你可以在条件函数中做你想做的任何事情,包括使用正则表达式等。缺点:和默认情况一样,不支持被排除文件的拷贝

gulp-if

和gulp-ignore作者是同一个人
API:
gulpif(condition, stream [, elseStream, [, minimatchOptions]])
gulp-if will pipe data to stream whenever condition is truthy.
If condition is falsey and elseStream is passed, data will pipe to elseStream
这就类似于三目运算符,功能用伪代码表示就是if condition then stream(data) else elseStream(data)
After data is piped to stream or elseStream or neither, data is piped down-stream.

参数说明:
condition 与gulp-ignore一致。
Type: boolean or stat object or
function that takes in a vinyl file and returns a boolean or
RegularExpression that works on the file.path

streamStream for gulp-if to pipe data into when condition is truthy.

elseStreamOptional, Stream for gulp-if to pipe data into when condition is falsey.

minimatchOptionsOptional, if it's a glob condition, these options are passed to minimatch.

官方例子:

var gulpif = require('gulp-if');
var uglify = require('gulp-uglify'); var condition = true; // TODO: add business logic gulp.task('task', function() {
gulp.src('./src/*.js')
.pipe(gulpif(condition, uglify()))
.pipe(gulp.dest('./dist/'));
});

Only uglify the content if the condition is true, but send all the files to the dist folder仅压缩符合条件的文件,丹斯所有文件(包括不符合条件的)都会被发送到dist目录。

实现:

var condition = function(f){
if(f.path.endswith('.min.js')){
return false;
}
return true;
}; gulp.task('jsmin', function (cb) {
return gulp.src([SRC_DIR+'/**/*.js'])
.pipe(sourcemaps.init())
.pipe(gulpif(condition, uglify({mangle: {except: ['require' ,'exports' ,'module' ,'$']}}))) //排除混淆关键字
.pipe(sourcemaps.write('.'))
.pipe(gulp.dest(DEST_DIR)); });

gulp-filter

API
filter(pattern, [options])
Returns a transform stream with a .restore object.
参数说明:
pattern
Type: string, array, function
Accepts a string/array with globbing patterns which are run through multimatch.
如果是函数,则应该接受一个 vinyl file object作为第一个参数,return true/false whether to include the file:

filter(file => /unicorns/.test(file.path));

选项options
Type: object
Accepts minimatch options.
Note: Set dot: true if you need to match files prefixed with a dot (eg. .gitignore).

options.restore
Type: boolean
Default: false
Restore filtered files.

options.passthrough
Type: boolean
Default: true

When set to true filtered files are restored with a PassThrough
stream, otherwise, when set to false, filtered files are restored as a
Readable stream.

官方例子:

const gulp = require('gulp');
const uglify = require('gulp-uglify');
const filter = require('gulp-filter'); gulp.task('default', () => {
// create filter instance inside task function
const f = filter(['**', '!*src/vendor'], {restore: true}); return gulp.src('src/**/*.js')
// filter a subset of the files
.pipe(f)
// run them through a plugin
.pipe(uglify())
// bring back the previously filtered out files (optional)
.pipe(f.restore)
.pipe(gulp.dest('dist'));
});
gulp.task('defaultmulti', () => {
const jsFilter = filter('**/*.js', {restore: true});
const lessFilter = filter('**/*.less', {restore: true}); return gulp.src('assets/**')
.pipe(jsFilter)
.pipe(concat('bundle.js'))
.pipe(jsFilter.restore)
.pipe(lessFilter)
.pipe(less())
.pipe(lessFilter.restore)
.pipe(gulp.dest('out/'));
});

实战:

var condition = function(f){
if(f.path.endswith('.min.js')){
return false;
}
return true;
};
const jsFilter = filter(condition, {restore: true}); gulp.task('jsmin', function (cb) {
return gulp.src([SRC_DIR+'/**/*.js'])
.pipe(jsFilter)
.pipe(sourcemaps.init())
.pipe(uglify({mangle: {except: ['require' ,'exports' ,'module' ,'$']}})) //排除混淆关键字
.pipe(sourcemaps.write('.'))
.pipe(jsFilter.restore)
.pipe(gulp.dest(DEST_DIR)); });

部分文件被压缩,所有文件都会被发送到DEST_DIR

小结

如何选择?
gulp-if:可以完美解决问题,且足够优雅。
gulp-filter:可以完美解决问题,但是相比gulp-if略显麻烦。更复杂的场景下用gulp-filter比gulp-if方便。
gulp-ignore:更为强大的过滤,在仅仅只是过滤而不拷贝的情况下首推。

[转]gulp排除已压缩文件思路的更多相关文章

  1. 7z压缩文件时排除指定的文件

    分享一个7z压缩文件时排除指定文件类型的命令行,感觉很有用: 7z a -t7z d:\updateCRM.7z d:\updateCRM\*.* -r -x!*.log -x!*bak a:创建压缩 ...

  2. 文件 "c:\Program Files\Microsoft SQL Server\MSSQL10.SQLEXPRESS\MSSQL\DATA\ttt.mdf" 已压缩,但未驻留在只读数据库或文件组中。必须将此文件解压缩。 CREATE DATABASE 失败。无法创建列出的某些文件名。请查看相关错误。 (.Net SqlClient Data Provider)

    问题: 文件 "c:\Program Files\Microsoft SQL Server\MSSQL10.SQLEXPRESS\MSSQL\DATA\ttt.mdf" 已压缩,但 ...

  3. gulp插件实现压缩一个文件夹下不同目录下的js文件(支持es6)

    gulp-uglify:压缩js大小,只支持es5 安装: cnpm: cnpm i gulp-uglify -D yarn: yarn add gulp-uglify -D 使用: 代码实现1:压缩 ...

  4. 7z.exe 命令行压缩文件排除文件(exclude filenames) 手记

    命令行使用格式:Usage: 7z <command> [<switches>...] <archive_name> [<file_names>...] ...

  5. ios开发网络学习五:MiMEType ,多线程下载文件思路,文件的压缩和解压缩

    一:MiMEType:一般可以再百度上搜索到相应文件的MiMEType,或是利用c语言的api去获取文件的MiMEType : //对该文件发送一个异步请求,拿到文件的MIMEType - (void ...

  6. C#基础-压缩文件及故障排除

    C#压缩文件可以使用第三方dll库:ICSharpCode.SharpZipLib.dll: 以下代码能实现文件夹与多个文件的同时压缩.(例:把三个文件夹和五个文件一起压缩成一个zip) 直接上代码, ...

  7. winform程序压缩文件上传,服务器端asp.net mvc进行接收解压

    期间编程没什么难度,唯一可能忽略导致结果失败是asp.net  mvc配置 对于压缩文件大的话,需要配置mvc的最大接收量: <system.web> <httpRuntime ma ...

  8. bat批处理异备文件、压缩文件

    1.压缩本地文件,并把压缩后的文件复制到其他机器 net use Z: \\192.168.135.1\share_linux a123456! /user:chaoqun.guo set bath= ...

  9. Linux —— 压缩文件

    Linux——压缩文件 为什么需要压缩文件?    文件在传输过程中,可能由于文件过大,传输所需时间过多.减少文件大小有两个明显的好处,一是可以减    少存储空间,二是通过网络传输文件时,可以减少传 ...

随机推荐

  1. C#泛型集合之——队列与堆栈

    队列与堆栈基础 队列 1.操作: (1)创建及初始化: Queue<类型> 队列名 =new Queue<类型>()://空队列,无元素 Queue<类型> 队列名 ...

  2. Java调用Http/Https接口(2)--HttpURLConnection/HttpsURLConnection调用Http/Https接口

    HttpURLConnection是JDK自身提供的网络类,不需要引入额外的jar包.文中所使用到的软件版本:Java 1.8.0_191. 1.服务端 参见Java调用Http接口(1)--编写服务 ...

  3. 自学Python编程的第五天(希望有IT大牛帮我看最下面的代码)----------来自苦逼的转行人

    2019-09-15-15:40:24 今天没有学知识,是一个一周总结,把这一周学的知识总结一遍,然后把做过的练习题再做一遍 看是否还会有再出现同样的错误,而且还可以知道有哪些知识点没有掌握好,可以把 ...

  4. 1.Javascript实现Symbol

    // 当调用 Symbol 的时候,会采用以下步骤: //1. 如果使用 new ,就报错 //2. 如果 description 是 undefined,让 descString 为 undefin ...

  5. CentOS - Eclipse安装Shelled

    一,下载Shelled: https://sourceforge.net/projects/shelled/ 二,打开Eclipse,以离线方式安装: Help->Install New Sof ...

  6. js 数组 深拷贝 复制 (汇总)

    https://www.cnblogs.com/zhoupengyi/p/6048955.html https://www.cnblogs.com/racyily/p/3532176.html htt ...

  7. VS调试 DataTable (转载)

    调试的时候遇到一个问题:不知道怎么在自动窗口或者添加监视那里查看DataSet或者DataTable的具体的值.度娘了一下很多都是添加DataTable.Rows[][]监视,但是一行一列地看还是有点 ...

  8. SpringBoot整合定时任务和异步任务处理

    SpringBoot定时任务schedule讲解 简介:讲解什么是定时任务和常见定时任务区别 1.常见定时任务 Java自带的java.util.Timer类 timer:配置比较麻烦,时间延后问题, ...

  9. VMware 设置虚拟机Centos 上网的两种方式

    能在VMware上面安装虚拟机,不可能说是不让链接外网,只是在自己电脑上玩玩就可以了.因为学习需要,经常在自己笔记本上面搭建虚拟机,我经常使用的两种上网方式 一 NET方式上网 设置VMware Ne ...

  10. 团队项目-Beta冲刺

    请大家在每次作业开头添加格式描述: 这个作业属于哪个课程 <课程的链接> 这个作业要求在哪里 <作业要求的链接> 团队名称 <写上团队名称>(附上团队博客链接) 这 ...