gulp 中的增量编译_第1页
gulp 中的增量编译_第2页
gulp 中的增量编译_第3页
gulp 中的增量编译_第4页
gulp 中的增量编译_第5页
已阅读5页,还剩5页未读 继续免费阅读

下载本文档

版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领

文档简介

1、gulp 中的增量编译最近花一点时间学了下 gulp,顺便学了下 sass,因为工作中并不需要用(我比较希望学习是需求驱动),所以一直拖到现在才学。突然觉得学习这类工具性价比很高,半天一天即可上手,技能树丰富了(尽管可能只会 20%,但是可以完成 80% 的工作了啊!),简历丰富了,所以才有这么多 前端er 不屑数据结构和算法这些基础吧,毕竟投入产出比太低,学一个简单的算法的时间都够掌握两遍基本的 gulp 工作流了!言归正传,今天要讲的是 gulp 的增量编译。在编译的过程中,有没有发现很多不必要的编译呢?我们以如下的例子为例:复制代码let dest = 'css/'/ s

2、ass -> cssgulp.task('css', function() / 任务名 return gulp.src('sass/*.scss') / 目标 sass 文件 .pipe(plumber(errorHandler: notify.onError('Error: <%= error.message %>') .pipe(sass() / sass -> css .pipe(debug(title: '编译') .pipe(gulp.dest(dest););gulp.task('wat

3、ch', function() gulp.watch('sass/*.scss', 'css'););gulp watch 启动监听,此时修改 sass 文件夹下的任意文件,都会编译该文件夹下的所有文件,这不是我们希望的,我们希望只对修改过的文件进行编译,即增量编译(Incremental Builds)。gulp 官方推荐了 4 个用于增量编译的插件,我们一起来看看使用方法以及它们的差异。gulp-changed - only pass through changed filesgulp-cached - in-memory file cache, n

4、ot for operation on sets of filesgulp-remember - pairs nicely with gulp-cachedgulp-newer - pass through newer source files only, supports many:1 source:destgulp-changed首先推荐的是 gulp-changed,毕竟它的作者在 GitHub 上拥有 15k 的 followers。该插件默认是通过比较源文件和生成文件的修改时间来判断是否将文件往下传递(pipe 流),当然也可以通过 haschanged 改变默认比较方式,采用 sh

5、a1 比较,感觉有点像浏览器缓存中的 Last-Modified/If-Modified-Since 和 ETag/If-None-Match。个人觉得默认比较已经足够了。复制代码let dest = 'css/'/ sass -> cssgulp.task('css', function() / 任务名 return gulp.src('sass/*.scss') / 目标 sass 文件 .pipe(plumber(errorHandler: notify.onError('Error: <%= error.message

6、 %>') .pipe(changed(dest, / dest 参数需要和 gulp.dest 中的参数保持一致 extension: '.css' / 如果源文件和生成文件的后缀不同,这一行不能忘 ) / sass() will only get the files that / changed since the last time it was run .pipe(sass() / sass -> css .pipe(debug(title: '编译') .pipe(gulp.dest(dest);gulp.task('wat

7、ch', function() gulp.watch('sass/*.scss', 'css'););值得注意的是,如果源文件和生成文件的后缀不一样,需要加上 extension 参数。个人认为还有两点需要注意。第一点是因为 gulp-changed 是基于文件的判断,所以并不一定需要开启 watch(这和接下去要说的 gulp-cached 不同),怎么说?先用 gulp css 的命令编译一次,然后修改一个文件,再用 gulp css 编译一次,这样的操作是生效的。第二点,因为 gulp-changed 只会将修改过的文件往下 pipe,所以如果后续

8、有需要合并的操作(concat 操作),那么就会导致文件缺失,合并后的文件其实就是修改过的文件了。所以 gulp-changed 只适合 1:1 的操作。gulp-cached和 gulp-changed 基于文件的对比不同,gulp-cached 可以将第一次传递给它的文件内容保留在内存中,如果之后再次执行 task,它会将传递给它的文件和内存中的文件进行比对,如果内容相同,就不再将该文件继续向后传递,从而做到了只对修改过的文件进行增量编译。复制代码let dest = 'css/'/ sass -> cssgulp.task('css', functi

9、on() / 任务名 return gulp.src('sass/*.scss') / 目标 sass 文件 .pipe(plumber(errorHandler: notify.onError('Error: <%= error.message %>') .pipe(cached('sass-task') / 取个名字 .pipe(sass() / sass -> css .pipe(debug(title: '编译') .pipe(gulp.dest(dest);gulp.task('watch

10、9;, function() gulp.watch('sass/*.scss', 'css'););和 gulp-changed 不同的是,gulp-cached 必须要开启 gulp watch,保证内存中存在副本,才能进行比较。gulp-remembergulp-remember 同样可以在内存中缓存所有曾经传递给它的文件,但是它和 gulp-cached 的区别是,在之后的 task 中,gulp-cached 会过滤掉未经修改的文件不再向下传递,而 gulp-remember 则会将未传递给它的文件进行补足从而能够继续向下传递,因此通过 gulp-cac

11、hed 和 gulp-remember 的结合使用,既能做到只对修改过的文件进行编译,又能做到当相关联的文件任意一个发生改变时,编译所有相关的文件。所以我觉得实际开发中用 gulp-cached+gulp-remember 的组合非常合适。复制代码let dest = 'css/'/ sass -> cssgulp.task('css', function() / 任务名 return gulp.src('sass/*.scss') / 目标 sass 文件 .pipe(plumber(errorHandler: notify.onErro

12、r('Error: <%= error.message %>') .pipe(cached('sass-task') / 取个名字 .pipe(sass() / sass -> css .pipe(debug(title: '编译') .pipe(gulp.dest(dest) .pipe(remember('sass-task') / 和 cached() 参数一致 .pipe(concat('all.css') .pipe(debug(title: '合并') .pipe(gu

13、lp.dest(dest);gulp.task('watch', function() gulp.watch('sass/*.scss', 'css'););由于在第一次合并文件时,gulp-remember 已经将传递过来的文件缓存在内存中了,那么即使在后续的 task 执行中,gulp-cached 插件过滤掉了未经修改过的 css 文件,但是 gulp-remember 还是能够通过自己的缓存来补全这些缺失的文件,从而做到正确地合并文件。我们还可以合理地管理两个插件的缓存,具体见文档。gulp-newergulp-newer 和 gulp-

14、changed 类似,也是基于文件对比,不过它只支持最后修改时间的对比。1 : 1 进行增量编译的例子:复制代码let dest = 'css/'/ sass -> cssgulp.task('css', function() / 任务名 return gulp.src('sass/*.scss') / 目标 sass 文件 .pipe(plumber(errorHandler: notify.onError('Error: <%= error.message %>') .pipe(newer( dest: de

15、st, ext: '.css' ) .pipe(sass() / sass -> css .pipe(debug(title: '编译') .pipe(gulp.dest(dest);gulp.task('watch', function() gulp.watch('sass/*.scss', 'css'););1 对 多进行增量编译的例子:复制代码let dest = 'css/'/ sass -> cssgulp.task('css', function() / 任务

16、名 return gulp.src('sass/*.scss') / 目标 sass 文件 .pipe(plumber(errorHandler: notify.onError('Error: <%= error.message %>') .pipe(newer('dest' + 'all.css') .pipe(sass() .pipe(concat('all.css') .pipe(gulp.dest(dest););gulp.task('watch', function() gul

17、p.watch('sass/*.scss', 'css'););遗憾的是,貌似不能同时 1:1 & 1:多 进行编译(此处问号脸 ):)gulp-watch除了以上 4 个插件外,用 gulp-watch 也是可以的。复制代码let dest = 'css/'/ sass -> cssgulp.task('css', function() / 任务名 return gulp.src('sass/*.scss') / 目标 sass 文件 .pipe(plumber(errorHandler: noti

18、fy.onError('Error: <%= error.message %>') .pipe(watch('sass/*.scss') .pipe(sass() .pipe(debug(title: '编译') .pipe(gulp.dest(dest););gulp.task('watch', function() gulp.watch('sass/*.scss', 'css'););gulp-watch 也不能使用类似 gulp-concat 的工具进行一对多的编译。之前关于 gu

19、lp 的基础笔记都不敢往首页发,本文发到首页,除了觉得很多人使用 gulp 可能不关注增量编译外,还想知道大家在实际的开发中使用的增量编译插件方式是?个人觉得 gulp-cached+gulp-remember 的搭配不错,不过我还没在实际开发中用过 gulp,所以想听听老司机的意见。参考资料:Gulp.js是目前前端非常流行的自动化构建工具,它基于流,代码优于配置,API简单,又有着大量优秀的第三方插件。它的gulp.watch()接口,可以让我们监听文件改动而进行自动构建,但是如果存在耗时的任务或者随着项目的逐渐增大,可能每次构建都要花费很多的时间,那么在Gulp中有什么解决的办法呢?其实

20、在Gulp的文档中对于增量编译有推荐下面4个插件:gulp-changed - only pass through changed filesgulp-cached - in-memory file cache, not for operation on sets of filesgulp-remember - pairs nicely with gulp-cachedgulp-newer - pass through newer source files only, supports many:1 source:dest那么他们的具体用法和区别是什么呢?gulp-cachedgulp-cac

21、hed可以将第一次传递给它的文件内容保留在内存中,如果之后再次执行task,它会将传递给它的文件和内存中的文件进行比对,如果内容相同,就不再将该文件继续向后传递,从而做到了只对修改过的文件进行增量编译。var gulp = require('gulp');var less = require('gulp-less');var cached = require('gulp-cached');gulp.task('less', function() gulp.src('./src/*.less') .pipe(cach

22、ed('less') .pipe(less() .pipe(gulp.dest('./dist'););gulp.task('watch', function() gulp.watch('src/*.less', 'less'););gulp-cached插件还可以接收一个可选的optimizeMemory参数,插件默认会将文件内容保存在内存中,如果将optimizeMemory设置为true,那么会转而将文件的md5值保留在内存中,从而减少对内存的占用,但是另一方面计算md5值也会消耗更多的时间,插件的作者建议在

23、一般情况下,并不需要开启这个功能。但是,gulp-cached在使用时也有一些限制,比如下面的例子:var gulp = require('gulp');var cached = require('gulp-cached');var remember = require('gulp-remember');var less = require('gulp-less');var concat = require('gulp-concat');gulp.task('concat', function()

24、gulp.src('./src/*.less') .pipe(cached('concat') .pipe(less() .pipe(remember('concat') .pipe(concat('all.css') .pipe(gulp.dest('./dist'););gulp.task('watch', function() gulp.watch('src/*.less', 'concat'););这是一个监听less文件改动并自动编译成css文件后合并的ta

25、sk,考虑一下这种情况,在修改文件a.less后,触发了concat的task,但是由于此时并没有修改文件b.less,所以传递给gulp-concat插件的b.less被gulp-cached过滤掉了,导致最后生成的all.css文件中只有修改后的a.less编译成的内容。那如何解决这个问题呢,此时就需要借助gulp-remember了。gulp-remembergulp-remember同样可以在内存中缓存所有曾经传递给它的文件,但是它和gulp-cached的区别是,在之后的task中,gulp-cached会过滤掉未经修改的文件不再向下传递,而gulp-remember则会将未传递给它

26、的文件进行补足从而能够继续向下传递,因此通过gulp-cached和gulp-remember的结合使用,既能做到只对修改过的文件进行编译,又能做到当相关联的文件任意一个发生改变时,编译所有相关的文件。var gulp = require('gulp');var cached = require('gulp-cached');var remember = require('gulp-remember');var less = require('gulp-less');var concat = require('gulp-c

27、oncat');gulp.task('concat', function() gulp.src('./src/*.less') .pipe(cached('concat') .pipe(less() .pipe(remember('concat') .pipe(concat('all.css') .pipe(gulp.dest('./dist'););gulp.task('watch', function() gulp.watch('src/*.less',

28、'concat'););由于在第一次合并文件时,gulp-remember已经将传递过来的文件缓存在内存中了,那么即使在后续的task执行中,gulp-cached插件过滤掉了未经修改过的less文件,但是gulp-remember还是能够通过自己的缓存来补全这些缺失的文件,从而做到正确地合并文件。你可能要问了对于这种情况,为什么还要额外引入两个插件,直接监听文件改动重新编译不就好了么?gulp.task('concat', function() gulp.src('./src/*.less') .pipe(less() .pipe(concat

29、('all.css') .pipe(gulp.dest('./dist'););相比上面这种不使用插件方式,gulp-cached和gulp-remember的结合使用还是有一定优势的:gulp-remember缓存的是less文件编译后生成的css文件,这样只有修改了的less文件才需要重新编译成css文件,其他less文件对应的css文件可以直接从gulp-remember的缓存中读取,而不使用插件的方式每次都要重现编译所有的less文件。另外,不要忘了我们还可以合理的管理两个插件的缓存:gulp.task('watch', function

30、() var watcher = gulp.watch('./src/*.less', 'concat'); watcher.on('change', function(event) console.log(event.type); if (event.type = 'deleted') delete cached.caches'concat'event.path; remember.forget('concat', require('gulp-util').replaceExten

31、sion(event.path, '.css'); ););gulp-changedgulp-changed插件也能够像gulp-cached插件一样过滤未修改过的文件做到增量编译,不同之处主要在于如何判断文件被修改过,gulp-cached是通过对文件设置缓存来进行比较,而gulp-changed则是通过比较源文件和生成文件。var gulp = require('gulp');var changed = require('gulp-changed');var imagemin = require('gulp-imagemin'

32、);var pngquant = require('imagemin-pngquant');gulp.task('img', function() gulp.src('./src/img/*') .pipe(changed('./dist/img') .pipe(imagemin( progressive: true, use: pngquant() ) .pipe(gulp.dest('./dist/img'););gulp.task('watch', function() gulp.watch(

33、'src/img/*.png', 'img'););由于gulp-changed是比较源文件和生成文件,所以调用插件的时候,要传入生成的位置,一般就是最后gulp.dest()方法要传入的参数。插件默认比较的是文件修改的时间,如果不同,就说明源文件有被修改过。另外可以通过hasChanged参数来使用插件内置的另一种比较方式:changed('dist', hasChanged: pareSha1Digest),也就是通过计算文件内容的sha1值来比较,一般情况下,生成文件的内容都是不同于源文件的,除非只是简单的拷贝,所以说基本上没什么用,has

34、Canged参数也支持传入一个函数来进行自定义比较。在使用gulp-changed插件时有一个需要注意的地方,如果在task中改变了文件的后缀名,那么就需要通过extension参数来指定新的后缀名,否则插件无法找到生成的文件,比较令人遗憾的是,对于这种情况gulp-changed插件不会有任何提示,只是默默的执行了task,但是完全没有起到增量编译的目的。var gulp = require('gulp');var changed = require('gulp-changed');var less = require('gulp-less')

35、;gulp.task('less', function() gulp.src('./src/*.less') .pipe(changed('./dist', extension: '.css' ) .pipe(less() .pipe(gulp.dest('./dist'););gulp.task('watch', function() gulp.watch('src/*.less', 'less'););gulp-newergulp-newer既可以像gulp-ca

36、ched/gulp-changed那样1对1地进行增量编译,也可以像gulp-cached配合gulp-remember那样多对1地进行增量编译。它实现增量编译的原理和gulp-changed相同,都是通过比较源文件和生成文件,只不过它只支持比较修改时间。先来看一个1对1进行增量编译的例子:var gulp = require('gulp');var newer = require('gulp-newer');var less = require('gulp-less');gulp.task('less', function() gulp.src('./src/*.less') .pipe(newer( dest: './dist', ext: '.css' ) .pipe(less() .pipe(gulp.dest('./dist'););gulp.task('watch', function() gulp.watch('src/*.less', 'less'););多对1增量编译的例子如下:var gulp =

温馨提示

  • 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
  • 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
  • 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
  • 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
  • 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
  • 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
  • 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。

评论

0/150

提交评论