Gulp浅应用

69 阅读6分钟

什么是Gulp

一个工具包,可以帮你自动化和增加你的工作流

Gulp和Webpack

Gulp

gulp的核心理念是task runner

  1. 可以定义自己的一系列任务,等待任务被执行
  2. 基于文件Stream的构建流
  3. 我们可以使用gulp的插件体系来完成某些任务

Webpack

webpack的核心理念是module bundler

  1. webpack是一个模块化的打包工具
  2. 可以使用各种各样的loader来加载不同的模块
  3. 可以使用各种各样的插件在webpack打包的生命周期完成其他的任务

Gulp优缺点

  1. gulp相对于webpack思想更加的简单、易用,更适合编写一些自动化的任务
  2. 目前对于大型项目(VueReactAngular)并不会使用gulp来构建,比如默认gulp是不支持模块化的

Gulp基本使用

安装

//1.安装gulp脚手架

npm install --global gulp-cli

//2.创建文件夹gulp-demo

mkdir gulp-demo

//3.进入文件夹

cd gulp-demo

//4.初始化项目

npm init

创建gulp任务

  1. 每个gulp任务都是一个异步的JavaScript函数
    1. 此函数可以接受一个callback作为参数,调用callback函数那么任务会结束;
    2. 或者是一个返回streampromiseevent emitterchild processobservable类型的函数;
  2. 任务可以是public或者private类型的
    1. 公开任务(Public tasks)gulpfile 中被导出(export),可以通过 gulp 命令直接调用
    2. 私有任务(Private tasks) 被设计为在内部使用,通常作为series()parallel() 组合的组成部分;

gulpfile.js

在项目根目录创建个gulpfile.js文件,执行gulp命令后,gulp会去读取gulpfile.js文件,这是gulp的入口文件,所有的指令逻辑处理都在此文件中进行。

当项目体量过大时,可以在根目录内创建个gulpfile.js文件夹,文件夹内部创建index.js,可以在index.js中引入不同的处理模块.

在以前的版本中都是通过gulp.task来创建不同的任务,新版本主要通过exports.xxx来导出任务

function test(cb) {
 console.log('test')
 cb()
}

exports.test = test;

在控制台输入指令gulp test

如果将exports.test = test改为exports.default=test,在控制台直接输入gulp就可以直接构建了

任务组合series和parallel

gulp提供了两个强大的组合方法:

  1. series():串行任务组合
  2. parallel():并行任务组合
// 多个任务的串行执行
exports.seriesTask = series(task1, task2)

// 多个任务的并行执行
exports.parallelTask = parallel(task1, task2)

// 再次组合
exports.composeTask = series(exports.seriesTask, exports.parallelTask)

读取和写入文件

gulp 暴露了 src()dest() 方法用于处理计算机上存放的文件

  1. src() 接受参数,并从文件系统中读取文件然后生成一个Node流(Stream),它将所有匹配的文件读取到内存中并通过流(Stream)进行处理
  2. src() 产生的流(stream)应当从任务(task函数)中返回并发出异步完成的信号
  3. dest() 接受一个输出目录作为参数,并且它还会产生一个Node流(stream),通过该流将内容输出到文件中
exports.default = function() {
    return src('./index.html').pipe(dest('output/'))
}

流(stream)所提供的主要的 API.pipe() 方法 pipe方法接受一个 转换流(Transform streams)可写流(Writable streams),转换流或者可写流拿到数据之后可以对数据进行处理,再次传递给下一个转换流或者可写流;

glob文件匹配

src()方法接受一个 glob字符串或由多个 glob字符串组成的数组作为参数,用于确定哪些文件需要被操作(globglob 数组必须至少匹配到一个匹配项,否则 src() 将报错;)

glob的匹配规则:

  • (一个星号*):在一个字符串中,匹配任意数量的字符,包括零个匹配;'*.js'
  • (两个星号**):在多个字符串匹配中匹配任意数量的字符串,通常用在匹配目录下的文件;scripts/**/*.js
  • 取反['scripts/**/*.js', '!scripts/lib/']
    • 由于 glob 匹配时是按照每个 glob在数组中的位置依次进行匹配操作的
    • 所以 glob 数组中的取反(negative)glob 必须跟在一个非取反(non-negative)glob 后面
    • 第一个 glob 匹配到一组匹配项,然后后面的取反 glob 删除这些匹配项中的一部分

文件转换

如果在流传递过程中,我们希望对文件进行某些处理,可以使用插件

处理js

压缩js、创建sourcemap、重命名js

const {
  src, //gulp的内置方法
  dest
} = require('gulp');
//重命名js文件
const rename = require('gulp-rename');
const uglify = require('gulp-uglify');
const sourcemaps = require('gulp-sourcemaps');

function javascript() {
  return src(['src/js/*.js', '!src/js/*.min.js']) //1.创建一个流,从src读取
    //2.创建sourcemap
    .pipe(sourcemaps.init()) 
    //pipe为gulp内的一个方法
    //用于流之间的链接
    // 3. 压缩文件
    .pipe(uglify())
    //4.重命名,名称后加min.js
    .pipe(rename({
      extname: '.min.js'
    }))
    //5.将sourcemap写入
    .pipe(sourcemaps.write('./'))
    // 6.将文件写入build/js目录下
    .pipe(dest('build/js'))
}

exports.javascript = javascript;

控制台输入指令gulp javascript

build/js下会生成两个文件index.min.js 以及index.min.js.map

处理css

压缩css、创建sourcemap、重命名css

const {
  src,
  dest
} = require('gulp');
const minifyCSS = require('gulp-clean-css');
const sourcemaps = require('gulp-sourcemaps');
const autoprefixer = require('gulp-autoprefixer');

function css() {
  return src('src/css/*.css') //1.流入口文件
    //2.创建sourcemap
    .pipe(sourcemaps.init())
    //3.自动添加浏览器前缀
    .pipe(autoprefixer())
    // 4.压缩css
    .pipe(minifyCSS())
    //5.写入sourcemap
    .pipe(sourcemaps.write('./'))
    //6.写入文件
    .pipe(dest('build/css'))
}

exports.css = css;

控制台输入指令gulp css

build/js下会生成两个文件index.min.css 以及index.min.css.map

处理less

const {
  src,
  dest
} = require('gulp');
const gulpLess = require('gulp-less');
const minifyCss = require('gulp-clean-css')
const sourcemaps = require('gulp-sourcemaps');
const rename = require('gulp-rename');

function less() {
  return src('src/less/**.less') //1.创建输入流
    //2.创建sourcemap
    .pipe(sourcemaps.init())
    //3.less转为css
    .pipe(gulpLess())
    //4.压缩css
    .pipe(minifyCss())
    //5.修改名称
    .pipe(rename({extname: '.min.css'}))
    //6.写入sourcemap
    .pipe(sourcemaps.write('./'))
    //7.写入文件
    .pipe(dest('build/less'))
}

exports.less = less;

处理图片

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

function image() {
  return src('src/images/*.*') // 1. 创建输入流
    // 2. 压缩图片
    .pipe(imagemin({
      progressive: true
    }))
    // 3. 写入文件
    .pipe(dest('build/images'))
}

exports.image = image;

控制台输入指令gulp image

[17:00:07] Using gulpfile F:\gulp-demo\gulpfile.js
[17:00:07] Starting 'image'...
[17:00:19] gulp-imagemin: Minified 3 images (saved 449 kB - 35.5%)
[17:00:19] Finished 'image' after 12 s

可以看到图片的压缩比例

静态服务器

const browserSync = require("browser-sync").create();

function browser() {
  browserSync.init({
    server: {
      baseDir: "./dist",
    },
  });
  // next
}

exports.dev = series(browser)

文件监听

gulp api 中的 watch() 方法主要利用文件系统的监控程序(file system watcher)

const { watch } = require('gulp')

const task = function() {
    return src('./scr/*.js')
           .pipe(babel({presets: ['@babel/preset-env']}))
           .pipe(terser())
           .pipe('./output')
}

watch('./src/js/*.js', task)