要说到 gulp 的运作形式,就不得不提到 vinyl 和 Node.js 的 stream
vinyl
vinyl 是 gulp 用的虛擬的檔案格局,在它的 readme 是這麼說的:「說你檔案你第一個想到的是什麼?路徑跟內容吧」,它次要紀錄的資訊有:
vinyl 是 gulp 所应用的虚构的文件格式,在它的自述文件是这么说的:“当提到文件时你首先想到的是什么?必定是门路和内容吧”,它次要记录的信息有:
path
:文件门路contents
:文件内容cwd
:程序执行的目录base
:用 glob 寻找文件时开始的目录,例如src/**/*.js
,那base
就会是src
,这能够用来重现目录构造
另外它还有几个函数用来判断这个文件的内容是什么类型的这类操作,到于这个虚构文件实际上用在什么中央,咱们稍后再说,先创立一个文件试试:
const { readFile } = require('fs/promises')const Vinyl = require('vinyl')const file = new Vinyl({ path: __filename, // 这个文件的门路 // 在 Node.js 14.8.0 中 反对 top level await,不过还是倡议用 async function 封装 contents: await readFile(__filename), cwd: process.cwd(), // 不设定的话默认值为 process.cwd() base: process.cwd(), // 不设定的话默认值为 process.cwd()})console.log(file) // 这是应该能看到 <File "file.js" <Buffer ...>>
这样就创立好了一个 gulp 用的文件格式,接下来是 Node.js 的 stream。
stream
stream 设计的本意是要解决大文件的,它能一次读取文件的一小部分,而后再传给调用者进行解决:
const { createReadStream } = require('fs')// 创立一个读取文件的 streamconst stream = createReadStream(__filename)// 设置文件字符集编码,否则就会以 Buffer (二进制数据) 的格局读取stream.setEncoding('utf-8')// 解决数据stream.on('data', (chunk) => { console.log('chunk', JSON.stringify(chunk))})// 完结stream.on('end', () => { console.log('end')})
实际上它是基于 EventEmitter 之上创立的一组 API,比方 on
就是来自于 EventEmitter,只有照着它的模式,也不肯定只能传小块的文件,在 Node.js 中的 stream 也有一个对象模式,如果传的数据不是缓冲区或流就应该设置为对象模式,而对象模式跟个别的模式次要的区别就是不须要解决字符集编码。
再回到 gulp,还记得之前说过 src
是回传一个 stream 吗?接下来看看外面到底传的是什么,先写个 gulpfile 来试看看:
exports.stream = function () { const stream = src('./src/**.js') stream.on('data', (data) => { console.log(data) }) return stream}
输入:
<File "file.js" <Buffer ...>>
没错,这就是 Vinyl 的文件,gulp 用 stream 的对象模式在传输这些文件,plugin 其实上就是回传一个 Transform
的 stream(Node.js 中 stream 的一种,stream 的品种有 Readable、Writeable、Duplex、Transform)来转换这些文件,比上面是一个把文件内容都换成大写的流:
const { Transform } = require('stream')exports.uppercase = function () { return src('./src/**.js') .pipe( new Transform({ // 设置为 object mode objectMode: true, transform(file, _enc, cb) { // 把文件内容转换成为字符串 const content = file.contents.toString() // 转为大写后再转回 Buffer 存回去 file.contents = Buffer.from(content.toUpperCase()) // 用 callback 回传 cb(null, file) }, }) ) .pipe(dest('upper'))}
当初咱们有了一个把文件全转大写的 plugin了,不过没什么实用上的意义。这样转来转去的效率太低了。
剩下的局部就是 gulp 解决工作的注册与依赖性的逻辑了,依赖性次要是由 undertaker
解决的,不过我感觉这里没什么特地的货色,所以有趣味就本人去看看吧。
本文首发微信公众号:前端先锋
欢送扫描二维码关注公众号,每天都给你推送陈腐的前端技术文章
欢送持续浏览本专栏其它高赞文章:
- 深刻了解Shadow DOM v1
- 一步步教你用 WebVR 实现虚拟现实游戏
- 13个帮你进步开发效率的古代CSS框架
- 疾速上手BootstrapVue
- JavaScript引擎是如何工作的?从调用栈到Promise你须要晓得的所有
- WebSocket实战:在 Node 和 React 之间进行实时通信
- 对于 Git 的 20 个面试题
- 深刻解析 Node.js 的 console.log
- Node.js 到底是什么?
- 30分钟用Node.js构建一个API服务器
- Javascript的对象拷贝
- 程序员30岁前月薪达不到30K,该何去何从
- 14个最好的 JavaScript 数据可视化库
- 8 个给前端的顶级 VS Code 扩大插件
- Node.js 多线程齐全指南
- 把HTML转成PDF的4个计划及实现
- 更多文章...