是时候搁置Grunt,耍一耍gulp了
也算是用了半年Grunt,几个月前也写过一篇它的入门文章(点此查看),不得不说它是前端项目的一个得力助手。不过技术工具跟语言一样日新月异,总会有更好用的新的东西把旧的拍死在沙滩上(当然Grunt肯定没死,gulp也不是多新颖的东西)。
看标题很明显知道相比Grunt,我会更为推崇gulp,不是说Grunt不好,而是gulp效率更高、健壮性更好,配置也更为简单,自然也值得我们为它任性一回。
先谈谈上述提到的gulp的优越性:
一. 性能更高
相对Grunt频繁的IO操作读写,gulp是将项目任务流程以streaming(流)的形式来做管道化处理,这句话怎么理解呢?
比如一个文件A,Grunt按顺序会有三个组件任务a、b、c 要对起进行处理,那么流程可能是这样的:
读取A → A.a() → 写A → 读取A → A.b() → 写A → 读取A → A.c() → 写A → complete/watch...
那么换成gulp又是怎样的一个过程,它大概是这么处理:
读取A并转为流信息 → A.a() → A.b() → A.c() → 写A → complete/watch...
可以看到执行任务的过程,是减少了(3-1)处对文件A的读/写操作,减轻了磁盘IO操作负担,效率自然也得到明显提升。
至于“流”的概念,可以戳这里了解一下。大致是读取文件时,不按常规那样把文件一口气写入内存中,而是把文件转为数据流,收到多少数据就处理多少数据,像经过竹筒的涓涓流水那样,有水源过来了就马上处理后(你可以假设竹筒在这里有净水的过滤作用)再送出去,直到水源全部“流”过该竹筒。
那么“管道化”处理又是怎样的概念?
它很类似jQuery中的链式写法,在nodeJS中管道式方法的api一般为.pipe() ,比如
XXXX.pipe(a()) //处理a任务
.pipe(b()) //处理b任务
.pipe(c()) //处理c任务
你也可以理解为上述的涓涓流水经过一排竹筒后,紧接着流向下一个竹筒,一直这样循环,直到流过最后一个竹筒(当然流水依旧代表数据,竹筒代表任务)。
二. 健壮性更好
gulp走的是递归编译的解析方式,有助于项目优化的健壮性。打个比方,比如我们使用sass来编写样式,其中b.scss引入了_a.scss文件,如果我们修改了_a.scss的内容,gulp会即时更新b.scss对应的b.css编译文件,但Grunt是基于缓存机制的,故不会重新编译b.scss文件,导致问题。
三. 配置更简洁
其实之前写的那篇Grunt入门的文章,我的确不懂到底要如何介绍Gruntfile.js的配置——略复杂和混乱,鄙人口才也不好,便草草几句话带过,相信读者可能也不太能够理清头绪。而gulp使用了node的流式管道化(pipe)处理,其配置和写法变得简洁、统一了许多,自然也方便理解。
为你的项目搭建gulp任务
搭建gulp其实很简单,就俩步骤——在项目根目录下安装所需组件,并配置一份gulpfile.js。
我们假设我们有一个放在D盘下的项目 D:/project,里面的文件结构是这样的:
我们打算利用gulp把RAW文件夹下的js和sass文件编译/压缩后都输出到COMPRESS文件夹下。
一. 安装组件
gulp自己有官方的组件推荐/查找页面(点我进入),就我们上述项目要求而言,我个人推荐下述几个组件:
gulp //这个是必须安装的,没有它,其它组件都用不了(注意watch组件直接集成在gulp中了,无需额外安装watch组件)
gulp-sass //编译sass用的
gulp-sourcemaps //编译sass时生成额外的.map文件用的(有啥用?看我这篇文章)
gulp-mini-css //压缩css使用的
gulp-uglify //压缩、混淆js文件用的
组件的安装很简单,直接npm安装即可,比如安装gulp:
npm install gulp
安装过程可能会遇到组件被墙导致连接不上镜像的问题,解决方法有两个,一个是翻墙,另一个是走cnpm镜像(点此查阅)。
组件全部安装完成后会在你的项目根目录下生成一个node_modules文件夹,用来存放组件模块:
二. gulpfile.js文件配置
如同Grunt需要配置Gruntfile.js文件来告知node我要用什么组件并以怎样的流程来执行任务,gulp也需要在项目根目录配置一个gulpfile.js文件。
我们新建一个gulpfile.js文件,先在之中输入下面内容:
var gulp = require('gulp'),
sass = require('gulp-sass'),
mincss = require('gulp-mini-css'),
sourcemaps = require('gulp-sourcemaps'),
uglify = require('gulp-uglify');
浓浓的commonJS风,告知node我们要使用哪些组件模块来完成任务。
接着我们进一步配置文件,告诉node我们具体要以怎样的流程来执行任务,这是完整的gulpfile.js文件内容:
var gulp = require('gulp'),
sass = require('gulp-sass'),
mincss = require('gulp-mini-css'),
sourcemaps = require('gulp-sourcemaps'),
uglify = require('gulp-uglify'); var raw_css = './RAW/css',
com_css = './COMPRESS/css',
raw_js = './RAW/js',
com_js = './COMPRESS/js'; gulp.task('sass', function () {
gulp.src(raw_css+'/**/*.scss')
.pipe(sourcemaps.init())
.pipe(sass())
.pipe(mincss())
.pipe(sourcemaps.write('/'))
.pipe(gulp.dest(com_css));
}); gulp.task('mincss', function () {
gulp.src(com_css+'/**/*.scss')
.pipe(mincss())
.pipe(gulp.dest(com_css));
}); gulp.task('minjs', function () {
gulp.src(raw_js+'/**/*.js')
.pipe(uglify())
.pipe(gulp.dest(com_js));
}); gulp.task('watch', function () {
gulp.watch(raw_css+'/**/*.scss',['sass']);
gulp.watch(raw_js+'/**/*.js',['minjs']);
}); gulp.task('default',function(){
gulp.run('sass','minjs','mincss');
gulp.run('watch');
});
我们拿写的最长的sass编译模块配置代码块来注释说明下:
//每个gulp.task(name, fn)都是一个任务配置模块,如本代码段定义了名为"sass"的任务的执行流程
gulp.task('sass', function () {
gulp.src(raw_css+'/**/*.scss') //gulp.src(glob)返回了一个可读的stream,如此行返回了RAW/css/下的全部(包含子文件夹里的).scss文件流
.pipe(sourcemaps.init()) //.pipe()管道化执行组件任务,此处调用gulp-sourcemaps的初始化api来处理接收的文件流(方便后续编译出.map文件)
.pipe(sass()) //执行gulp-sass组件任务,把.scss文件流编译为.css文件流
.pipe(sourcemaps.write('/')) //调用gulp-sourcemaps的写入api,额外输出.map文件流
.pipe(mincss()) //执行gulp-mini-css组件任务,压缩所有css文件流
.pipe(gulp.dest(com_css)); //gulp.dest(glob)返回一个可写的stream,如此行是将文件流写入到 COMPRESS/css 里的对应路径下
});
接着看看末尾处的两个代码段:
gulp.task('watch', function () { //定义名为"watch"的任务
gulp.watch(raw_css+'/**/*.scss',['sass']); //监听 RAW/css 下的全部.scss文件,若有改动则执行名为'sass'任务
gulp.watch(raw_js+'/**/*.js',['minjs']); //监听 RAW/js 下的全部.js文件,若有改动则执行名为'minjs'任务
}); gulp.task('default',function(){ //每个gulpfile.js里都应当有一个dafault任务,它是缺省任务入口(类似C语言的main()入口),运行gulp的时候实际只是调用该任务(从而来调用其它的任务)
gulp.run('sass','minjs','mincss'); //gulp.run(tasks)表示运行对应的任务,这里表示执行名为'sass','minjs','mincss'的三个任务
gulp.run('watch'); //执行'watch'监听任务
});
上述的两个步骤做好后,直接输入运行 gulp 指令即可(我是在webstorm里直接写命令的):
同时可以看到COMPRESS文件夹下已经有了我们想要的编译、压缩后的文件:
另外这时候gulp已转入监听模式(虽然不像Grunt那样有“watch...”的提示),只要你修改了被监听的文件,任务会立即被执行一遍,无需再手动gulp一次。
用下来还是觉得gulp是个好东西,比Grunt更易上手,效率也更好,不过相较Grunt的“grunt-newer”组件,gulp对应功能的两个组件“gulp-changed”和"gulp-newer"貌似运行起来都达不到预想效果,比如我希望只针对我修改了的某个sass文件来做任务处理,我做了如下配置:
var gulp = require('gulp'),
sass = require('gulp-sass'),
mincss = require('gulp-mini-css'),
sourcemaps = require('gulp-sourcemaps'),
changed = require('gulp-changed'),
uglify = require('gulp-uglify'); var raw_css = './RAW/css',
com_css = './COMPRESS/css',
raw_js = './RAW/js',
com_js = './COMPRESS/js'; gulp.task('sass', function () {
gulp.src(raw_css+'/*.scss')
.pipe(changed(raw_css+'/*.scss'))
.pipe(sourcemaps.init())
.pipe(sass())
.pipe(sourcemaps.write('/'))
.pipe(mincss())
.pipe(gulp.dest(com_css));
}); gulp.task('mincss', function () {
gulp.src(com_css+'/*.scss')
.pipe(changed(com_css))
.pipe(mincss())
.pipe(gulp.dest(com_css));
}); gulp.task('minjs', function () {
gulp.src(raw_js+'/*.js')
.pipe(changed(com_js))
.pipe(uglify())
.pipe(gulp.dest(com_js));
}); gulp.task('watch', function () {
gulp.watch(raw_css+'/*.scss',['sass']);
gulp.watch(raw_js+'/*.js',['minjs']);
}); gulp.task('default',function(){
gulp.run('sass','minjs','mincss');
gulp.run('watch');
});
结果发现依旧是整个文件夹下的文件都被做了任务处理。或许是我的配置不正确,若有了解newer或者changed的朋友望能不吝指正。
另外百度fis貌似也是另一个不错的alternative,跟gulp差不多,而且中文文档也挺详细的,之前用过百度的一些东西,感觉质量还是有保障的。
最后推荐下一个大神级朋友的博客,在我们苦口婆心的催产下他终于发表了第一篇文章,介绍的JS面向对象的思想,欢迎大家去看一看。
共勉~
是时候搁置Grunt,耍一耍gulp了的更多相关文章
- gulp和grunt的区别
1. Grunt -> Gulp 早些年提到构建工具,难免会让人联想到历史比较悠久的Make,Ant,以及后来为了更方便的构建结构类似的Java项目而出现的Maven.Node催生了一批自动化工 ...
- Gulp vs Grunt 前端构建工具对比
Gulp vs Grunt 前端工程的构建工具对比 1. Grunt -> Gulp 早些年提到构建工具,难免会让人联想到历史比较悠久的Make,Ant,以及后来为了更方便的构建结构类似的Jav ...
- 前端工程的构建工具对比 Gulp vs Grunt
1. Grunt -> Gulp 早些年提到构建工具,难免会让人联想到历史比较悠久的Make,Ant,以及后来为了更方便的构建结构类似的Java项目而出现的Maven.Node催生了一批自动化工 ...
- 谈谈Grunt,NPM,Gulp
随着前端工程化的趋势,产生了越来越多的构建工具,而其中比较优秀的就是grunt,npm,gulp,今天我来说说这三者间的区别以及他们的优缺点. 相信一般前端开发者选择构建工具的时候,更多的是看个人习惯 ...
- Node开发项目管理工具 Grunt 对比 Gulp
转自Gulp vs Grunt 1. Grunt -> Gulp 早些年提到构建工具,难免会让人联想到历史比较悠久的Make,Ant,以及后来为了更方便的构建结构类似的Java项目而出现的Mav ...
- Appium+python自动化(二十一)- 让猴子按你指令大闹手机,让你成为耍猴高手 - Monkey(猴子) - MonkeyScript(超详解)
简介 一年一度的暑假如期而至,每年必不可少的,便是<西游记>这部经典电视连续剧的播出,作为一名90后,对于这部经典剧的情谊,就是观看已成为一种习惯.依然深刻的记得,小时候妈妈为了催促我睡觉 ...
- 如何选择JavaScript构建工具之Babel、Browserify、Webpack、Grunt以及Gulp
当我们开始一个新的 JavaScript 项目时,我们需要考虑的第一件事就是搭建一个前端编译环境.但是在面对众多的 JavaScript 构建工具时,我们却无所适从,不知道究竟哪一个才是最适合我们的. ...
- 送干货,实用内联gulp插件——gulp-embed
现在npm上有很多gulp内联工具,用于把脚本和样式内嵌到HTML页面上,之前搞项目我也在这些插件中寻觅许久,但均不满足公司项目的一个需求—— HTML上同时插入了开发(dev版,src文件夹下,比如 ...
- Gulp 自动化的项目构建工具
在很多场合都会听到前端工和 node 程师推荐 Grunt 来实现项目的自动化,自动化可以自动完成 javascript/coffee/sass/less 等文件的的测试.检查.合并.压缩.格式化.部 ...
随机推荐
- 认识 Azure
本文为官网摘录总结
- DOM、BOM 操作超级集合
本章内容: 定义 节点类型 节点关系 选择器 样式操作方法style 表格操作方法 表单操作方法 元素节点ELEMENT 属性节点attributes 文本节点TEXT 文档节点 Document 位 ...
- 《LoadRunner12七天速成宝典》签售会2016-12-17北京
报名地址: http://www.after615.com/actives/s?id=3141&time=1480042829608&sign=9ac8e25e9ab3cf57f613 ...
- js callee,caller学习
原文地址:js callee,caller学习 /* * caller 返回一个对函数的引用,该函数调用了当前函数. * 如果函数是由顶层调用的,那么 caller包含的就是 null . * 如果在 ...
- Tomcat启动报错org.springframework.web.context.ContextLoaderListener类配置错误——SHH框架
SHH框架工程,Tomcat启动报错org.springframework.web.context.ContextLoaderListener类配置错误 1.查看配置文件web.xml中是否配置.or ...
- Java实现Excel中的NORMSDIST函数和NORMSINV函数
由于工作中需要将Excel中的此两种函数转换成java函数,从而计算内部评级的资本占用率和资本占用金额.经过多方查阅资料和整理,总结出如下两个转换方法 标准正态分布累计函数NORMSDIST: pub ...
- Register-SPWorkflowService 404
最近需要做一个SharePoint 2013工作流演示环境. 于是在自己的本子上安装了一个虚拟机. 虚拟机操作系统是Windows Server 2012 R2,计划把AD.SQL Server 20 ...
- listview下拉刷新和上拉加载更多的多种实现方案
listview经常结合下来刷新和上拉加载更多使用,本文总结了三种常用到的方案分别作出说明. 方案一:添加头布局和脚布局 android系统为listview提供了addfootview ...
- NodeJS使用mysql
1.环境准备 手动添加数据库依赖: 在package.json的dependencies中新增, "mysql" : "latest", { "nam ...
- 【腾讯优测干货分享】安卓专项测试之GPU测试探索
本文来自于Dev Club 开发者社区,非经作者同意,请勿转载,原文地址:http://dev.qq.com/topic/57c7ffdc0569a1191bce8a63 作者:章未哲——腾讯SNG质 ...