Gulp
什么是Gulp
- Gulp是基于Node.js的构建工具,我们使用它来集成前端开发环境,来构建自动化工作流程。
- 通常一些常见、重复的任务我们可以使用Gulp来代替我们完成,例如压缩代码文件/图片等资源,给CSS添加兼容性前缀,ES6语法转换成ES5,打包代码以及部署环境等。
- gulp的核心概念是流,可以简单类比为工厂的流水线,从原材料到最后的商品,会经过很多道工序,每一道工序的输入都是前一道工序的输出。gulp的任务就是把源文件进行各种加工处理最终输出到指定位置,省略了途中的中间文件,相比grunt的频繁IO操作,gulp的流操作,能更快更便捷地完成构建工作。
- 流与流之间是通过管道(pipe)连接的,pipe接受一个函数作为参数,将当前流的内容传给这个函数让其加工。可以想象成让流中的所有文件一个接一个地流过有着某种加工方法的管道。
- gulp虽然是基于node的,但是它并没有直接使用node中fs模块里的文件系统和流,而是包装了一层vinyl。
vinyl是一个用来描述文件的简单的数据格式。所以gulp中的流其实是一种vinyl流,与我们通常所见的流其实不是一种流。
安装入门
1. 首先全局安装gulp
$ npm install -g gulp
2. 作为项目的开发依赖安装(需要在开发项目的目录下安装)
$ npm install --save-dev gulp
3.在项目的根目录下创建一个名为gulpfile.js的文件
目录结构如下
project
│ README.md
│ gulpfile.js
│ package.json
│ package-lock.json
│
└───src
│ │ assets
│ │ js
│ │ page
│ │
│ └───scss
│ │ test.scss
│ │ ...
│
└───dist
│
└───css_output
│ test.css
4. 在gulpfile.js中编写你的任务
let gulp = require('gulp'),
sass = require('gulp-sass'); //SASS编译插件
gulp.task('default', function() {
return gulp.src('src/scss/**/*.scss')
.pipe(sass()) //通过gulp-sass插件将scss文件编译成css文件
.pipe(gulp.dest('dist/css_output'))
});
5. 运行gulp
$ gulp
API介绍
-
gulp.src(globs[, options])
说明:可以读取符合匹配规则路径下(包括数组形式)的文件,并将这些文件返回到一个流中,以便后续使用操作。
第一个参数类型可以是String或Array,表示所要读取的并且符合匹配规则的文件或数组的文件
第二个参数并不是必须的,类型是Object,表示一些参数的配置。通常我们选择默认配置即可
return: 返回的是一个Vinyl流,它可以被piped到别的插件中
备注:
在gulp4中gulp.src()接收的文件匹配字符串会顺序解析,所以你可以写成这样
gulp.src([ '.js', '!b.js', 'bad.js' ]) //表示匹配除了所有以b开头的JS文件但是除了bad.js
-
gulp.dest(paths[, options])
说明: 可以将文件写入到paths路径下,并且返回的还是一个流,可以继续操作使用。
第一个参数类型是String或function,表示的是文件将被写入的路径(输出目录)
第二个参数不是必须的,类型是Object,其中值得一提的是options.mode表示的是所创建的目录的权限,用八进制权限字符表示,默认值是077
return: 返回的是一个Vinyl流,它可以继续被piped到别的插件中
-
gulp.task(name[, deps], fn)
说明: 可以定义一个任务。在gulp3中,可以接受3个参数,在gulp4中,只能接受两个参数。
第一个参数类型是String,表示的是任务的名字,避免名字中带空格
第二个参数不是必须的,类型是Array,表示的是一个包含任务列表的数组,这些任务会在你当前任务运行之前完成,但并不能很好的控制它们的执行顺序。
第三个参数类型是function,表示的是定义该任务所要执行的一些操作
-
gulp.task(name, fn)
说明:这是在gulp4中的格式,不在接受任务列表的数组。但是可以通过别的方式更好的实现相同的功能
第一个参数类型是String,表示的是任务的名字,避免名字中带空格
第二个参数类型是function,表示的是定义该任务所要执行的一些操作。这个函数可以是匿名函数,也可以是在别的地方已经声明过的函数
备注:
gulp.task用字符串注册的任务必须是直接在命令行中调用的任务
gulp.task可以接受单参数语法,这个参数必须是一个命名函数,函数名会被作为任务名
添加了gulp.series和gulp.parallel方法来用于组合任务代替了以前使用任务列表数组的方式
demo
##在gulp3中定义
gulp.task(name, function() { ... });
gulp.task(name, ['task1', 'task2', 'task3'], function() { ... });
##在gulp4中定义
gulp.task(name, () => { ... });
gulp.task(name, gulp.series('task1', 'task2', 'task3')); //顺序执行
gulp.task(name, gulp.parallel('task1', 'task2', 'task3')); //并行执行
//当然gulp.series和gulp.parallel两者可以随意组合使用
-
gulp.watch(glob[, opts, cb])
说明:监听符合匹配规则路径下的文件变动,并在变动后执行callback里的内容
第一个参数类型是String或Array,表示指定具体监控哪些文件的变动。
第二个参数类型是Object,表示用来传给gaze的参数。通常无需配置,使用默认即可。
第三个参数cb(event)类型是Function,表示每次变动需要执行的callback。callback会被传入一个名为event的对象,这个对象描述了所监控到的变动。
event.type -- 发生变动的类型 added ,changed,deleted
event.path -- 触发了该事件的文件路径
demo
gulp.wathc('js/**/.js', function(event) {
console.log('File ' + event.path + ' was ' + event.type + ', running tasks...');
});
下面是在gulp4中新增的API:
-
gulp.series(fn)
说明:以串行的方式运行指定的任务,并会返回一个函数。
接受任意数量的参数,参数可以是已经定义了的任务名,也可以是函数。
由于它返回一个函数,因此它在调用时通常是作为参数传递给其他方法,比如gulp.task中使用它。
-
gulp.parallel(fn)
说明:以并行的方式运行指定的任务,并会返回一个函数。
接受任意数量的参数,参数可以是已经定义了的任务名,也可以是函数。
由于它返回一个函数,因此它在调用时通常是作为参数传递给其他方法,比如gulp.task中使用它。
- gulp.symlink() – 与dest相似,但是使用软连接形式
- gulp.lastRun(taskName[,timeResolution]) – 获得某任务上次成功运行的时间戳
- gulp.tree(options) – 返回一个数组,该数组由已定义的任务名字字符串所组成
- gulp.registry() – 获取或者设置任务名和任务函数之间的映射关系
心得
以上便是gulp的语法相关内容,包含gulp3和gulp4的相关内容。
但是私以为仅仅学会这些语法,不亲自去应用是无法真正掌握的,因为语法相对而言非常简单,gulp的关键是在它有许多丰富多彩的插件,我们如何去搭配配置使用它们,并应用到我们的项目中,才是我们应该去思考并实践的问题,所以,让我们去带着目的去实践吧!
gulp实践
目标需求:
自动添加CSS兼容性前缀,并且能将SASS文件编译成CSS文件
能监听文件变化,并且在文件变化后自动编译
在浏览器上实时刷新变化
gulpfile.js
/**
* 此为gulp4.0的配置文件
*/
var gulp = require('gulp'),
gutil = require('gulp-util'), //打印日志工具
clean = require('gulp-clean'), //清理文件工具
del = require('del'), //更好用的清理工具
htmlmin = require('gulp-htmlmin'), //HTML压缩
sass = require('gulp-sass'), //SASS编译
cleanCSS = require('gulp-clean-css'), //压缩CSS
autoprefixer = require('gulp-autoprefixer'), //CSS自动添加前缀
postcss = require('gulp-postcss'), //对css处理的插件系统
pxtorem = require('postcss-pxtorem'), //将px转成rem
inlineSource = require('gulp-inline-source'), //html外链文件复制到HTML
browserSync = require('browser-sync').create(), //浏览器实时刷新
reload = browserSync.reload,
fileName = "sakura-new-website",
srcDir = "src", //源文件存放路径
srcPath = {
scss: [srcDir + "/scss/**/*.scss"],
js: srcDir + "/**/*.js",
html: [
srcDir + "/**/*.html"
],
other: [srcDir + "/**/*+(png|jpg|gif)"]
},
buildDir = "dist", //编译后文件存放路径
buildPath = {
css: buildDir + "/css_output",
js: buildDir + "/js"
},
end = "";
//编译SCSS && 添加CSS前缀 && 将px转成rem
gulp.task('styles', function() {
var processors = [
pxtorem({
propList: ['*'],
selectorBlackList: ['ignore'],
replace: true,
mediaQuery: true,
minPixelValue: 1
})
];
return(
gulp
.src(srcPath.scss)
.pipe(sass().on("error", sass.logError))
.pipe(
autoprefixer({
browsers: ['last 4 versions'],
cascade: false
})
)
.pipe(postcss(processors))
.pipe(gulp.dest(buildPath.css))
.pipe(reload({ stream: true }))
);
});
/**
* 删除所有编译文件
*/
gulp.task('clean', function() {
return del([buildDir]);
});
/**
* 监听文件变化
*/
gulp.task('watch', function(done) {
gulp.watch(srcPath.scss, gulp.series('styles')).on(
'change', function(event) {
console.log('File ' + event.path + ' was ' + event.type + ', running tasks...');
done
}
);
gulp.watch(srcPath.html, reload).on(
'监听--HTML变化了--styles end',
done
);
gulp.watch(srcPath.js, reload).on(
'监听--JS变化了--styles end',
done
);
});
/**
* 浏览器实时刷新
*/
gulp.task('server', function() {
browserSync.init({
server: './'
});
});
/**
* gulp 默认指令
*/
gulp.task('default', gulp.series('clean', gulp.parallel('server', 'watch', 'styles')));
运行截图
$ gulp
编译文件对比
浏览器运行效果