自动化工具 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,一经查实,立即删除!

相关文章

探索 Seata 分布式事务

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

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

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

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

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

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

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

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;迈…

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

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

CSS:导航栏三角箭头

用CSS实现导航流程图的样式。可根据自己的需求进行修改&#xff0c;代码精略的写了一下。 注&#xff1a;场景一和场景二在分辨率比较低的情况下会有一个1px的缝隙不太优雅&#xff0c;自行处理。有个方法是直接在每个外面包一个DIV&#xff0c;用动态样式设置底色。 场景一、…

Qt_day4_Qt_UI设计

目录 Qt_UI设计 1. Designer 设计师&#xff08;掌握&#xff09; 2. Layout 布局&#xff08;重点&#xff09; 2.1 基本使用 2.2 高级用法 2.3 代码布局&#xff08;了解&#xff09; 3. Designer与C的关系&#xff08;熟悉&#xff09; 4. 基本组件&#xff08;掌握…

数据结构的时间复杂度和空间复杂度

目录 时间复杂度 空间复杂度 时间复杂度 基本操作的执行次数&#xff0c;为时间复杂度。 我们使用大O的渐进表示法来表示时间复杂度。 怎么使用&#xff1f; 先看例子&#xff1a; 在这个例子中&#xff0c; 基本操作为变量 count 的 加加 操作&#xff0c;并且&#xff0c;执行…

【Chapter 3】Machine Learning Classification Case_Prediction of diabetes-XGBoost

文章目录 1、XGBoost Algorithm2、Comparison of algorithm implementation between Python code and Sentosa_DSML community edition(1) Data reading and statistical analysis(2)Data preprocessing(3)Model Training and Evaluation(4)Model visualization 3、summarize 1…

Rust Struct 属性初始化

结构体是用户定义的数据类型&#xff0c;其中包含定义特定实例的字段。结构有助于实现更容易理解的抽象概念。本文介绍几种初始化结构体对象的方法&#xff0c;包括常规方法、Default特征、第三方包实现以及构建器模式。 Struct声明与初始化 struct Employee {id: i32,name: …

AI大模型微调:Qwen2大模型微调入门实战(完整代码)

简介&#xff1a; 该教程介绍了如何使用Qwen2&#xff0c;一个由阿里云通义实验室研发的开源大语言模型&#xff0c;进行指令微调以实现文本分类。微调是通过在&#xff08;指令&#xff0c;输出&#xff09;数据集上训练来改善LLMs理解人类指令的能力。教程中&#xff0c;使用…

基于Python+Django+Vue3+MySQL实现的前后端分类的商场车辆管理系统

项目名称&#xff1a;基于PythonDjangoVue3MySQL实现的前后端分离商场车辆管理系统 技术栈 开发工具&#xff1a;PyCharm、Visual Studio Code (VSCode)运行环境&#xff1a;Python 3.10、MySQL 8.0、Node.js 18技术框架&#xff1a;Django 5、Vue 3.4、Ant-Design-Vue 4.12 …

C++初阶:类和对象(上)

1. 类的定义 1.1 类的定义格式 class为定义类的关键字&#xff0c;Stack为类的名字&#xff0c;{ } 中为类的主体&#xff0c;注意类定义结束后的分号不能省略。类体中的内容为类的成员&#xff1a;类中的变量称为类的属性或成员变量&#xff1b;类中的函数称为类的方法或成员…

ctfshow DSBCTF web部分wp

ctfshow 单身杯 web部分wp web 签到好玩的PHP 源码&#xff1a; <?php error_reporting(0); highlight_file(__FILE__);class ctfshow {private $d ;private $s ;private $b ;private $ctf ;public function __destruct() {$this->d (string)$this->d;$this…

【分布式】万字图文解析——深入七大分布式事务解决方案

分布式事务 分布式事务是指跨多个独立服务或系统的事务管理&#xff0c;以确保这些服务中的数据变更要么全部成功&#xff0c;要么全部回滚&#xff0c;从而保证数据的一致性。在微服务架构和分布式系统中&#xff0c;由于业务逻辑往往会跨多个服务&#xff0c;传统的单体事务…

边缘计算在智能物流中的应用

&#x1f493; 博客主页&#xff1a;瑕疵的CSDN主页 &#x1f4dd; Gitee主页&#xff1a;瑕疵的gitee主页 ⏩ 文章专栏&#xff1a;《热点资讯》 边缘计算在智能物流中的应用 边缘计算在智能物流中的应用 边缘计算在智能物流中的应用 引言 边缘计算概述 定义与原理 发展历程 …

Spring Boot框架:电商开发的新趋势

5 系统实现 系统实现部分就是将系统分析&#xff0c;系统设计部分的内容通过编码进行功能实现&#xff0c;以一个实际应用系统的形式展示系统分析与系统设计的结果。前面提到的系统分析&#xff0c;系统设计最主要还是进行功能&#xff0c;系统操作逻辑的设计&#xff0c;也包括…