gulp系列文章一 fis vs grunt和gulp的区别 vs gulp,为什么要是gulp

Gulp挑战Grunt,背后的哲学 - 简书
下载简书移动应用
写了25123字,被36人关注,获得了88个喜欢
Gulp挑战Grunt,背后的哲学
[按:网上介绍Gulp和Grunt安装使用的文章很多,甚少比较二者的思路,连官方文档都语焉不详。我在此做一个粗陋的对比,希望能提纲挈领,加深读者对这两个工具的理解。]
做过点儿正经开发的同学都知道,构建工具必不可少。C时代的Make、Java的Ant、Ruby的Rake……没有这些工具,一遍遍地点选输入,准烦死你。
在前端和Node JS的开发中,最普及的构建工具就是Grunt。它的功能说来简单,就是管理一系列的Task。大部分的Task都是第三方的插件,安装好对应的NPM包,再loadNpmTasks就可以用了。
Grunt的配置文件Gruntfile,主要包含两部分:
配置每个Task,包括文件从哪里,到哪里去,还有一些处理的选项
自己写一些简单的Task,把第三方插件提供的Task组合起来
别看这两个事儿,轻轻松松几百行出来了。每个Task的配置,各有各的规矩,还牵扯到插件间的配合。反正我从seed库开始做新项目的时候,基本不敢改原来的Gruntfile,很多用不上的功能也搁那儿。留意了一下很多开源项目的Gruntfile,也都臃肿杂乱,好不到哪儿去。
Gruntfile维护起来那么困难,有几个原因:
配置和运行分离程序员都知道,变量的声明和使用挨在一起,最方便理解和修改。但Gruntfile里,配置Task和调用它们的地方离得很远,极大地增加了心智负担。
每个插件做的事太多每个Task的结果必须写到磁盘文件,另一个Task再读,损害性能倒是小事,更麻烦的是让整个过程变复杂了。就像一个个小作坊,来料加工又返回给客户,这中间的沟通成本、出错机会都大大增加。
配置项过多做事多了,配置项自然也多。至少输入和输出的位置得配吧。每个插件的配置规则还不尽相同。用每个插件,都得去学习一番。
Gulp应运而生。
恐怕没几个IT人不知道Unix管道的概念。前一级的输出,直接变成后一级的输入。把简单的工具组合起来,优雅地解决复杂的问题。听起来那么熟悉呢?是的,Gulp就把这种思维用在构建过程中。
Gulp基于Node JS的一个机制,叫做,有点类似C++中的stream。在Node中,文件访问、输入输出、HTTP连接,都是stream。Gulp的每个插件从stream中读取输入,做一些处理,再输出到stream中。
每个插件不是拿来独立使用的。相反,它专注于完成单一职责。只有把合适的插件组合起来,才能完成具体的Task。引用,看看一个典型的Task长什么样(略有删减):
var paths = {
scripts: ['client/js/**/*.coffee', '!client/external/**/*.coffee']
gulp.task('scripts', ['clean'], function() { // 可以依赖于其它task
return gulp.src(paths.scripts) // 指定输入
.pipe(coffee()) // 环节一
.pipe(uglify()) // 环节二
.pipe(concat('all.min.js')) // 环节三
.pipe(gulp.dest('build/js')); // 指定输出
配置呢?不需要了。是不是行云流水,一气呵成?
那我们再回头来看看前面Grunt的几个问题,Gulp是怎么解决的:
配置和运行分离code over configuration,直接就在调用的地方配置。
每个插件做的事太多单一职责,依靠组合来发挥作用。就像一条自动化生产线,上一道工序的产出直接交给下一步,效率不要太高。
配置项过多既然大家都遵循同一个协议,很多配置就不需要了。
放大了看,Gulp像是一个非常贴近领域模型的DSL,而Grunt更像万能的XML。哪个好用,无需多说。在我们制作DSL时,也有参考意义。
最后,举一个Grunt很别扭,Gulp却能优雅解决的例子。
做前端开发会用到一个功能叫usemin。我们HTML中会引用到很多css和js文件。发布时,这些文件要合并、压缩、混淆,最后生成一两个文件。为了让修改过的代码绕过浏览器的缓存机制,要根据文件内容hash出文件名。html文件里就要引用这些新的文件名。
比较一下和各自README的长度,就能看出区别。
grunt.registerTask('build', [
'useminPrepare', // 准备
'filerev',
'usemin' // 执行
grunt-usemin分成两步:
先从html文件中收集需要处理的js和css,传给后续的一堆任务它本身并不知道在实际中会调用哪些其它Task,只能用一些hack,支持固定的几个Task。而上面的每个Task,都有自己的配置项。要把这些配置项都列出来,实在太长了。
真正执行,更新html文件里的js和css引用。
而gulp-usemin就干净得多,没有丝毫多余的东西:
gulp.task('usemin', function() {
gulp.src('./*.html')
.pipe(usemin({
css: [minifyCss(), 'concat'],
html: [minifyHtml({empty: true})],
js: [uglify(), rev()]
.pipe(gulp.dest('build/'));
usemin不需要有minifyCss、minifyHtml、uglify和rev这几个插件的任何知识,只要把对应的内容从stream丢出去就好。在用这些插件组装task时才需要关心。
当前,Gulp的社区还远不如Grunt成熟,有些功能的插件,Gulp可能就没有。这其实不算很大的劣势,只要足够好用,追上来很快。而且,写一个Gulp插件要比相应的Grunt插件短小得多!
如果觉得我的文章对您有用,请随意打赏。您的支持将鼓励我继续创作!
打开微信“扫一扫”,打开网页后点击屏幕右上角分享按钮
被以下专题收入,发现更多相似内容:
如果你是程序员,或者有一颗喜欢写程序的心,喜欢分享技术干货、项目经验、程序员日常囧事等等,欢迎投稿《程序员》专题。
专题主编:小...
· 155656人关注
用于提高各种效率的工具和方法搜集
· 30539人关注
每个程序员上辈纸都是法力无边的巫师
· 4035人关注
如果觉得我的文章对您有用,请随意打赏。您的支持将鼓励我继续创作!
选择支付方式:gulp或者grunt中有哪些神一般的task?
按时间排序
front-end-separate(前后端分离脚手架)一个前后端分离的脚手架工具(自主研发)为什么选择grunt而不是gulp如果你也和我一样喜欢grunt这种配置的方式,那么我相信这个脚手架觉对十分适合你所有静态资源都md5全并压缩打包,css,js,img,html已在生产环境验证基于express和grunt的前后端分离框架模板引擎使用的是nunjucks,好处是可以实现模版继承,又不像jade一样把html标签都简化了express提供路由服务项目中app为原代码文件(开发用),dist为打包后的文件(用于线上)开发使用app,线上使用dist,支持一键cdn部署,加速你的项目项目启动时,修改任何express代码,可以实现自动重启–基于nodemon支持sass图片精灵(自动打包精灵图片,再也不用手动去拼凑了)基于grunt md5 打包合并线上输出的html已经压缩成一行(让你的代码更有Geeker范)###怎么使用:clone 代码启动命令行:如果没有安装grunt,请先全局安装grunt bash $ npm i grunt-cli -g 安装npm包(可能需要一段时间,请耐心等待)$ npm i
开发模式(可以打开浏览器localhost:3001开始开发,端口配置文件里可以更改)$ grunt
打包$ grunt build
打包成CDN模式(config/config.js中可配置cdn路径)$ grunt buildCdn
browserSync(可以实现更改静态资源自动刷新了)$ grunt serve
浏览器输入localhost:3001,你就可以看到漂亮的页面了打包命令 grunt build 会生成dist文件夹,里面可以看到js、css都加了md5缀tip:scss推荐用Webstorm自带的File watch功能,非常方便(安装node-sass即可)-关于图片精灵$ grunt sprite 执行即可得到精灵图片,如需配置请去config/grunt/sprite.js下配置更多的图片精灵在scss中引用@import “sprite” 样式中写如:@include sprite($index_bg); 即可使用;如果大家喜欢的话,请点一下star此项目或follow一下本人,即是对本人最大的支持我会继续完善这个项目的,并一直维护下去,如果有任何问题,欢迎在issues里面提出感谢大家支持!——Nobody
我觉得官方文档的很多秘籍非常好 (中文版本)贴出目录来
我做了一个简单的方案,针对单页面的js和css打包处理,对当前项目侵入少,我的方案,支持base64,支持雪碧图,md5改了3处源码,js支持简单的合并压缩混淆方案,也支持webpack打包,支持es6,欢迎star,京东的jdf和百度的fis和腾讯的tmt都是基于项目的打包方案,适合他们公司自己,但使用起来麻烦而且对国内开源项目没有信心,网上的方案五花八门 。总结了下用useref的可配置性不强,用gulprev配合其他插件的md5会有文件冗余,而且很多的sourcemap也有问题,我的方案是单独放到一个dist目录,发布到线上就删掉maps目录,既不会泄露源码又方便调试。主要是对网上很多方案失望,不适合自己的项目,所以自己做了一个,欢迎大家提建议!
刚刚写了一个,用于express的自动构建,可以一行指令新建一个新的页面及路由。gulp.task("new_view",function(name){
return gulp.src('templates/page.handlebars')
.pipe(template({name: name?name:"new"}))
.pipe(rename({
basename:name
.pipe(gulp.dest('views'));
gulp.task("new_router",function(name){
return gulp.src('templates/router.js')
.pipe(template({name: name?name:"new"}))
.pipe(rename({
basename:name
.pipe(gulp.dest('routes'));
gulp.task("new_less",function(name){
return gulp.src('templates/style.less')
.pipe(template({name: name?name:"new"}))
.pipe(rename({
basename:name
.pipe(gulp.dest('src/less'));
gulp.task("inject_app",function(name){
return gulp.src("app.js")
.pipe(replace("//newFilesRouter", '//newFilesRouter\nvar router_'+name+' = require("./routes/'+name+'");'))
.pipe(replace("//newRouter", '//newRouter\napp.use("/'+name+'", router_'+name+');'))
.pipe(gulp.dest("./"))
gulp.task('new',function (name,router) {
if(router)
return runsequence(['new_view',"new_less","new_router","inject_app"]);
return runsequence(['new_view',"new_less"]);
这些task可以生成对应名称的页面,样式文件和配置路由,同时在app.js中注册路由。执行代码npm new --name newpage --router
记得yeoman有一个基于grunt的angular构建工具可以做到在控制台生成新的组件,但是基于gulp的没有见到过,另外就是注入js文件用了一点奇技淫巧,替换标识注释的同时再次更新的标识注释,用replace实现了inject。
看了所有的答案,真是美团感爆棚。
我自己写了一个,不是gulp插件,反而是gulp的一些整合:browerify-build,整合了sass,imagemin browserify browerSync.支持全局安装
既然问gulp和grunt,自然想到:这两个插件作者不一样,名字怎么这么像呢?前者让你在gulp里调用grunt的任务,后者能在grunt里开gulp的任务。神器啊。
这个必须是[grunt-usemin]()啊,功能很强大,但是配置没人看得懂!!
补充一下:
gulp-connect-proxy 代理外部的接口
如果基于现成的接口开发,就省了 mock 数据这一步,更方便;
我当前的个人项目的开发模式 python/php/ruby/postgrest + gulp/grunt, 一边都是后端的接口先开发完,然后开始开发前端,这个代理插件给我带来了极大的方便,
有人说直接在后端服务器上开发,那就没法使用 gulp-server-livereload(@droiz)这种好用的自刷新的组件(或者其他的前端工具了)了,我还是偏喜欢前后端开发环境分离
var Proxy = require('gulp-connect-proxy');
// A local web server for dev convenience
gulp.task("server", function() {
connect.server({
root: "./dist",
port: 22532,
middleware: function (connect, opt) {
opt.route = '/proxy';
var proxy = new Proxy(opt);
return [proxy];
自己有一个task: 不能说神,但是极大方便了前端 template 的管理。这款task使前端开发也可以像后端一样,把模板文本存放在单独的文件中(而不是放在dom节点但或者手工js拼接字符串), 然后将其编译成javascript文件。使我们的开发工作从繁琐的dom操作和JS拼串中解放出来,提高我们的开发效率。最主要的,模板文件作为单独文件存放,可以使我们的项目代码逻辑更加清晰,更具可维护性。都支持啥模板引擎?grunt-cptpl支持各大主流模板引擎:artTemplate、 Handlebars 、Hogan 、 Underscore、 juicer、 doT、 kissy、 baiduTemplate。 对于不在此列的引擎,提供了自定义编译方法接口。这玩意都做了啥?grunt-cptpl会读取每个模板文件的文本内容,用指定模板引擎的预编译方法将其包裹起来,生成一个新的javascript文件。这个javascript文件文件里面的内容,其实就是模板引擎的预编译方法调用,传入的参数为模板文件的文本内容。这样我们就有了一个编译好的模板函数,要渲染的时候把数据传给它就好了。欢迎一试哈~
这个 task 写完后感觉挺有趣的. 这个 task 可以让 gulp 监测 gulpfile 自身的改动, 并且重新启动自己 :D. 完蛋了, 人工智能崛起后这种程序好可怕的赶脚.这个 task 的用途是用 gulp watch 文件的改动并启动相应的 task ( 我们用 gulp 做增量开发基本都会这么搞 ). 有趣的地方在于如果 gulpfile 自身发生了改动, 那么 gulp 将会重新启动自己. 为了达到这个目的, 这里需要做两层 watch, 通过 gulp watch 去启动 child process 的 deep-watch, 这样当 gulp 自身改变了以后, 他重启的部分是 deep-watch. 愚蠢的人类啊, 以为逃出 Matrix 来到 Sion 就是现实了? var Path = require('path');
var Chalk = require('chalk');
var gulp = require('gulp');
var watch = require('gulp-watch');
// ... some other codes ...
var tasks = {
var gulpfiles = ['**/gulpfile.js', '**/tasks/*.js'].concat(ignores);
function dowatch ( taskName ) {
watch( paths[taskName], function ( file ) {
if ( file.event !== 'unlink' ) {
gulp.start(taskName);
}).on('error', function (e) {
console.warn(e.message);
gulp.task('deep-watch', function() {
for ( var name in tasks ) {
dowatch(name);
gulp.task('watch', function() {
// reload if gulpfile changed
function restart () {
if ( p ) {
console.log( Chalk.yellow.bold('gulpfile changed, deep-watch restart!') );
var spawn = require('child_process').spawn;
p = spawn('gulp', ['deep-watch'], {stdio: 'inherit'});
watch( gulpfiles, restart ).on('error', function (e) {
console.log( Chalk.red(e.message) );
restart();
useref,合并html中指定的js,cssbrowser-sync,更改页面自动刷新浏览器,双屏必备,那一个酸爽
在node中使用gulp,自动刷新browserSync,应该要怎么引入 入口文件app.js ?
-& nodemon !// 程序入口
gulp.task('nodemon', function (cb) {
var called =
return nodemon({
script: 'app.js',
ext: 'js',
ignore: ['public/**'],
env: {'NODE_ENV': 'development'}
.on('start', function onStart() {
if(!called){cb();}
.on('restart', function() {
setTimeout(function() {
console.log('-------- restart --------');
reload({stream: false});
// 监听变化
gulp.task('browser-sync', ['nodemon'], function(){
browserSync.init({
files: ['public/**','views/**'],
proxy: 'http://localhost:3000',
port: 4000,
browser: ['/Applications/Google\ Chrome\ Canary.app/'],
notify: true,
前人的基础上修改了一下,能做到:1. 监听 项目 静态资源模块以外 js文件变化(如:修改route文件),重启服务 & 自动刷新页面。2. 监听 模板文件,静态资源文件变化,自动刷新页面。其他 task 可以根据项目情况,自主选择加入。
怒答一记~从Material-ui项目里学习到的整个gulp提取出来了,针对jsx(es6),用到了babel browserify没有添加css预处理,可以自行添加sass或者less...uglify在最终build的时候把注释去掉,就能用了哟~github地址 : star了以后建构项目就不yeoman自动生成的gulp了(虽然可以自己写,但是肯定没这么好哒)
介绍两个插件。这两个插件,是因为我花了近一天的时间各种搜索和试用,一直没找到合适的,尼玛然后就自己写了个。所以,我觉得,应该还是挺有用的,因为我一直没找到其他顺手的啊。1、
用来合并JS和CSS引用的。
gulp.task('merge',function(){gulp.src('*.css').pipe(
'css/all.css':['**/*.css'],
'js/all.js':['**/*.js']
},{debug:true}
)).pipe(gulp.dest('dist'))})
执行gulp merge前:&head&
&link type="text/css" href="base.css" /&
&link type="text/css" href="common.css" /&
&script src="jquery.js"&&/script&
&script src="app.js"&&/script&
执行后:&head&
&link type="text/css" href="css/all.css" /&
&script src="js/all.js"&&/script&
类似插件: gulp-preprocess 不过它实现的是在HTML中声明,我特别讨厌这种在原代码中声明的方式,个人感觉很不爽2、
至于为什么叫2,不是因为很二。。。
因为是在gulp-css-spriter基础上改了一丢丢,所以取名为2,
另外也因为雪碧图插件一堆堆的,各种重名只有加个2了,
gulp-css-spriter是我觉得在这一堆堆里算是最好用的了,但是还有有两点很不爽,
1)过滤采用的是在css文件中声明的方式,我说过了,我对于这种语法很不爽!
2)不能实现分组。
介于此,在原基础上,参数options添加了ignore属性,
1)过滤:ignore:[ "img/*.gif" ]
2)分组:创建多个task, 好了,求赞。。。我就这点乐趣了。。。
后端nodejs,项目构建工具grunt,模块打包webpack。之前,每次改动服务器js代码后,都要手动重启服务器,真是疼;之前,每次改动逻辑代码后,都要重新打包js,真是疼;之前,每次改动css后,都要刷新浏览器,真是疼;现在,一切都是自动化,一切都是所见即所得,以下 ,是我的app项目自动化配置。文件压缩跟加密webpack都能干,grunt主要是监测文件改动。var path = require('path');var webpack = require("webpack");var webpackConfig = require("./project/webpack.config.js");module.exports = function (grunt) { grunt.initConfig({
pkg: grunt.file.readJSON('package.json'),
dynamic_mappings: {
expand: true,
cwd: 'project/js',
src: ['*.js'],
dest: 'project/src',
ext: '.js'
options: {
banner: '/*! &%= pkg.name %& &%= grunt.template.today("yyyy-mm-dd") %& */\n'
// Grunt will search for "**/*.js" under "lib/" when the "uglify" task
// runs and build the appropriate src-dest file mappings then, so you
// don't need to update the Gruntfile when files are added or removed.
expand: true,
// Enable dynamic expansion.
cwd: 'project/',
// Src matches are relative to this path.
src: ['bundle.js'], // Actual pattern(s) to match.
dest: 'project/',
// Destination path prefix.
ext: '.min.js',
// Dest filepaths will have this extension.
files: ['project/src/*.js'],
options: {
globals: {
exports: true
options: {
banner: '/*! &%= pkg.name %& &%= grunt.template.today("yyyy-mm-dd") %& */\n'
dynamic_mappings: {
// Grunt will search for "**/*.js" under "lib/" when the "uglify" task
// runs and build the appropriate src-dest file mappings then, so you
// don't need to update the Gruntfile when files are added or removed.
expand: true,
// Enable dynamic expansion.
cwd: 'project/css',
// Src matches are relative to this path.
src: ['*.css'], // Actual pattern(s) to match.
dest: 'project/build',
// Destination path prefix.
ext: '.css',
// Dest filepaths will have this extension.
filerev: {
options: {
algorithm: 'md5',
length: 16
expand: true,
cwd: 'project/',
src: ['bundle.js'],
dest: 'project'
express: {
options: {
port: 3000,
background: true
options: {
script: './project/app.js',
webpack: {
options: webpackConfig,
devtool: "sourcemap",
debug: true
connect: {
files: ['project/*.js', 'project/libs/*.js', 'project/views/*.ejs', 'project/public/css/*.css'],
options: {
livereload: true
webpack: {
files: ["project/libs/*.js", 'project/webpack.config.js'],
tasks: ["webpack:dev"],
options: {
spawn: false,
express: {
files: ['project/app.js', 'project/server/*.js'],
tasks: ['express:dev'],
options: {
spawn: false
}); // grunt.loadNpmTasks('grunt-react');
// grunt.loadNpmTasks('grunt-contrib-uglify');
// grunt.loadNpmTasks('grunt-contrib-jshint');
// grunt.loadNpmTasks('grunt-contrib-cssmin');
// grunt.loadNpmTasks('grunt-contrib-connect');
// grunt.loadNpmTasks('grunt-contrib-imagemin');
// grunt.loadNpmTasks('grunt-usemin');
// grunt.loadNpmTasks('grunt-filerev');
grunt.loadNpmTasks("grunt-webpack");
grunt.loadNpmTasks('grunt-contrib-watch');
grunt.loadNpmTasks('grunt-express-server');
grunt.registerTask('default', ['webpack:dev', 'express', 'watch']);};
generator-gulp-angular ()这是一个Yeoman Generator,最近项目里稍微改了一下在用。其中有两个task我觉得很实用。一个是Inject,代码如下'use strict';
var gulp = require('gulp');
var $ = require('gulp-load-plugins')();
var wiredep = require('wiredep').
module.exports = function(options) {
gulp.task('inject', ['scripts', 'styles'], function () {
var injectStyles = gulp.src([
options.tmp + '/serve/app/**/*.css',
'!' + options.tmp + '/serve/app/vendor.css'
], { read: false });
var injectScripts = gulp.src([
options.src + '/app/**/*.js',
'!' + options.src + '/app/**/*.spec.js',
'!' + options.src + '/app/**/*.mock.js'
.pipe($.angularFilesort()).on('error', options.errorHandler('AngularFilesort'));
var injectOptions = {
ignorePath: [options.src, options.tmp + '/serve'],
addRootSlash: true
return gulp.src(options.src + '/*.html')
.pipe($.inject(injectStyles, injectOptions))
.pipe($.inject(injectScripts, injectOptions))
.pipe(wiredep(options.wiredep))
.pipe(gulp.dest(options.tmp + '/serve'));
这个task其实信息量还是有点大的,首先是 gulp-load-plugins 这个插件,它可以自动加载所有devDependencies插件,这样就不需要在开头写一堆require了。接下来是gulp-inject,这个插件通过在文件中寻找特定的tag,将指定的文件插入到目标文件中,比如Less、Sass的import,CMD的Module,html的JS及css依赖然后是wiredep,通过检查bower.json注入依赖,类似于gulp-inject,不过需要bower的包做的比较好,有些支持不是很好。gulp-angular-filesort,调整angular各模块的依赖顺序。这个文件扩展一下适用还是比较广的,大部分模块化的项目都可以用到,可以说是这个generator里面比较出彩的一部分了。第二个是Build,这是一个task的集合,我这里拿出其实两个比较重要的:partials和htmlgulp.task('partials', function () {
return gulp.src([
options.src + '/app/**/*.html',
options.tmp + '/serve/app/**/*.html'
.pipe($.minifyHtml({
empty: true,
spare: true,
quotes: true,
loose: true
.pipe($.angularTemplatecache('templateCacheHtml.js', {
module: 'foo',
root: '/app'
.pipe(gulp.dest(options.tmp + '/partials/'));
partials这个task的作用是将所有Angular的template合并起来,最后通过angular的templateCache服务将原本的Html载入,优点是减少请求数,在app不大的时候能显著的提高加载速度。gulp.task('html', ['otherStyles', 'partials'], function () {
var partialsInjectFile = gulp.src(options.tmp + '/partials/templateCacheHtml.js', {read: false});
var partialsInjectOptions = {
starttag: '&!-- inject:partials --&',
ignorePath: options.tmp + '/partials',
addRootSlash: false
var htmlFilter = $.filter('*.html');
var jsFilter = $.filter('**/*.js');
var cssFilter = $.filter('**/*.css');
return gulp.src(options.tmp + '/serve/*.html')
.pipe($.inject(partialsInjectFile, partialsInjectOptions))
.pipe($.replace('/bower', '../bower'))
.pipe(assets = $.useref.assets())
.pipe($.rev())
.pipe(jsFilter)
.pipe($.ngAnnotate())
.pipe($.stripDebug())
.pipe($.uglify({preserveComments: $.uglifySaveLicense})).on('error', options.errorHandler('Uglify'))
.pipe(jsFilter.restore())
.pipe(cssFilter)
.pipe($.csso())
.pipe(cssFilter.restore())
.pipe(assets.restore())
.pipe($.useref())
.pipe($.revReplace())
.pipe(htmlFilter)
.pipe($.minifyHtml({
empty: true,
spare: true,
quotes: true,
conditionals: true,
loose: true
.pipe(htmlFilter.restore())
.pipe(gulp.dest(options.dist + '/'))
.pipe($.size({title: options.dist + '/', showFiles: true}));
html基本就是最后的打包流程了,包括注入资源的合并,html、css、js压缩,版本号自动添加,Angular依赖注入修正等,基本上中小型项目需要做的都做了。这个generator还提供其他的很多功能,由于项目限制就没有使用了,总之这是一个结构清晰、代码风格也比较规范的workflow,是比较适合初学者学习的,缺点就是经常来个大更新,之前版本的代码完全不能兼容,要升级的话还是有点麻烦,具体代码可以参见项目的Repo。以上。
自己有一个task,不算神,但日常来说还是挺方便。livereload+sass自动编译+简易webserver。从编辑器复制来的,凑活看吧,,,var gulp = require('gulp'),
sass = require('gulp-sass'),
sourcemaps = require('gulp-sourcemaps'),
server = require('gulp-server-livereload');gulp.task('start', function() {
gulp.src('stylesheet/style.scss')
.pipe(sourcemaps.init())
.pipe(sass().on('error', sass.logError))
.pipe(sourcemaps.write('./map'))
.pipe(gulp.dest('./stylesheet'));
gulp.src('stylesheet/style2.scss')
.pipe(sourcemaps.init())
.pipe(sass().on('error', sass.logError))
.pipe(sourcemaps.write('./map'))
.pipe(gulp.dest('./stylesheet'));});gulp.task('default', ['webserver'], function() {
gulp.watch(['stylesheet/style.scss', 'stylesheet/style2.scss'], ['start'])
.on('change', function(event) {
console.log('rebuild
'+event.path);
});});gulp.task('webserver', function() {
gulp.src('./')
.pipe(server({
defaultFile: 'index.html',
livereload: {
enable: true,
filter: function(filePath, cb) {
cb( !(/node_modules/.test(filePath)) );
没人回答?好,我来。不是glup党,所以说说我用的grunt。0 concat 基础工具。一般来说我觉得它很有用,在开发环境中1 cssmin
这个task比较牛,自动优化合并css,不是单单的压缩,还有自动生成css patch,比如你写transition类css3,会自动为你补上浏览器前缀。grunt-contrib 主力维护项目,之前还为它repo过issue2
如果是用AMD 的requirejs 做模块加载器,首选它作为js压缩工具,内置的r.js 是专门为requirejs设计的js合并压缩parser,将define都合并到一个文件里。3 imagemin
node图片压缩首选,有几级level优化,追求pref4 还有个工具忘记叫什么名字了, 之前用过, 用来检索所有项目 HTML 和 CSS 文件, 分析CSS依赖, 自动删除掉没有用的CSS, 尤其是大项目, 做这样的优化很有必要, 在开发过程中, 有些CSS有可能在改了又改之后就没有地方需要了。jsconf 上有介绍过
已有帐号?
无法登录?
社交帐号登录

我要回帖

更多关于 grunt和gulp 的文章

 

随机推荐