gulp4入门教程

92 阅读5分钟

hi,在这里分享和记录一下 gulp 的基本使用,让我们对 gulp 有一个基本的了解,使我们遇到 gulp 搭建的第三方库或者项目时,不会变的手足无措。

介绍

gulp 是一个异步的,基于流的前端构建工具。
要安装 gulp,首先要确保你的电脑里已经安装了node,可以通过node -v查看你是否已经安装了 node 和你的 node 版本。

安装

全局安装 gulp 命令行工具:npm i -G gulp-cli
使用gulp命令的三种方式:

  1. 全局安装 gulp-cli,使用gulp --help查看和使用命令
  2. 安装 gulp,配置 package.json,使用 npm、yarn 或者 pnpm 运行
  3. 不安装 gulp-cli,使用npx gulp --help查看和使用命令

初始化项目:npm init -y

安装 gulp:npm i -D gulp

配置文件

创建 gulp 配置文件有两种方式:

  1. 创建 gulpfile.js 文件。
  2. 创建 gulpfile 文件夹,文件夹中创建 index.js 文件。

API

在此仅介绍几个常用 api 的基本用法,要了解详细内容请阅读 官网。 在此还得提一嘴 Vinyl 对象,Vinyl 对象就是 描述文件的元数据对象。globs 即是文件路径匹配规则。

  • src() 创建流,从文件系统中读取 vinyl 对象
  • dest() 将 vinyl 对象写入到文件系统的流
  • series() 串联任务,按顺序依次执行任务
  • parallel() 并行任务,同时执行的任务
  • watch() 监听 globs 发生更改时运行任务

创建、导出任务

在 gulpfile 文件中有三种 gulp 任务:

  1. 公开任务:通过 exports 导出,可以被gulp xxx任务名调用的任务。
  2. 私有任务:没有通过 exports 导出,不可以被gulp xxx任务名调用的任务。
  3. 组合任务:series() 和 parallel(),允许将多个独立的任务组合为一个更大的任务。也可以可以互相嵌套至任意深度。

注意:exports 默认将函数注册为任务。旧版本中,task()用来将函数注册为任务。

const { series, parallel } = require('gulp'); // series、parallel可以接受任意数量的任务
const publicTask = cb => cb();
const privateTask = cb => cb(); // 私有任务

exports.publicTask = publicTask; // 公开任务
exports.seriesTask = series(publicTask, privateTask); // 组合任务
exports.default = parallel(publicTask, series(publicTask, privateTask)); // 组合任务

/** 以下是运行gulp的结果 **/
[16:27:52] Starting 'default'...   // Starting 开始任务
[16:27:52] Starting 'publicTask'...
[16:27:52] Finished 'publicTask' after 1.03 ms // Finished 完成的任务和完成时间
[16:27:52] Starting 'publicTask'...
[16:27:52] Finished 'publicTask' after 750 μs
[16:27:52] Starting 'privateTask'...
[16:27:52] Finished 'privateTask' after 455 μs
[16:27:52] Finished 'default' after 4.99 ms

运行任务

gulp 运行任务同 gulp 命令的三种方式一样。以下仅使用一种方式举例:

gulp publicTask // 使用gulp运行指定任务
gulp // 使用gulp运行默认任务,即exports.default的任务

插件和api使用

启动服务

gulp-connect起本地服务

安装npm i -D gulp-connect,配置如下:

const { series } = require('gulp');
const connect = require('gulp-connect');

function serverTask(cb) {
  connect.server({
    name: 'demo', // 服务器启动、停止时,输出的名称
    root: 'dist', // 根路径,运行时默认打开的文件位置。可配置Array或String
    livereload: true, // 是否实时加载
    host: '127.0.0.1', // 主机号
    port: '8080', // 端口号
  })
  cb();
}

exports.default = series(serverTask);

运行 gulp 后就可以在控制台看到如下内容,就表示你的本地服务已经成功启动啦。 image.png

删除文件

del在下一次打包前删除上一次打包的文件

安装npm i -D del,配置如下:

const { src, dest, series } = require('gulp');

function deleteFile() {
  return import('del').then(({ deleteSync }) => deleteSync('dist/'))
}

exports.default = series(serverTask, deleteFile, buildHTML);

处理js文件

gulp-babel将ES6+代码转换为ES5
gulp-uglify压缩 js 代码

安装npm i -D gulp-babel @babel/core @babel/preset-env gulp-uglify配置如下:

const { src, dest, series, parallel } = require('gulp');
const connect = require('gulp-connect');
const babel = require('gulp-babel');
const uglify = require('gulp-uglify');

function buildJS() {
  return src('src/*.js') // 从文件系统中读取 globs 匹配的 vinyl 对象
  .pipe(babel({
    "presets": [ // 配置 babel 预设
      [
        "@babel/preset-env", { // 使用 @babel/preste-env 并配置参数
          "useBuiltIns": 'usage', // 指定模块导入模式
          "corejs": 3 // 指定 corejs 版本
        }
      ]
    ]
  }))
  .pipe(uglify({ // 压缩 js 代码
    mangle: {
      toplevel: true // 混淆变量名
    }
  }))
  .pipe(dest('dist/')) // 输出到 dist 目录
  .pipe(connect.reload()) // 热更新
}

exports.default = series(serverTask, deleteFile, parallel(buildHTML, buildJS));

运行 gulp,查看 dist 目录打包好的 js 文件如下: image.png

处理html文件

gulp-htmlmin压缩 html

安装npm i -S gulp-htmlmin,配置如下:

const { src, dest, series, parallel } = require('gulp');
const connect = require('gulp-connect');
const htmlmin = require('gulp-htmlmin');

function buildHTML() {
  return src('src/*.html') // 从文件系统读取 globs匹配的 vinyl 对象
  .pipe(htmlmin({
    collapseWhitespace: true, // 是否 折叠空格
    caseSensitive: true, // 是否 以区分大小写的方式区分属性
    collapseBooleanAttributes: true, // 是否 从布尔值中省略属性值
    removeAttributeQuotes: true, // 尽可能删除属性两边的引号
    removeComments: true, // 去除HTML注释
    removeEmptyAttributes: true, // 删除所有仅含空格值的属性
    removeEmptyElements: true, // 删除所有内容为空的属性
    minifyCSS: true, // 压缩内联css
    minifyJS: true, // 压缩内联js
  }))
  .pipe(dest('dist/')) // 将 vinyl 对象写入文件系统
  .pipe(connect.reload()) // 热更新
}

exports.default = series(serverTask, parallel(buildHTML, buildJS));

运行 gulp,查看 dist 目录打包好的 html 文件如下: image.png

处理scss文件

gulp-sass将 sass 文件转换为 css 文件
gulp-autoprefixer自动添加不同浏览器的 css 前缀,使用此插件需要在package.json 文件中添加"browserslist": "last 2 versions"
gulp-clean-css压缩 css

安装npm i -D gulp-sass gulp-autoprefixer gulp-clean-css,配置如下:

const { src, dest, series, parallel } = require('gulp');
const connect = require('gulp-connect');
const sasscss = require('gulp-sass')(require('sass'));
const autoprefixer = require('gulp-autoprefixer');
const cleancss = require('gulp-clean-css');

function buildCSS() {
  return src('src/*.scss')
  .pipe(sasscss()) // 转换 css
  .pipe(autoprefixer({
    cascade: false, // 补充前缀 是否 以级联的方式展示
  }))
  .pipe(cleancss()) // 压缩 css
  .pipe(dest('dist/'))
  .pipe(connect.reload()) // 热更新
}

exports.default = series(serverTask, parallel(buildCSS, buildHTML, buildJS));

监听文件

监听文件变化,更新对应打包文件。配置如下:

const { src, dest, series, parallel, watch } = require('gulp');

function watchFile(cb) {
  // watch 的 change 事件,监听文件变化,获取对应路径 执行对应操作
  watch(['src/**/*']).on('change', (path, stat) => {
    // 匹配路径调用对应的任务
    if (/\.html$/.test(path)) { // 匹配 html
      return buildHTML();
    }
    if (/\.scss$/.test(path)) { // 匹配 scss
      return buildCss();
    }
    if (/\.js$/.test(path)) { // 匹配 js
      return buildJS();
    }
  })
  cb(); // 没有任何返回,则需要调用cb结束当前任务
}

exports.default = series(serverTask, parallel(buildCSS, buildHTML, buildJS), watchFile);

大致就是酱子了。