gulp入门-gulpfile文件

gulp是什么?

gulp是自动化构建工具,主要用来设定程序自动处理静态资源的工作,它将开发流程中让人痛苦或耗时的任务自动化,从而减少你所浪费的时间、创造更大价值。也就是说它可以帮助你压缩文件,检查语法,打包项目等。

开始使用

全局安装

npm i gulp -g
# 同样,也可以按官网描述使用 npm install --global gulp-cli 安装

这里假设你已经有了一个现成的项目。

依赖安装

在项目根目录下执行以下命令安装gulp。

npm i gulp --save-dev

创建文件

在项目根目录下创建一个gulpfile.js文件(或者Gulpfile.js,执行命令时会自动去找这个文件),并在文件中输入以下内容。

const defaultTask = cd => {
cd()
}

exports.default = defaultTask

执行

在项目根目录下执行以下命令使用gulp。

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
#执行公有任务task2
gulp task2

处理文件

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()) // 清理dist文件夹下所有的文件和文件夹
}

exports.cleanDir = cleanDir
// gulp 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 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 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 copyHtmlFile

gulp-rename – 重命名文件

参数

参数详见gulp-rename

当接收参数为Object时,常用的参数如下

{
dirname: "main/text/ciao", // 相对路径
basename: "aloha", // 文件名
prefix: "bonjour-", // 文件名前缀
suffix: "-hola", // 文件名后缀
extname: ".md" // 文件扩展名
}

// /main/text/ciao/bonjour-aloha-hola.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 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')) // 默认为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 copyJsFile

gulp-concat – 文件合并

注意

合并顺序会按照src()中参数的顺序进行合并,所以当文件之间有互相依赖时,需要特别注意其顺序。

参数

可只接收一个String类型参数作为文件名。

concat('app.js')

可同时接收两个参数,第一个String类型作为文件名,第二个Object类型为合并的配置。

concat('app.js', {
newLine: ';', // 新一行开头加一个';',默认为'\n'
})

可只接收一个Object类型参数作为配置项。即描述文件的元数据对象,参见vinyl

concat({
cwd?: string; // 文件的当前工作目录
base?: string; // 用于计算relative属性。通常是在这里开始的。
path?: string; // 文件的完整路径。
stat?: {
dev?: number; // 包含文件的设备的数字标识符。
ino?: number; // 文件系统特定的文件索引节点编号。
mode?: number; // 描述文件类型和模式的位字段。
nlink?: number; // 文件存在的硬链接数。
uid?: number; // 拥有该文件(POSIX)的用户的数字型用户标识符。
gid?: number; // 拥有该文件(POSIX)的群组的数字型群组标识符。
rdev?: number; // 如果文件表示一个设备,则此值为数字型设备标识符。
size?: number; // 文件的大小(以字节为单位)。
blksize?: number; // 用于 I/O 操作的文件系统块的大小。
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 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
// gulp 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中文网

文章作者: JaCo Wu
文章链接: https://jacokwu.cn/blog/2020/11/17/gulp入门-gulpfile文件/
版权声明: 本博客所有文章除特别声明外,均采用 CC BY-NC-SA 4.0 许可协议。转载请注明来自 JaCo Wu的博客