自动化工具 Gulp

自动化工具 gulp


摘要

概念:gulp用于自动化开发流程。

理解:我们只需要编写任务,然后gulp帮我们执行

核心概念:

任务:通过定义不同的任务来组织你的构建流程。

管道:通过管道方式将文件从一个插件传递到下一个插件,从而进行一系列的处理。

插件:Gulp 社区提供了大量的插件,用于实现各种常见的任务,如文件压缩、CSS 预处理等。

Gulp和Webpack的区别:

gulp的核心理念是task runner:可以定义自己的一系列任务,等待任务被执行。

webpack的核心理念是module bundler:可以使用各种的loader来加载不同的模块,也可以使用各种各样的插件在webpack打包的生命周期完成其他的任务。




概念

**概念:**A toolkit to automate & enhance your workflow

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

解释:

Gulp 是一个流行的基于 JavaScript 的构建工具,用于自动化开发工作流程。它通过定义任务(tasks)来处理和转换项目中的文件,例如编译 Sass 或 LESS、压缩 JavaScript、优化图像等。Gulp 以其简单易用、插件丰富和速度快等特点受到许多前端开发者的欢迎。

image.png

核心概念:

任务(Tasks)

  • 在 Gulp 中,任务是执行特定操作的 JavaScript 函数,如编译代码、处理文件等。你可以通过定义不同的任务来组织你的构建流程。

管道(Pipes)

  • Gulp 利用 Node.js 的流(stream)机制,通过管道方式将文件从一个插件传递到下一个插件,从而进行一系列的处理。这种流式处理方式使得 Gulp 效率很高,不需要将文件全部加载到内存中。

插件(Plugins)

  • Gulp 社区提供了大量的插件,用于实现各种常见的任务,如文件压缩、CSS 预处理、文件合并等。每个插件通常只负责一种功能,这符合了 Unix 哲学“做好一件事”的原则。

Gulp和Webpack:

gulp的核心理念是task runner:可以定义自己的一系列任务,等待任务被执行。

基于文件Stream的构建流,我们可以使用gulp的插件体系来完成某些任务;

webpack的核心理念是module bundler

webpack是一个模块化的打包工具,可以使用各种各样的loader来加载不同的模块。

可以使用各种各样的插件在webpack打包的生命周期完成其他的任务。

gulp相对于webpack的优缺点:

  • gulp相对于webpack思想更加的简单、易用,更适合编写一些自动化的任务。

但是目前对于大型项目(Vue、React、Angular)并不会使用gulp来构建,比如默认gulp是不支持模块化的。




基本使用

安装

首先,安装gulp:

# 全局安装 
npm install gulp -g# 局部安装 
npm install gulp

其次,编写gulpfile.js文件,在其中创建一个任务:

gulpfile.js

const foo = (cb) => {console.log('第一个 gulp 任务')cb()
}module.exports = {foo
}

最后,执行gulp命令:

npx gulp foo

结果:

nathanchen@192 gulp % npx gulp foo
[10:00:14] Using gulpfile ~/Downloads/CoderWhy/17_Webpack工程化高级/code/Nathan/gulp/gulpfile.js
[10:00:14] Starting 'foo'...
第一个 gulp 任务
[10:00:14] Finished 'foo' after 1.25 ms


创建gulp的任务

每个gulp任务都是一个异步的JavaScript函数:

  • 此函数可以接受一个callback作为参数,调用callback函数那么任务会结束。
  • 或者是一个返回stream、promise、event emitter、child process或observable类型的函数;

任务可以是public或者private类型的:

公开任务(Public tasks):从 gulpfile 中被导出(export),可以通过 gulp 命令直接调用。

私有任务(Private tasks):被设计为在内部使用,通常作为 series() 或 parallel() 组合的组成部分。

补充:gulp4之前, 注册任务时通过gulp.task的方式进行注册的

gulp.task("bar", cb => {console.Log("bar任务");cb();
}

默认任务

我们可以编写一个默认任务:

module.exports.default = (cb) => {console.log('default task exec~')cb()
}

执行 gulp 命令:

nathanchen@192 gulp % npx gulp    
[10:08:03] Using gulpfile ~/Downloads/CoderWhy/17_Webpack工程化高级/code/Nathan/gulp/gulpfile.js
[10:08:03] Starting 'default'...
default task exec~
[10:08:03] Finished 'default' after 1.07 ms



gulp的任务组合

任务组合series和parallel:

通常一个函数中能完成的任务是有限的(放到一个函数中也不方便代码的维护),所以我们会将任务进行组合。gulp提供了两个强大的组合方法:

**series():**串行任务组合。 依次执行任务。

**parallel():**并行任务组合。同时执行任务。

Code:

//多个任务串行执行
const seriesTask = series(taskl, task2, task3)
//多个任务并行执行
const parallelTask = parallel(task1, task2, task3)

Case:

const { series, parallel } = require('gulp')const foo1 = (cb) => {setTimeout(() => {console.log('foo1 task exec~')cb()}, 1000)
}const foo2 = (cb) => {setTimeout(() => {console.log('foo1 task exec~')cb()}, 2000)
}const foo3 = (cb) => {setTimeout(() => {console.log('foo1 task exec~')cb()}, 3000)
}const seriesFoo = series(foo1, foo2, foo3)
const parallelFoo = parallel(foo1, foo2, foo3)module.exports = {seriesFoo,parallelFoo
}



gulp的文件操作

读取和写入文件

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

src()

src() 接受参数,并从文件系统中读取文件然后生成一个Node流(Stream),它将所有匹配的文件读取到内存中并通过流 (Stream)进行处理。由 src() 产生的流(stream)应当从任务(task函数)中返回并发出异步完成的信号。

dest()

dest() 接受一个输出目录作为参数,并且它还会产生一个 Node流(stream),通过该流将内容输出到文件中。

pipe()

流(stream)所提供的主要的 API 是 .pipe() 方法,pipe方法的原理是什么呢?

pipe方法接受一个 转换流(Transform streams)或 可写流(Writable streams)。

转换流或者可写流,在拿到数据后可以对数据进行处理,再次传递给下一个转换流或者可写流。

gulpfile.js

const { src, dest } = require('gulp')
const copyFile = () => {// 读取文件,写入文件// gulp 需要回调函数,而 pipe 返回的是一个 stream,所以这里直接return即可return src("./src/main.js").pipe(dest("./dist"))
}module.exports = {copyFile
}

res:

nathanchen@192 gulp % npx gulp copyFile
[10:33:57] Using gulpfile ~/Downloads/gulp/gulpfile.js
[10:33:57] Starting 'copyFile'...
[10:33:57] Finished 'copyFile' after 14 ms


glob文件匹配

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

glob的匹配规则如下:

  • (一个星号*):在一个字符串中,匹配任意数量的字符,包括零个匹配;

    比如 '*.js'

  • (两个星号**):在多个字符串匹配中匹配任意数量的字符串,通常用在匹配目录下的文件;

    比如 'scripts/**/*.js'**表示匹配任意多个字符串,可以匹配 /scirpts/a/b/c.js

  • (取反!):

    由于 glob 匹配时是按照每个 glob 在数组中的位置依次进行匹配操作的。

    所以 glob 数组中的取反(negative)glob 必须跟在一个非取反(non-negative)的 glob 后面。

    第一个 glob 匹配到一组匹配项,然后后面的取反 glob 删除这些匹配项中的一部分。

    ['script/**/*.js', '!scripts/vendor/']



对文件进行转换

**需求:**如果在这个过程中,我们希望对文件进行某些处理,可以使用社区给我们提供的插件。

比如我们希望ES6转换成ES5,那么可以使用babel插件。

如果我们希望对代码进行压缩和丑化,那么可以使用uglify或者terser插件。

Case: babel 转换

pnpm add @babel/core gulp-babel @babel/preset-env -D

gulpfile.js

const { src, dest } = require('gulp')
const babel = require('gulp-babel')const copyFile = () => {// 读取文件,写入文件// gulp 需要回调函数,而 pipe 返回的是一个 stream,所以这里直接return即可return src("./src/**/*.js").pipe(babel({ presets: ["@babel/preset-env"] })).pipe(dest("./dist"))
}module.exports = {copyFile
}

结果:

转换前 main.js

const test = () => {console.log('test')
}test()

转换后main.js

"use strict";var test = function test() {console.log('test');
};
test();



Gulp的文件监听

watch

gulp api 中的 watch() 方法利用文件系统的监控程序(file system watcher)将 与进行关联。

Case: 监听内容的变化

gulpfile.js

const { src, dest, watch } = require('gulp')
const babel = require('gulp-babel')const copyFile = () => {return src("./src/**/*.js").pipe(babel({ presets: ["@babel/preset-env"] })).pipe(dest("./dist"))
}watch("./src/**/*.js", copyFile) // 监听module.exports = {copyFile
}

res: 修改 main.js ,会自动执行 copyFile

nathanchen@192 gulp % npx gulp copyFile
[11:04:12] Using gulpfile ~/Downloads/CoderWhy/17_Webpack工程化高级/code/Nathan/gulp/gulpfile.js
[11:04:12] Starting 'copyFile'...
[11:04:12] Finished 'copyFile' after 415 ms
[11:04:28] Starting 'copyFile'...
[11:04:28] Finished 'copyFile' after 23 ms



gulp 案例

**需求:**通过gulp来开启本地服务和打包。

打包html文件

**打包html文件:**使用gulp-htmlmin插件。

pnpm add gulp-htmlmin -D  

gulpfile.js

const { src, dest, watch } = require('gulp')
const htmlmin = require('gulp-htmlmin')const htmlTask = () => {// 读取文件,写入文件// gulp 需要回调函数,而 pipe 返回的是一个 stream,所以这里直接return即可return src("./src/**/*.html").pipe(htmlmin({ collapseWhitespace: true })).pipe(dest("./dist"))
}watch("./src/**/*.html", htmlTask)module.exports = {htmlTask
}

执行命令:

nathanchen@192 gulp % npx gulp htmlTask
[13:26:01] Using gulpfile ~/Downloads/CoderWhy/17_Webpack工程化高级/code/Nathan/gulp/gulpfile.js
[13:26:01] Starting 'htmlTask'...
[13:26:01] Finished 'htmlTask' after 17 ms

产物如下:

<!DOCTYPE html>
<html lang="en"><head><meta charset="UTF-8" /><meta name="viewport" content="width=device-width,initial-scale=1" /><title>Document</title></head><body><h1>Gulp</h1></body>
</html>


打包JavaScript文件

**打包JavaScript文件:**使用gulp-babel,gulp-terser插件。

安装插件:

pnpm add @babel/core gulp-babel @babel/preset-env -D
pnpm add gulp-terser -D

gulpfile.js

const babel = require('gulp-babel')
const terser = require('gulp-terser')const jsTask = () => {return src("./src/**/*.js").pipe(babel({ presets: ["@babel/preset-env"] })).pipe(terser({ toplevel: true })).pipe(dest('./dist'))
}module.exports = {jsTask
}


打包less文件

**打包less文件:**使用gulp-less插件

nathanchen@192 gulp % pnpm add gulp-less -D

gulpfile.js

const less = require('gulp-less')const lessTask = () => {return src("./src/**/*.less").pipe(less()).pipe(dest('./dist'))
}module.exports = {lessTask
}


html资源注入

  • 使用gulp-inject插件:将js和less注入到html文件中
 pnpm add gulp-inject -D
  • 使用browser-sync插件:文件更新,浏览器同步更新
 pnpm add browser-sync -D

操作:

执行 npm run build 进行打包,npm run serve开启服务器。

gulpfile.js

const { src, dest, watch, parallel, series } = require('gulp')
const htmlmin = require('gulp-htmlmin')
const babel = require('gulp-babel')
const terser = require('gulp-terser')
const less = require('gulp-less')
const inject = require('gulp-inject')
const browserSync = require('browser-sync')// 打包html
const htmlTask = () => {// 读取文件,写入文件// gulp 需要回调函数,而 pipe 返回的是一个 stream,所以这里直接return即可return src('./src/**/*.html').pipe(htmlmin({ collapseWhitespace: true })).pipe(dest('./dist'))
}// 打包js
const jsTask = () => {return src('./src/**/*.js').pipe(babel({ presets: ['@babel/preset-env'] })).pipe(terser({ toplevel: true })).pipe(dest('./dist'))
}// 打包less
const lessTask = () => {return src('./src/**/*.less').pipe(less()).pipe(dest('./dist'))
}// 在html中注入js和css
const injectTask = () => {return src('./dist/**/*.html').pipe(inject(src(['./dist/**/*.css', './dist/**/*.js']), { relative: true })).pipe(dest('./dist'))
}// 开启本地服务
const bs = browserSync.create()
const serve = () => {// 进行监听watch('./src/**', buildTask)bs.init({port: 8080,open: true,files: './dist/*',server: {baseDir: './dist'}})
}// 创建项目构建的任务
const buildTask = series(parallel(htmlTask, jsTask, lessTask), injectTask)
const serveTask = series(buildTask, serve)module.exports = {buildTask,serveTask
}

package.json

{..."scripts": {"build": "gulp buildTask","serve": "gulp serveTask"},...
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/diannao/60592.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

大华Android面试题及参考答案

请解释 Service 和 IntentService 之间的区别。 Service 是 Android 中的一种组件,用于在后台执行长时间运行的操作,不提供用户界面。它可以通过 startService () 或者 bindService () 方法来启动。当通过 startService () 启动时,服务会一直运行直到自己停止或者被系统回收…

探索 Seata 分布式事务

Seata(Simple Extensible Autonomous Transaction Architecture)是阿里巴巴开源的一款分布式事务解决方案,旨在帮助开发者解决微服务架构下的分布式事务问题。它提供了高效且易于使用的分布式事务管理能力,支持多种事务模式,确保数据的一致性和完整性。 以下是 Seata 的一…

【QT常用技术讲解】优化网络链接不上导致qt、qml界面卡顿的问题

前言 qt、qml项目经常会涉及访问MySQL数据库、网络服务器&#xff0c;并且界面打开时的初始化过程就会涉及到链接Mysql、网络服务器获取数据&#xff0c;如果网络不通&#xff0c;卡个几十秒&#xff0c;会让用户觉得非常的不爽&#xff0c;本文从技术调研的角度讲解解决此类问…

探索美赛:从准备到挑战的详细指南

前言 美国大学生数学建模竞赛&#xff08;MCM/ICM&#xff09;&#xff0c;简称“美赛”&#xff0c;是全球规模最大的数学建模竞赛之一。它鼓励参赛者通过数学建模来解决现实世界中的复杂问题&#xff0c;广受世界各地大学生的欢迎。本文将详细介绍美赛的全过程&#xff0c;从…

selenium 控制内嵌table滚动条的方法

selenium 控制内嵌table滚动条的方法 我们经常会遇到selenium 无法捕获到对应元素的问题&#xff0c;其中有一个原因是由于页面中存在滚动条&#xff0c;而需要操作的元素需要滑动滚动条后才能捕获到。 之前有使用过如下方式&#xff1a; document.getElementById(id).scrollT…

编程之路,从0开始:知识补充篇

Hello大家好&#xff0c;很高兴我们又见面了&#xff01; 给生活添点passion&#xff0c;开始今天的编程之路&#xff01; 这一篇我们来补充一下在之前篇目没讲到的知识&#xff0c;并结合一些码友的私信提问和我在编程中遇到的问题&#xff0c;做一些易错点或易混点的讲解。 …

C语言中,让人又爱又恨的字符串编码

引言 在C语言的世界里&#xff0c;字符串编码是一个让人既爱又恨的话题。 所有的打印信息&#xff0c;都是以字符串输出的。但是&#xff0c;大家在编码的时候&#xff0c;经常会遇到一些情况&#xff0c;稍不注意&#xff0c;就会导致显示出乱码&#xff0c;到了客户那里&…

Javaweb—Ajax与jQuery请求

文章目录 十一.Javaweb—Ajax与jQuery请求11.1 异步/同步请求11.2 异步请求案例案例一&#xff1a;案例二&#xff1a; 十一.Javaweb—Ajax与jQuery请求 Ajax: 全称Asynchronous JavaScript And XML&#xff0c;异步的JavaScript和XML。 11.1 异步/同步请求 【往期文章】 同…

单片机中的BootLoader(重要的概念讲解)

文章目录 一、链接地址和执行地址1. 链接地址(Load Address)2. 执行地址(Execution Address)链接地址与执行地址的关系实际工作流程总结二、相对跳转和绝对跳转1. 相对跳转(Relative Jump)2. 绝对跳转(Absolute Jump)3. `BX` 和 `BL` 指令总结三、散列文件1. 散列文件的…

macOS解决U盘装完系统容量变小的问题

发现原来256GB容量的U盘在mac电脑上只显示34GB&#xff0c;想起来之前用该U盘装过系统&#xff0c;最终搜到了以下解决方案&#xff0c;在此记录&#xff1a; (1) 查看盘符列表&#xff0c;找到需要格式化的U盘&#xff0c;假设为disk4 diskutil list(2) 卸载分区disk4 disk…

Linux 系统管理和监控命令---- auditctl命令

文章目录 基本语法常用参数和选项添加规则删除规则查看规则控制审计系统其他选项 使用示例启用审计系统禁用审计系统添加文件监视规则删除文件监视规则添加系统调用规则删除系统调用规则列出当前的审计规则 结合 ausearch 和 aureport查询审计日志生成审计报告 总结 auditctl 是…

知识图谱6:neo4j查询语句

neo4j增删改查 常见查询语句 1、查询所有节点和关系 //查询所有节点和关系 MATCH (n)-[r]->(m) RETURN n, r, m 2、查询某个知识图谱的全部 3、查询 MATCH (n:zhongyao {name: "艾虎"})-[r]->(m) RETURN n, r, m4、统计 // 查询边的个数 MATCH ()-[r]->…

【计算机网络】UDP网络程序

一、服务端 1.udpServer.hpp 此文件负责实现一个udp服务器 #pragma once#include <iostream> #include <string> #include <cstdlib> #include <cstring> #include <functional> #include <strings.h> #include <unistd.h> #incl…

【027B】基于51单片机模拟电梯(点阵)【Proteus仿真+Keil程序+报告+原理图】

☆、设计硬件组成&#xff1a;51单片机最小系统8*8点阵显示按键设置LED灯。 1、设计采用STC89C51/52、AT89C51/52、AT89S51/52作为主控芯片&#xff1b; 2、采用8*8点阵显示楼层和电梯运作&#xff08;上升、下降&#xff09;指示&#xff0c;同时具有八个楼层指示灯&#xf…

nginx openresty lua-resty-http 使用的一些问题记录

需求背景 需求是使用 nginx 做一个 https 服务的代理 nginx 收到 http 请求后&#xff0c;需要修改 body 中的某些参数值&#xff0c;然后将修改后的数据发送到目标服务器&#xff08;https&#xff09; 本来以为很简单的需求&#xff0c;结果中间出现了不少岔子&#xff0c;这…

vue2+ element ui 集成pdfjs-dist

目录 1. 下载Pdf.js1.1 下载1.2 修改配置1.2.1 将pdfjs-3.8.162-dist复制到项目中1.2.2 解决跨域问题1.2.3 将pdf.worker.js文件复制到public目录下1.2.4 安装 pdfjs-dist1.2.5 前端vue代码(示例) 3. 参考资料 1. 下载Pdf.js 1.1 下载 下载链接&#xff08;官方&#xff09;需…

「Mac玩转仓颉内测版2」入门篇2 - 编写第一个Cangjie程序

本篇详细介绍在Mac系统上创建首个Cangjie项目并编写、运行第一个Cangjie程序的全过程。内容涵盖项目创建、代码编写、程序运行与调试&#xff0c;以及代码修改后的重新运行。通过本篇&#xff0c;掌握Cangjie项目的基本操作&#xff0c;进一步巩固开发环境的配置&#xff0c;迈…

@ComponentScan 和 @SpringBootApplication 同时使用出现问题

1 同时使用ComponentScan和SpringBootApplication&#xff0c;会导致SpringBootApplication所带的注解失效&#xff0c;请注意这个问题。我在使用mybatis时出现了找不到bean的问题&#xff0c;使用了ComponentScan导致Controller没有扫描到。 2 在springboot下使用mybatis时&a…

接单渠道,程序员看这篇就够了。

接单、兼职&#xff0c;有团队没单子&#xff1f;僧多粥少&#xff0c;苦矣。 很多程序员&#xff0c;有时间、有技术&#xff0c;有steam&#xff08;咳咳&#xff0c;不对&#xff0c;是team&#xff09;。但是&#xff0c;可能还是挣不到什么钱&#xff0c;何也&#xff1f…

【深度学习】使用硬件加速模型训练速度

一、 单机器单GPU 特点 配置简单&#xff1a;无需多 GPU 或分布式环境的复杂配置&#xff0c;适合资源有限的场景。适合小规模模型&#xff1a;对于计算量不大的模型&#xff08;如中小型 CNN、RNN&#xff09;&#xff0c;单 GPU 可以处理大多数常见任务。 优势 简单易用&…