Gulp 入门

Avatar of Zell Liew
Zell Liew on

DigitalOcean 提供适合您旅程各个阶段的云产品。使用 $200 免费信用额度 开始您的旅程!

Gulp 是一个工具,可以帮助您完成 web 开发中的多种任务。它通常用于执行前端任务,例如

  • 启动 web 服务器
  • 在保存文件时自动重新加载浏览器
  • 使用 Sass 或 LESS 等预处理器
  • 优化 CSS、JavaScript 和图像等资源

重要说明! 本文是为 Gulp 3.x 编写的,但现在 Gulp 4.x 已发布并推荐使用。与任何主要版本更改一样,API 存在重大更改。如果您安装了 Gulp 4 并尝试执行本文中的一些操作,它们将无法正常工作。我们将在本文中添加一些备注以提醒您。 这是一个不错的 Gulp 4 启动程序。

这不是 Gulp 可以执行的操作的完整列表。如果您有足够的疯狂,甚至可以使用 Gulp 构建静态网站生成器(我曾经做过!)。因此,是的,Gulp 非常强大,但是如果您想创建自己的自定义构建流程,您必须学习如何使用 Gulp。

因此,这就是本文的目的。它可以帮助您掌握 Gulp 的基础知识,以便您可以开始自己探索其他一切。

在我们深入了解 Gulp 的工作原理之前,让我们先谈谈为什么您可能想要使用 Gulp 而不是其他类似的工具。

为什么选择 Gulp?

像 Gulp 这样的工具通常被称为“构建工具”,因为它们是用于运行构建网站任务的工具。当前最流行的两个构建工具是 Gulp 和 Grunt。(Chris 有一篇关于这里如何开始使用 Grunt 的文章)。当然还有其他工具。 Broccoli 专注于资产编译,这是最常见的构建工具任务之一。

已经有多篇文章介绍了 Grunt 和 Gulp 之间的区别,以及为什么您可能会选择其中一个而不是另一个。您可以查看这篇文章这篇文章这篇文章,如果您有兴趣了解更多。 Brunch 在其对资产的关注方面与它们类似,并且它捆绑了一些最常见的其他任务,例如服务器和文件监视器。

主要区别在于您如何使用它们配置工作流程。与 Grunt 相比,Gulp 配置往往更短、更简单。Gulp 的运行速度也更快。

现在让我们继续,了解如何使用 Gulp 设置工作流程。

我们正在设置的内容

在本教程结束时,您将拥有一个工作流程来执行我们在本文开头概述的任务

  • 启动 web 服务器
  • 将 Sass 编译为 CSS
  • 在您保存文件时自动刷新浏览器
  • 优化所有资源(CSS、JS、字体和图像)以供生产使用

您还将学习如何将不同的任务链接在一起,形成简单易懂且易于执行的命令。

让我们从将 Gulp 安装到您的计算机开始。

安装 Gulp

在安装 Gulp 之前,您需要在计算机上安装 Node.js(Node)。

如果您尚未安装 Node,您可以从Node 网站下载软件包安装程序获取它。

完成 Node 安装后,可以使用以下命令在命令行中安装 Gulp

$ sudo npm install gulp -g

注意:只有 Mac 用户需要 sudo 关键字。(查看 Pawel Grzybek 的第一条评论,如果您不想使用 sudo)。请记住,上面代码中的“$”只是代表命令提示符。这不是您实际运行的命令的一部分。

我们在这里使用的 npm install 命令是一个使用 Node Package Manager (npm) 将 Gulp 安装到您的计算机上的命令。

此命令中的 -g 标志告诉 npm 将 Gulp 全局安装到您的计算机上,这使您可以在系统上的任何位置使用 gulp 命令。

Mac 用户需要在命令中添加 sudo 关键字,因为他们需要管理员权限才能全局安装 Gulp。

现在您已经安装了 Gulp,让我们创建一个使用 Gulp 的项目。

创建一个 Gulp 项目

首先,我们将创建一个名为 project 的文件夹,作为我们本教程中的项目根目录。在该目录中运行 npm init 命令

# ... from within our project folder
$ npm init

npm init 命令为您的项目创建一个 package.json 文件,该文件存储有关项目的信息,例如项目中使用的依赖项(Gulp 是依赖项的一个示例)。

npm init 会提示您

创建 package.json 文件后,可以使用以下命令将 Gulp 安装到项目中

$ npm install gulp --save-dev

这次,我们正在将 Gulp 安装到 project 中,而不是全局安装它,这就是命令中存在一些差异的原因。

您会看到 sudo 关键字不再需要,因为我们不是全局安装 Gulp,所以 -g 也不需要。我们添加了 --save-dev,它告诉计算机将 gulp 作为 package.json 中的开发依赖项添加。

如果在命令执行完毕后检查项目文件夹,您应该会看到 Gulp 创建了一个 node_modules 文件夹。您还应该在 node_modules 中看到一个 gulp 文件夹。

我们几乎准备好开始使用 Gulp 了。在开始之前,我们需要明确我们将如何使用 Gulp 来完成项目,而其中的一部分是决定目录结构。

确定文件夹结构

Gulp 足够灵活,可以与任何文件夹结构一起使用。您只需要了解其内部工作原理,然后才能针对您的项目进行调整。

在本教程中,我们将使用通用 web 应用程序的结构

  |- app/
      |- css/
      |- fonts/
      |- images/ 
      |- index.html
      |- js/ 
      |- scss/
  |- dist/
  |- gulpfile.js
  |- node_modules/
  |- package.json

在此结构中,我们将使用 app 文件夹用于开发目的,而 dist(表示“分发”)文件夹用于包含生产站点的优化文件。

由于 app 用于开发目的,因此我们的所有代码都将放置在 app 中。

在进行 Gulp 配置时,我们需要牢记此文件夹结构。现在,让我们从在 gulpfile.js 中创建您的第一个 Gulp 任务开始,该文件存储所有 Gulp 配置。

编写您的第一个 Gulp 任务

使用 Gulp 的第一步是在 gulpfile 中require 它。

var gulp = require('gulp');

require 语句告诉 Node 在 node_modules 文件夹中查找名为 gulp 的包。找到包后,我们将它的内容分配给变量 gulp

现在,我们可以使用此 gulp 变量开始编写 gulp 任务。gulp 任务的基本语法是

gulp.task('task-name', async function() {
  // Stuff here
});

task-name 指的是任务的名称,该名称将在您想要在 Gulp 中运行任务时使用。您也可以在命令行中运行同一个任务,方法是编写 gulp task-name

为了测试它,让我们创建一个显示 Hello Zell!hello 任务。

gulp.task('hello', async function() {
  console.log('Hello Zell');
});

我们可以在命令行中使用 gulp hello 运行此任务。

$ gulp hello

命令行将返回一条显示 Hello Zell! 的日志。

Gulp 任务通常比这更复杂。它通常包含两个额外的 Gulp 方法,以及各种 Gulp 插件。

以下是一个真实任务的示例

gulp.task('task-name', async function () {
  return gulp.src('source-files') // Get source files with gulp.src
    .pipe(aGulpPlugin()) // Sends it through a gulp plugin
    .pipe(gulp.dest('destination')) // Outputs the file in the destination folder
})

如您所见,真实任务接受两个额外的 gulp 方法——gulp.srcgulp.dest

gulp.src 告诉 Gulp 任务要使用哪些文件来执行任务,而 gulp.dest 告诉 Gulp 在任务完成后将文件输出到哪里。

让我们尝试构建一个真实的任务,在这个任务中我们将 Sass 文件编译为 CSS 文件。

使用 Gulp 进行预处理

我们可以借助名为 gulp-sass 的插件在 Gulp 中将 Sass 编译为 CSS。您可以使用 npm install 命令将 gulp-sass 安装到您的项目中,就像我们之前对 gulp 所做的那样。

我们还想使用 --save-dev 标志来确保 gulp-sass 被添加到 package.json 中的 devDependencies 中。

$ npm install gulp-sass --save-dev

在我们能够使用该插件之前,我们必须从 node_modules 文件夹中 require gulp-sass,就像我们之前对 gulp 所做的那样。

var gulp = require('gulp');
// Requires the gulp-sass plugin
var sass = require('gulp-sass');

我们可以通过用 sass() 替换 aGulpPlugin() 来使用 gulp-sass。由于该任务旨在将 Sass 编译为 CSS,所以让我们将其命名为 sass

gulp.task('sass', async function(){
  return gulp.src('source-files')
    .pipe(sass()) // Using gulp-sass
    .pipe(gulp.dest('destination'))
});

我们需要向 sass 任务提供源文件和目标,以便任务能够正常工作,所以让我们在 app/scss 文件夹中创建一个 styles.scss 文件。该文件将被添加到 gulp.src 中的 sass 任务中。

我们希望将最终的 styles.css 文件输出到 app/css 文件夹,这将是 gulp.destdestination

gulp.task('sass', async function(){
  return gulp.src('app/scss/styles.scss')
    .pipe(sass()) // Converts Sass to CSS with gulp-sass
    .pipe(gulp.dest('app/css'))
});

我们希望测试 sass 任务是否按预期工作。为此,我们可以在 styles.scss 中添加一个 Sass 函数。

// styles.scss
.testing {
  width: percentage(5/7);
}

如果您在命令行中运行 gulp sass,您应该现在能够看到在 app/css 中创建了一个 styles.css 文件。此外,它还包含 percentage(5/7) 被计算为 71.42857% 的代码。

/* styles.css */
.testing {
  width: 71.42857%; 
}

这就是我们知道 sass 任务工作的方式!

有时我们需要能够将多个 .scss 文件同时编译为 CSS。我们可以借助 Node glob 来实现这一点。

FYI:Gulp-sass 使用 LibSass 将 Sass 转换为 CSS。它比基于 Ruby 的方法快得多。如果您愿意,您仍然可以使用 Gulp 中的 Ruby 方法,方法是使用 gulp-ruby-sassgulp-compass 代替。

Node 中的 Globbing

Glob 是用于文件的匹配模式,允许您将多个文件添加到 gulp.src 中。它类似于正则表达式,但专门用于文件路径。

当您使用 glob 时,计算机会检查文件名和路径以查找指定的模式。如果存在模式,则会匹配文件。

大多数使用 Gulp 的工作流程只需要 4 种不同的 globbing 模式

  1. *.scss* 模式是一个通配符,匹配当前目录中的任何模式。在这种情况下,我们正在匹配根文件夹(project)中以 .scss 结尾的任何文件。
  2. **/*.scss:这是 * 模式的更极端版本,它匹配根文件夹和任何子目录中以 .scss 结尾的任何文件。
  3. !not-me.scss! 表示 Gulp 应该从其匹配项中排除该模式,如果您需要从匹配模式中排除一个文件,这很有用。在这种情况下,not-me.scss 将被排除在匹配之外。
  4. *.+(scss|sass):加号 + 和括号 () 允许 Gulp 匹配多个模式,不同的模式用竖线 | 字符分隔。在这种情况下,Gulp 将匹配根文件夹中以 .scss.sass 结尾的任何文件。

既然我们了解了 globbing,我们可以用 scss/**/*.scss 模式替换 app/scss/styles.scss,该模式匹配 app/scss 或子目录中任何以 .scss 结尾的文件。

gulp.task('sass', async function() {
  return gulp.src('app/scss/**/*.scss') // Gets all files ending with .scss in app/scss and children dirs
    .pipe(sass())
    .pipe(gulp.dest('app/css'))
})

通过此更改,在 app/scss 中找到的任何其他 Sass 文件都将自动包含到 sass 任务中。如果您在项目中添加一个 print.scss 文件,您将看到 print.css 将在 app/css 中生成。

我们现在已经成功地使用单个命令将所有 Sass 文件编译为 CSS 文件。问题是,如果我们每次想要将 Sass 编译为 CSS 时都必须手动运行 gulp sass,它有什么用呢?

幸运的是,我们可以告诉 Gulp 在每次保存文件时自动运行 sass 任务,这是一个名为“观察”的过程。

观察 Sass 文件以进行更改

注意!Gulp Watch 是从 3.x 到 4.x 发生重大变化的事情之一。 查看文档.

Gulp 为我们提供了一个 watch 方法,该方法检查是否保存了一个文件。watch 方法的语法是

// Gulp 3.x watch syntax
gulp.watch('files-to-watch', ['tasks', 'to', 'run']);

// NOTE! Gulp 4.x watch syntax (all the rest of the examples would need to be like this for Gulp 4
gulp.watch('files-to-watch', gulp.series(['tasks', 'to', 'run']));

如果我们想要观察所有 Sass 文件,并在每次保存 Sass 文件时运行 sass 任务,我们只需用 app/scss/**/*.scss 替换 files-to-watch,用 ['sass'] 替换 ['tasks', 'to', 'run']

// Gulp watch syntax
gulp.watch('app/scss/**/*.scss', ['sass']); 

但更常见的是,我们希望一次观察不止一种类型的文件。为此,我们可以将多个观察进程组合到一个 watch 任务中

gulp.task('watch', async function(){
  gulp.watch('app/scss/**/*.scss', ['sass']); 
  // Other watchers
})

如果您现在运行 gulp watch 命令,您会看到 Gulp 立即开始观察。

并且它会在您保存 .scss 文件时自动运行 sass 任务。

让我们更进一步,借助 Browser Sync,让 Gulp 在我们保存 .scss 文件时重新加载浏览器。

使用 Browser Sync 进行实时重新加载

Browser Sync 通过启动一个 Web 服务器来帮助简化 Web 开发,该服务器帮助我们轻松地进行实时重新加载。它还具有其他功能,例如 同步多个设备上的操作

我们首先需要安装 Browser Sync

$ npm install browser-sync --save-dev

您可能已经注意到,我们在安装 Browser Sync 时没有 gulp- 前缀。这是因为 Browser Sync 与 Gulp 配合使用,所以我们不需要使用插件。

要使用 Browser Sync,我们必须 require Browser Sync。

var browserSync = require('browser-sync').create();

我们需要创建一个 browserSync 任务来使 Gulp 能够使用 Browser Sync 启动一个服务器。由于我们正在运行一个服务器,我们需要让 Browser Sync 知道服务器的根目录应该在哪里。在我们的例子中,它是 app 文件夹

gulp.task('browserSync', async function() {
  browserSync.init({
    server: {
      baseDir: 'app'
    },
  })
})

我们还必须稍微更改我们的 sass 任务,以便 Browser Sync 可以在每次运行 sass 任务时将新的 CSS 样式(更新 CSS)注入到浏览器中。

gulp.task('sass', async function() {
  return gulp.src('app/scss/**/*.scss') // Gets all files ending with .scss in app/scss
    .pipe(sass())
    .pipe(gulp.dest('app/css'))
    .pipe(browserSync.reload({
      stream: true
    }))
});

我们完成了配置 Browser Sync。现在,我们必须同时运行 watchbrowserSync 任务,才能进行实时重新加载。

在两个命令行窗口中分别运行 gulp browserSyncgulp watch 会很麻烦,所以让我们让 Gulp 同时运行它们,方法是告诉 watch 任务,在 watch 允许运行之前,必须完成 browserSync

我们可以通过向 watch 任务添加第二个参数来实现这一点。语法是

gulp.task('watch', ['array', 'of', 'tasks', 'to', 'complete','before', 'watch'], async function (){
  // ...
})

在这种情况下,我们添加了 browserSync 任务。

gulp.task('watch', ['browserSync'], async function (){
  gulp.watch('app/scss/**/*.scss', ['sass']); 
  // Other watchers
})

我们还希望确保 sasswatch 之前运行,这样每次我们运行 Gulp 命令时,CSS 已经是最新的了。

gulp.task('watch', ['browserSync', 'sass'], async function (){
  gulp.watch('app/scss/**/*.scss', ['sass']); 
  // Other watchers
});

现在,如果您在命令行中运行 gulp watch,Gulp 应该同时启动 sassbrowserSync 任务。当这两个任务都完成后,watch 将运行。

同时,指向 app/index.html 的浏览器窗口也会弹出。如果您更改 styles.scss 文件,您会看到浏览器会自动重新加载。

在我们结束这个实时重新加载部分之前,还有一件事。既然我们已经在观察 .scss 文件以进行重新加载,为什么不更进一步,在保存任何 HTML 或 JavaScript 文件时重新加载浏览器呢?

我们可以通过添加另外两个观察进程,并在保存文件时调用 browserSync.reload 函数来实现这一点

gulp.task('watch', ['browserSync', 'sass'], async function (){
  gulp.watch('app/scss/**/*.scss', ['sass']); 
  // Reloads the browser whenever HTML or JS files change
  gulp.watch('app/*.html', browserSync.reload); 
  gulp.watch('app/js/**/*.js', browserSync.reload); 
});

到目前为止,在本教程中,我们已经处理了三件事

  1. 启动用于开发的 Web 服务器
  2. 使用 Sass 预处理器
  3. 在每次保存文件时重新加载浏览器

让我们在下一节中介绍优化资产的部分。我们将从优化 CSS 和 JavaScript 文件开始。

优化 CSS 和 JavaScript 文件

当我们尝试优化 CSS 和 JavaScript 文件以供生产使用时,开发人员需要执行两个任务:缩小和合并。

开发人员在自动化此过程时遇到的一个问题是,很难按正确顺序合并脚本。

假设我们在 index.html 中包含了 3 个脚本标签。

  
  <script src="js/lib/a-library.js"></script>
  <script src="js/lib/another-library.js"></script>
  <script src="js/main.js"></script>

这些脚本位于两个不同的目录中。使用像 gulp-concatenate 这样的传统插件很难合并它们。

谢天谢地,有一个有用的 Gulp 插件 gulp-useref 可以解决这个问题。

Gulp-useref 通过查找以“<!–build:”开头并以“<!–endbuild–>”结尾的注释,将任意数量的 CSS 和 JavaScript 文件连接成单个文件。其语法如下:


... HTML Markup, list of script / link tags.

可以是 jscssremove。最好将 type 设置为你尝试连接的文件类型。如果你将 type 设置为 remove,Gulp 将删除整个构建块,而不会生成文件。

在这里指的是生成的文件的目标路径。

我们希望最终的 JavaScript 文件在 js 文件夹中生成,名为 main.min.js。因此,标记将是


<script src="js/lib/a-library.js"></script>
<script src="js/lib/another-library.js"></script>
<script src="js/main.js"></script>

现在让我们在 gulpfile 中配置 gulp-useref 插件。我们必须安装该插件并在 gulpfile 中引入它。

$ npm install gulp-useref --save-dev
var useref = require('gulp-useref');

设置 useref 任务与我们迄今为止完成的其他任务类似。以下是代码

gulp.task('useref', async function(){
  return gulp.src('app/*.html')
    .pipe(useref())
    .pipe(gulp.dest('dist'))
});

现在,如果你运行此 useref 任务,Gulp 将遍历 3 个脚本标签并将它们连接到 dist/js/main.min.js 中。

但是,该文件目前没有进行压缩。我们必须使用 gulp-uglify 插件来帮助压缩 JavaScript 文件。我们还需要一个名为 gulp-if 的第二个插件,以确保我们只尝试压缩 JavaScript 文件。

$ npm install gulp-uglify --save-dev 
// Other requires...
var uglify = require('gulp-uglify');
var gulpIf = require('gulp-if');

gulp.task('useref', function(){
  return gulp.src('app/*.html')
    .pipe(useref())
    // Minifies only if it's a JavaScript file
    .pipe(gulpIf('*.js', uglify()))
    .pipe(gulp.dest('dist'))
});

现在,只要你运行 useref 任务,Gulp 就会自动压缩 main.min.js 文件。

Gulp-useref 还有一个我尚未透露的巧妙之处,它会自动将“<!–build:”和“<!–endbuild–>”之间的所有脚本更改为指向 js/main.min.js 的单个 JavaScript 文件。

是不是很神奇?

我们也可以使用相同的方法连接任何 CSS 文件(如果你决定添加多个)。我们将遵循相同的步骤并添加 build 注释。




我们还可以压缩连接的 CSS 文件。我们需要使用一个名为 gulp-cssnano 的插件来帮助我们进行压缩。

$ npm install gulp-cssnano
var cssnano = require('gulp-cssnano');

gulp.task('useref', async function(){
  return gulp.src('app/*.html')
    .pipe(useref())
    .pipe(gulpIf('*.js', uglify()))
    // Minifies only if it's a CSS file
    .pipe(gulpIf('*.css', cssnano()))
    .pipe(gulp.dest('dist'))
});

现在,只要你运行 useref 任务,你就会得到一个优化的 CSS 文件和一个优化的 JavaScript 文件。

接下来,让我们优化图片。

优化图片

你可能已经猜到了,我们需要使用 gulp-imagemin 来帮助我们优化图片。

$ npm install gulp-imagemin --save-dev
var imagemin = require('gulp-imagemin');

我们可以使用 gulp-imagemin 来压缩 pngjpggif 甚至 svg。让我们为此优化过程创建一个 images 任务。

gulp.task('images', async function(){
  return gulp.src('app/images/**/*.+(png|jpg|gif|svg)')
  .pipe(imagemin())
  .pipe(gulp.dest('dist/images'))
});

由于不同的文件类型可以以不同的方式进行优化,因此你可能需要向 imagemin 添加选项来自定义如何优化每个文件。

例如,你可以通过将 interlaced 选项键设置为 true 来创建 隔行扫描 的 GIF。

gulp.task('images', async function(){
  return gulp.src('app/images/**/*.+(png|jpg|jpeg|gif|svg)')
  .pipe(imagemin({
      // Setting interlaced to true
      interlaced: true
    }))
  .pipe(gulp.dest('dist/images'))
});

如果你愿意,也可以尝试其他选项。

但是,优化图片是一个非常缓慢的过程,除非必要,否则你不想重复进行。为此,我们可以使用 gulp-cache 插件。

$ npm install gulp-cache --save-dev
var cache = require('gulp-cache');

gulp.task('images', async function(){
  return gulp.src('app/images/**/*.+(png|jpg|jpeg|gif|svg)')
  // Caching images that ran through imagemin
  .pipe(cache(imagemin({
      interlaced: true
    })))
  .pipe(gulp.dest('dist/images'))
});

我们几乎完成了优化过程。还有一个文件夹需要从 app 目录转移到 dist 目录,即字体目录。现在让我们来做这件事。

将字体复制到 Dist

由于字体文件已经过优化,所以我们不需要做任何其他事情。我们只需要将字体复制到 dist 目录中。

我们可以使用 Gulp 复制文件,方法是简单地指定 gulp.srcgulp.dest,而无需任何插件。

gulp.task('fonts', async function() {
  return gulp.src('app/fonts/**/*')
  .pipe(gulp.dest('dist/fonts'))
})

现在,只要你运行 gulp fonts,Gulp 就会将 app 中的 fonts 复制到 dist 中。

现在,gulpfile 中有 6 个不同的任务,每个任务都必须使用命令行单独调用,这有点麻烦,所以我们希望将所有任务绑定到一个命令中。

但是,在执行此操作之前,让我们看看如何自动清理生成的 files。

自动清理生成的 files

由于我们正在自动生成 files,因此我们希望确保不再使用的 files 不会在我们不知情的情况下保留在任何地方。

此过程称为清理(或简单来说,删除 files)。

我们必须使用 del 来帮助我们进行清理。

npm install del --save-dev
var del = require('del');

del 函数接受一组节点 glob,这些 glob 指示它要删除哪些文件夹。

使用 Gulp 任务进行设置与我们第一个“hello”示例几乎一样。

gulp.task('clean:dist', async function() {
  return del.sync('dist');
})

现在,只要运行 gulp clean:dist,Gulp 就会为你删除 dist 文件夹。

注意:我们不必担心删除 dist/images 文件夹,因为 gulp-cache 已经将图片的缓存存储在你的本地系统上了。

要清除本地系统的缓存,你可以创建一个名为 cache:clear 的单独任务

gulp.task(‘cache:clear’, async function (callback) {
return cache.clearAll(callback)
})

哇,真是一大堆。现在让我们将所有任务组合在一起!

组合 Gulp 任务

让我们总结一下我们所做的工作。到目前为止,我们已经创建了两个不同的 Gulp 任务集。

第一个集合用于开发过程,我们在此过程中将 Sass 编译为 CSS,监视更改,并相应地重新加载浏览器。

第二个集合用于优化过程,我们在此过程中准备好所有文件以用于生产网站。在此过程中,我们优化了 CSS、JavaScript 和图片等资产,并将字体从 app 复制到 dist

我们已经使用 gulp watch 命令将第一组任务组合到一个简单的流程中。

gulp.task('watch', ['browserSync', 'sass'], function (){
  // ... watchers
})

第二组包含我们需要运行以创建生产网站的任务。这包括 clean:distsassuserefimagesfonts

如果我们遵循相同的思路,就可以创建一个 build 任务将所有内容组合在一起。

gulp.task('build', [`clean`, `sass`, `useref`, `images`, `fonts`], async function (){
  console.log('Building files');
})

不幸的是,我们无法以这种方式编写 build 任务,因为 Gulp 会同时激活第二个参数中的所有任务。

userefimages 甚至 fonts 可能在 clean 完成之前完成,这意味着整个 dist 文件夹将被删除。

因此,为了确保清理在其他任务完成之前完成,我们需要使用一个名为 Run Sequence 的额外插件。

$ npm install run-sequence --save-dev

以下是使用运行序列执行任务序列的语法

var runSequence = require('run-sequence');

gulp.task('task-name', async function(callback) {
  runSequence('task-one', 'task-two', 'task-three', callback);
});

当调用 task-name 时,Gulp 将首先运行 task-one。当 task-one 完成后,Gulp 将自动启动 task-two。最后,当 task-two 完成后,Gulp 将运行 task-three

Run Sequence 还允许你同时运行任务,只要将它们放在数组中即可

gulp.task('task-name', async function(callback) {
  runSequence('task-one', ['tasks','two','run','in','parallel'], 'task-three', callback);
});

在这种情况下,Gulp 首先运行 task-one。当 task-one 完成后,Gulp 将同时运行第二个参数中的每个任务。第二个参数中的所有任务都必须完成,然后才能运行 task-three

因此,我们现在可以创建一个任务,确保 clean:dist 首先运行,然后运行所有其他任务

gulp.task('build', async function (callback) {
  runSequence('clean:dist', 
    ['sass', 'useref', 'images', 'fonts'],
    callback
  )
})

为了保持一致性,我们也可以使用第一组构建相同的序列。这次让我们使用 default 作为任务名称

gulp.task('default', async function (callback) {
  runSequence(['sass','browserSync', 'watch'],
    callback
  )
})

为什么是 default?因为当你有一个名为 default 的任务时,你只需键入 gulp 命令即可运行它,这样可以节省一些按键操作。

最后,这是一个 GitHub 仓库,其中包含我们完成的所有工作!

总结

我们已经学习了 Gulp 的绝对基础知识,并创建了一个工作流程,该流程能够将 Sass 编译为 CSS,同时监视 HTML 和 JS 文件的更改。我们可以使用命令行中的 gulp 命令运行此任务。

我们还构建了第二个任务 build,该任务为生产网站创建一个 dist 文件夹。我们已将 Sass 编译为 CSS,优化了所有资产,并将必要的文件夹复制到 dist 文件夹中。要运行此任务,我们只需在命令行中键入 gulp build 即可。

最后,我们有一个 clean 任务,可以清除生成的 dist 文件夹中的任何图片缓存,使我们能够删除任何无意中保留在 dist 中的旧 files。

到目前为止,我们已经创建了一个强大的工作流程,足以满足大多数 Web 开发人员的需求。我们还可以探索更多 Gulp 和工作流程,以使此过程更加完善。以下是一些供你参考的建议

用于开发

优化

  • 使用 unCSS 移除未使用的 CSS
  • 使用 CSSO 进一步优化 CSS
  • 使用 Critical 生成内联 CSS 以提升性能

除了开发或优化流程,还可以使用 gulp-jasmine 编写 JavaScript 单元测试,甚至使用 gulp-rync 自动将 dist 文件夹部署到生产服务器上。

如您所见,即使我们创建的工作流程做了很多事情,但还有很多事情可以做。创建适合您需求的工作流程非常令人兴奋且令人满足,但如果您是新手,则可能需要花费很多时间。

Gulp 的功能太多,无法在这篇博文中或一系列博文中全部涵盖。这就是我写一本关于 自动化工作流程 的书的原因,如果您有兴趣了解更多信息,欢迎您 免费获取十章 :)

请在下面的评论中告诉我您对这篇文章的感受!是的,如果您对工作流程有任何疑问,请随时 与我联系。我很乐意回复!