自动化工具 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.rhkb.cn/news/471410.html

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

相关文章

基于Spring Boot与Redis的令牌主动失效机制实现

目录 前言1. 项目结构和依赖配置1.1 项目依赖配置1.2 Redis连接配置 2. 令牌主动失效机制的实现流程2.1 登录成功后将令牌存储到Redis中2.2 使用拦截器验证令牌2.3 用户修改密码后删除旧令牌 3. Redis的配置与测试4. 可能的扩展与优化结语 前言 在现代Web系统中&#xff0c;用…

llama factory lora 微调 qwen2.5 7B Instruct模型

项目背景 甲方提供一台三卡4080显卡 需要进行qwen2.5 7b Instruct模型进行微调。以下为整体设计。 要使用 LLaMA-Factory 对 Qwen2.5 7B Instruct模型 进行 LoRA&#xff08;Low-Rank Adapters&#xff09;微调&#xff0c;流程与之前提到的 Qwen2 7B Instruct 模型类似。LoRA …

GPT-5 要来了:抢先了解其创新突破

Microsoft 的工程师计划于 2024 年 11 月在 Azure 上部署 Orion (GPT-5)。虽然这一版本不会向公众开放&#xff0c;但其上线被视为人工智能领域的一个重要里程碑&#xff0c;并将产生深远的影响。 文章目录 GPT-5 真的要来了GPT-4 的局限性GPT-5 的创新突破与遗留挑战GPT-5 预期…

微澜:用 OceanBase 搭建基于知识图谱的实时资讯流的应用实践

本文作者&#xff1a; 北京深鉴智源科技有限公司架构师 郑荣凯 本文整理自北京深鉴智源科技有限公司架构师郑荣凯&#xff0c;在《深入浅出 OceanBase 第四期》的分享。 知识图谱是一项综合性的系统工程&#xff0c;需要在在各种应用场景中向用户展示经过分页的一度关系。 微…

FluentUI使用

首先向Qt Qml FluentUI组件库的作者zhuzichu520致敬&#xff01; 一、源码下载地址&#xff1a; 1&#xff09;GitHub - zhuzichu520/FluentUI: FluentUI for QML 2&#xff09;GitCode - 全球开发者的开源社区,开源代码托管平台 二、Qt6下载地址&#xff1a; qt-online-i…

`node-gyp` 无法找到版本为 `10.0.19041.0` 的 Windows SDK

从你提供的错误信息来看&#xff0c;问题出在 node-gyp 无法找到版本为 10.0.19041.0 的 Windows SDK。我们可以尝试以下几种方法来解决这个问题&#xff1a; 完整示例 方法 1&#xff1a;安装指定版本的 Windows SDK 下载并安装 Windows SDK&#xff1a; 访问 Windows SDK 下…

CTFHub每日练习

文章目录 技能树CTF Web信息泄露目录遍历PHPINFO备份文件下载网站源码bak文件vim缓存.DS_Store Git泄露Logstash index方法一方法二 密码口令弱口令 技能树 CTF Web 信息泄露 目录遍历 PHPINFO 备份文件下载 网站源码 当开发人员在线上环境中对源代码进行了备份操作&#x…

【PowerHarmony】电鸿蒙学习记录-编写helloworld!

入门 一、编写HelloWorld1.1 编译SDK1.2 业务构建1.2.1 编写HelloWorld业务代码1.2.3 编辑业务构建文件 1.3 添加新组件1.4 编辑组件条目1.5 编译验证1.6 新增文件结构展示 一、编写HelloWorld 1.1 编译SDK 可以在VSCode终端中编译SDK源码&#xff0c;确认编译通过后即可开始…

【Excel】ToRow超级查找函数

看拼写ToRow的作用该是转换为行&#xff0c;的确如此&#xff0c;它可以把一个表格转换为一行。TOROW(A1:C6) 之所以敢挑Vlookup&#xff0c;是因为它的第2个参数为2时可以忽略错误值。TOROW(F9:F13,2) 所以要查找出符合条件的&#xff0c;只需要把不符合条件的变成错误值&am…

前缀和技巧解析

前缀和技巧解析 前缀和&#xff08;Prefix Sum&#xff09;是一种常用的算法技巧&#xff0c;用于高效地处理一系列连续子数组和的问题。通过构建一个额外的数组来存储从数组起始位置到当前位置的累计和&#xff0c;可以在常数时间内快速计算任意区间的和。 前缀和应用的典型…

分享 pdf 转 word 的免费平台

背景 找了很多 pdf 转 word 的平台都骗进去要会员&#xff0c;终于找到一个真正免费的&#xff0c;遂分享。 网址 PDF转Word转换器 - 100%免费市面上最优质的PDF转Word转换器 - 免费且易于使用。无附加水印 - 快速将PDF转成Word。https://smallpdf.com/cn/pdf-to-word

前端面试笔试(二)

目录 一、数据结构算法等综合篇 1.HTTP/2、ETag有关 二、代码输出篇 1.new URL&#xff0c;url中的hostname&#xff0c;pathname&#xff0c;href 扩展说一下url的组成部分和属性 URL的组成部分 urlInfo 对象的属性 2.一个递归的输出例子 3.数组去重的不普通方法1 4.数…

netmap.js:基于浏览器的网络发现工具

netmap.js是一款基于浏览器&#xff0c;用于提供主机发现和端口扫描功能的网络发现工具。 netmap.js的执行速度也非常的快&#xff0c;由于其使用了es6-promise-pool&#xff0c;因此它可以有效地运行浏览器允许的最大并发连接数。 动机 由于我正需要一个基于浏览器的端口扫…

MySQL(5)【数据类型 —— 字符串类型】

阅读导航 引言一、char&#x1f3af;基本语法&#x1f3af;使用示例 二、varchar&#x1f3af;基本语法&#x1f3af;使用示例 三、char 和 varchar 比较四、日期和时间类型1. 基本概念2. 使用示例 五、enum 和 set&#x1f3af;基本语法 引言 之前我们聊过MySQL中的数值类型&…

百度搜索AI探索版多线程批量生成TXT原创文章软件-可生成3种类型文章

百度搜索AI探索版是百度推出的一款基于大语言模型文心一言的综合搜索产品‌。以下是关于百度搜索AI探索版的详细介绍&#xff1a; ‌产品发布‌&#xff1a;百度搜索AI探索版在百度世界大会上进行了灰度测试&#xff0c;并面向用户开放体验‌。 ‌核心功能‌&#xff1a;与传…

websocket初始化

websocket初始化 前言 上一集我们HTTP的ping操作就可以跑通了&#xff0c;那么我们还有一个协议---websocket&#xff0c;我们在这一集就要去完成我们websocket的初始化。 分析 我们在初始化websocket的之前&#xff0c;我们考虑一下&#xff0c;我们什么时候就要初始化我们…

Git在版本控制中的应用

&#x1f493; 博客主页&#xff1a;瑕疵的CSDN主页 &#x1f4dd; Gitee主页&#xff1a;瑕疵的gitee主页 ⏩ 文章专栏&#xff1a;《热点资讯》 Git在版本控制中的应用 Git在版本控制中的应用 Git在版本控制中的应用 引言 Git 概述 定义与原理 发展历程 Git 的关键技术 分布…

[JAVAEE] 面试题(四) - 多线程下使用ArrayList涉及到的线程安全问题及解决

目录 一. 多线程下使用ArrayList 1.1. 自行判断加锁 1.2 使用Collections.synchronizedList()套壳加锁 1.3 CopyOnWriteArrayList类 二. 总结 一. 多线程下使用ArrayList 多线程下使用ArrayList会涉及到线程安全问题, 例如: public static void main(String[] args) thro…

python——面向对象

一、面向对象编程 1.1 面向过程与面向对象 面向过程和面向对象都是一种编程方式&#xff0c;只不过再设计上有区别。 1.1.1 面向过程pop&#xff1a; 举例&#xff1a;孩子上学 1. 妈妈起床 2. 妈妈洗漱 3. 妈妈做饭 4. 妈妈把孩子叫起来 5. 孩子起床 6. 孩子洗漱 7. 孩子吃…

【缺陷检测】Anomaly Detection via Reverse Distillation from One-Class Embedding

论文地址 代码地址 动机 论文针对传统的知识蒸馏的方案提出了一个问题&#xff1a;认为之前的&#xff08;基于像素点的重建&#xff09;方案[1,2]容易阻碍异常表现的多样性 传统的知识蒸馏teacher和student的网络架构很相似或者几乎相同而且teacher和student的输入流都是…