gulp是什么?
gulp是自动化构建工具,主要用来设定程序自动处理静态资源的工作,它将开发流程中让人痛苦或耗时的任务自动化,从而减少你所浪费的时间、创造更大价值。也就是说它可以帮助你压缩文件,检查语法,打包项目等。
开始使用
全局安装
这里假设你已经有了一个现成的项目。
依赖安装
在项目根目录下执行以下命令安装gulp。
创建文件
在项目根目录下创建一个gulpfile.js
文件(或者Gulpfile.js
,执行命令时会自动去找这个文件),并在文件中输入以下内容。
const defaultTask = cd => { cd() }
exports.default = defaultTask
|
执行
在项目根目录下执行以下命令使用gulp。
可以看到以下执行结果。
[16:13:03] Using gulpfile D:\web-github\gulp-test-demo\gulpfile.js [16:13:03] Starting 'default'... [16:13:03] Finished 'default' after 5.21 ms
|
基本构成
接下来我们开始编写这个文件,让它去自动执行我们需要操作的任务。
创建任务
gulp中的任务分为公有任务(Public tasks)和私有任务(Private tasks)。其中公有任务可以直接通过gulp
命令去调用,而私有任务通常作为子任务,在内部使用。
这里需要先了解两个API – series()
和parallel()
(见4.1 - 4.2)。
创建一个任务就是创建一个函数,而公有任务与私有任务之间的区别就是是否导出。这里我们创建两个空任务。
const { series } = require('gulp') const task1 = cb => cb() const task2 = cb => cb() exports.task2 = task2 exports.default = series(task1, task2)
|
在上面的代码中,参数cb
是一个回调函数,执行这个参数表示任务执行结束,也就是任务完成通知,任务完成通知不再做详细介绍。
对于上面导出的任务可以通过以下命令执行。
处理文件
gulp的核心就是处理文件,它暴露了 src()
和 dest()
方法用于处理计算机上存放的文件。
src()
src()
接受 glob
参数,并从文件系统中读取文件然后生成一个 Node
流(stream)。它将所有匹配的文件读取到内存中并通过流(stream)进行处理。所以src()
的返回值拥有Node的Stream对象的属性和方法。
经由src()
返回的值常用的一个API是pipe()
方法,官网的介绍是:用于连接转换流(Transform streams)或可写流(Writable streams)。简单地说pipe()
就是一个管道用来传输流对象,然后在传输的过程中可以接收一个数据写入的目标,用来处理流对象,可无限链式调用。或者也可以使用pipeline()
方法,类似于pipe()
,传入多个参数,按顺序处理流对象。
dest()
dest()
接受一个输出目录作为参数,并且它还会产生一个 Node
流(stream),通常作为终止流(terminator stream)。当它接收到通过管道(pipeline)传输的文件时,它会将文件内容及文件属性写入到指定的目录中。
打包文件
首先我们应该找到所有我们要打包的文件。
const jsFilePath = [ 'src/*.js' ]
const cssFilePath = [ 'src/*.css' ]
const htmlFilePath = [ 'src/*.html' ]
const staticFilePath = [ 'src/images/*.*' ]
|
然后我们需要将这些文件全部复制到我们的打包文件夹下面。
const { series, src, dest } = require('gulp')
const copyJsFile = () => { return src(jsFilePath).pipe(dest('dist/js')) }
const copyCssFile = () => { return src(cssFilePath).pipe(dest('dist/css')) }
const copyHtmlFile = () => { return src(htmlFilePath).pipe(dest('dist')) }
const copyStaticFile = () => { return src(staticFilePath).pipe(dest('dist/static')) }
exports.default = series(copyJsFile, copyCssFile, copyHtmlFile, copyStaticFile)
|
执行gulp
命令就可以看到所有你想要打包的文件都已经在项目根目录下的dist
文件夹内了。这里需要注意的是,因为打包后文件路径可能会发生变化,所以在写路径相关的代码时应以打包后的路径为准。
使用插件
先介绍一下使用插件,在文件的编写过程中,插件是必不可少的,首先说几个比较常用的插件。
gulp-clean – 清理文件和文件夹
参数
force: Boolean 清理当前工作区之外(等同于../)的安全文件或文件夹
|
用法
const clean = require('gulp-clean')
const cleanDir = () => { return src(['dist/*']).pipe(clean()) }
exports.cleanDir = cleanDir
|
我们可以通过阻止访问文件来来提示清理的速度,src(['dist/*'], { read: false }).pipe(clean())
。
gulp-uglify – 压缩js文件
参数
参数详见UglifyJS2。
需要注意的是,其中sourceMap
不可用。
ie8 Boolean 是否支持ie8,默认false keep_fnames Boolean 是否保留函数名,默认false output Object 指定输出选项,默认null webkit Boolean 是否启用Safari / WebKit错误的解决方法,默认false
|
用法
const uglify = require('gulp-uglify')
const copyJsFile = () => { return src('src/*.js') .pipe(uglify()) .pipe(dest('dist/js')) }
exports.copyJsFile = copyJsFile
|
gulp-clean-css – 压缩css文件
参数
参数详见clean-css。
compatibility String 控制使用的兼容方式,默认*(ie10+) format Boolean 控制输出css格式,默认false inline Boolean 控制 @import 内联规则,默认false rebase Boolean 控制URL重新定位,默认true rebaseTo String 控制所有URL都重新定位到的目录,最有可能是输出文件所在的目录;默认为当前目录
|
用法
const cleanCss = require('gulp-clean-css')
const copyCssFile = () => { return src('src/*.css') .pipe(cleanCss()) .pipe(dest('dist/css')) }
exports.copyCssFile = copyCssFile
|
gulp-htmlmin – 压缩html文件
参数
参数详见html-minifier。
collapseWhitespace Boolean 折叠节点之间的空白,就是压缩文件,默认false removeComments Boolean 删除注释,默认false removeAttributeQuotes Boolean 尽可能删除属性周围的引号,默认false removeEmptyAttributes Boolean/Function 删除所有值为空的属性,默认false removeEmptyElements Boolean 删除所有内容为空的元素,默认为false collapseBooleanAttributes Boolean 省略值为布尔类型的属性值, 默认false removeScriptTypeAttributes Boolean type="text/javascript"从script标签中删除。其他type属性值保持不变,默认false removeStyleLinkTypeAttributes Boolean type="text/css"从style和link标签中删除。其他type属性值保持不变,默认false minifyCSS Boolean/Object/Function 缩小样式元素和样式属性中的CSS,使用clean-css,默认false minifyJS Boolean/Object/Function 缩小脚本元素和事件属性中的JavaScript,使用UglifyJS,默认false minifyURLs Boolean/Object/Function 缩小各种属性中的URL,使用relatedurl,默认false
|
用法
const htmlmin = require('gulp-htmlmin')
const copyHtmlFile = () => { return src('src/*.html') .pipe(htmlmin({ collapseWhitespace: true })) .pipe(dest('dist/html')) }
exports.copyHtmlFile = copyHtmlFile
|
gulp-rename – 重命名文件
参数
参数详见gulp-rename。
当接收参数为Object
时,常用的参数如下
{ dirname: "main/text/ciao", basename: "aloha", prefix: "bonjour-", suffix: "-hola", extname: ".md" }
|
用法
const rename = require('gulp-rename')
const copyJsFile = () => { return src(jsFilePath) .pipe(uglify()) .pipe(rename({suffix: '.min'})) .pipe(dest('dist/js')) }
exports.copyJsFile = copyJsFile
|
gulp-jshint – 代码检查
注意
此插件基于jshint,需同时安装jshint才可使用。
参数
参数详见gulp-jshint。
jshint提供了一个方法可以用来输出检查结果。
jshint.reporter('default')
const stylish = require('jshint-stylish');
stuff .pipe(jshint()) .pipe(jshint.reporter(stylish))
stuff .pipe(jshint.reporter('default')) .pipe(jshint.reporter('fail'))
|
jshint还提供了方法可以让我们去检查html文件中的内联脚本
stuff .pipe(jshint.extract('auto|always|never')) .pipe(jshint()) .pipe(jshint.reporter('default'))
|
用法
const jshint = require('gulp-jshint')
const copyJsFile = () => { return src('src/*.js') .pipe(jshint()) .pipe(jshint.reporter('default')) .pipe(dest('dist/js')) }
exports.copyJsFile = copyJsFile
|
gulp-concat – 文件合并
注意
合并顺序会按照src()
中参数的顺序进行合并,所以当文件之间有互相依赖时,需要特别注意其顺序。
参数
可只接收一个String
类型参数作为文件名。
可同时接收两个参数,第一个String
类型作为文件名,第二个Object
类型为合并的配置。
concat('app.js', { newLine: ';', })
|
可只接收一个Object
类型参数作为配置项。即描述文件的元数据对象,参见vinyl
concat({ cwd?: string; base?: string; path?: string; stat?: { dev?: number; ino?: number; mode?: number; nlink?: number; uid?: number; gid?: number; rdev?: number; size?: number; blksize?: number; blocks?: number; atime?: Date; mtime?: Date; ctime?: Date; }; contents?: NodeJS.ReadableStream | Buffer; })
|
使用
const concat = require('gulp-concat')
const copyJsFile = () => { return src('src/*.js') .pipe(concat('app.js', { newLine: ';' })) .pipe(dest('dist/js')) }
exports.copyJsFile = copyJsFile
|
gulp-sass – 编译sass
插件基于node-sass
,需同时安装。
参数
参数与node-sass
一致。
使用
const sass = require('node-sass')
const copyScssFile = () => { return src('src/scss/*.scss') .pipe(sass().on('error', sass.logError)) .pipe(dest('dist/css'))
exports.copyScssFile = copyScssFile
}
|
API
series(…task)
series被用来将其他任务或者组合操作组合成为更大的组合操作。
参数
task: 任意数量的任务或者组合
用法
const { series } = require('gulp') const teask1 = cb => cb() const teask2 = cb => cb() exports.default = series(task1, task2)
|
parallel(…task)
parallel被用来将其他任务或者组合操作组合成为更大的组合操作。
参数
task: 任意数量的任务或者组合
用法
const { parallel } = require('gulp') const teask1 = cb => cb() const teask2 = cb => cb() exports.default = parallel(task1, task2)
|
与series的区别
series()
的最大特点是任务按顺序执行,而parallel()
通常以最大并发来运行任务。因其特性,在series()
中,当一个任务发生错误而中止时,后面的所有任务都将不再执行;在parallel()
中,当一个任务发生错误而中止时,后面的所有任务可能会执行完,也可能不会执行完。
参考
gulp.js中文文档
Node.js中文网