gulp

作者: 9吧和9说9话 | 来源:发表于2020-02-19 21:25 被阅读0次

流式构建工具,自动化加强你的工作流

  1. 基于任务配置
  2. 提供插件系统
  3. 简单、定义良好的API
  4. 基于nodejs stream设计,前端友好,构建高效。

gulp处理流程:

  1. 启动一个task,
  2. 通过glob语法定位处理的文件流
  3. 通过插件 进行插件内容的处理
  4. 最终产出输出文件。

定位要处理的文件 - Glob

几个特殊的字符

* Matches 0 or more characters in a single path portion
? Matches 1 character
[...] Matches a range of characters, similar to a RegExp range. If the first character of the range is ! or ^ then it matches any character not in the range.
!(pattern|pattern|pattern) Matches anything that does not match any of the patterns provided.
?(pattern|pattern|pattern) Matches zero or one occurrence of the patterns provided.
+(pattern|pattern|pattern) Matches one or more occurrences of the patterns provided.
*(a|b|c) Matches zero or more occurrences of the patterns provided
@(pattern|pat*|pat?erN) Matches exactly one of the patterns provided
** If a "globstar" is alone in a path portion, then it matches zero or more directories and subdirectories searching for matches. It does not crawl symlinked directories.
  1. 一个*, 表示匹配文件名中 0个或大于0个的任意字符。
  2. ? 代表一个任意的字符
  3. 两个*, 表示匹配文件夹名 0个或大于0个的任意字符。
  4. {xxx,aaa} 表示匹配文件夹名是xxx或者aaa
  5. [] 类似正则表达式中的 范围
  6. !(pattern|pattern|pattern) 除了pattern匹配的其他字符

具体参考:node-glob

实际使用:

// 匹配当前文件夹下的所有已`.js`结尾的文件
*.js
./*.js
// 匹配当前文件夹下的所有的已`test`开头的文件
test*
// 匹配当前文件夹下的所有的已`test`开头的js文件
test*.js
// 匹配当前文件夹下的所有的已`test`开头的js文件
test*.js
// 匹配当src文件夹下的所有的已`test`开头,间隔一个字符,后加一个aa或者是bb文件
src/test?{aa,bb}*
// 匹配当src文件夹下的所有的已`test`开头,间隔一个字符,后面不是`aa` `nice`的所有文件
src/test-[^(aa)(nice)]*
// 匹配当前文件夹以及子目录的所有的已`test`开头的js文件
**/test-*.js

vinyl File objects

gulp依赖的一个模块。

stream

为啥需要stream
假设下面的代码:

const http = require('http');
const fs = require('fs');

// 响应一个大的文件给客户端
const server = http.createServer((req, res)=> {
  fs.readFile('bigfile.txt', 'utf-8', function (err, data) {
    if(err) throw err;
    res.end(data)
  })
});
server.listen(3000);

这个时候的简单处理流程是这样的:

  1. 客户端发起请求
  2. 服务端接收请求
  3. 将文件全部一次性读取到内存中,然后通过网络接口发送到客户端

这里的问题在于:一次性的读取到内存中。

我们知道计算机发展到今天,硬件已经有了很大的发展进步,但是即使这样我们的普通的计算机内存也是很有限的(一般是4-8g),对于服务器而言也不会很大,内存要求越高,价格也越高。如果我们读取的是一个几百兆的文件,加上并发,服务器将变得异常脆弱,很容易因为内存占用过高,导致应用无法提供正常的服务。

那么stream是什么

四种流:

  1. reaableStream 提供数据源(能够从中读取数据)
  2. writableStream 写入数据源(能够写入数据)
  3. duplexStream 双工(既可以当做数据源 也可写入数据)
  4. transformStream

使用stream

  1. 使用pipe方法
reableStream.pipe(writableStream)

reableStream
.pipe(duplexStream)
.pipe(duplexStream)
.pipe(writableStream)
  1. 通过事件使用


    image.png
# readable.pipe(writable)

readable.on('data', (chunk) => {
  writable.write(chunk);
});

readable.on('end', () => {
  writable.end();
});

实现stream

  1. 实现一个reable stream
const inStream = new Readable({
  read(size) {
    this.push(String.fromCharCode(this.currentCharCode++));
    if (this.currentCharCode > 90) {
      this.push(null);
    }
  }
});

inStream.currentCharCode = 65;

inStream.pipe(process.stdout);
  1. 实现一个writable stream
const { Writable } = require('stream');

const outStream = new Writable({
  write(chunk, encoding, callback) {
    console.log(chunk.toString());
    callback();
  }
});

process.stdin.pipe(outStream);
  1. 实现一个duplex stream,同时实现read write方法
const { Duplex } = require('stream');

const inoutStream = new Duplex({
  write(chunk, encoding, callback) {
    console.log(chunk.toString());
    callback();
  },

  read(size) {
    this.push(String.fromCharCode(this.currentCharCode++));
    if (this.currentCharCode > 90) {
      this.push(null);
    }
  }
});

inoutStream.currentCharCode = 65;

process.stdin.pipe(inoutStream).pipe(process.stdout);
  1. 实现一个transform stream, 实现transform方法
const { Transform } = require('stream');

const upperCaseTr = new Transform({
  transform(chunk, encoding, callback) {
    this.push(chunk.toString().toUpperCase());
    callback();
  }
});

process.stdin.pipe(upperCaseTr).pipe(process.stdout);

streamobjectMode

  1. nodejs创建的所有的流对象,只能操作 stringbuffer以及Buffer对象。
  2. 提供了一个配置项:objectMode

那么stream是怎么解决的呢?

不会一次将文件内容读取到内存中,而是分批次的进行处理。先写入到缓存区Buffer,然后等待消费

关于Buffer

  1. 可读流和可写流都会把数据存储内部的一个缓存区。
  2. highWaterMark控制缓存区的大小
  3. 当可读流调用stream.push(data)的时候 会把data缓存到Buffer
  4. 如果消费这个流的消费者没有触发strea.read(),data就一直在内部队列中,等待被消费。
  5. 一旦内部读取缓冲区的总大小达到highWaterMark指定的阈值,流将暂时停止从基础资源读取数据,直到可以使用当前缓冲的数据为止
  6. 重复调用writable.write(chunk)方法时,数据将缓存在可写流中
  7. 当内部写缓冲区的总大小低于highWaterMark设置的阈值时,对writable.write()的调用将返回true
  8. 一旦内部缓存区大小达到或者超过了 highWaterMark设置的阈值,writable.write()将返回false

参考:

  1. https://www.freecodecamp.org/news/node-js-streams-everything-you-need-to-know-c9141306be93/
  2. https://github.com/substack/stream-handbook

插件体系

实现Transform 流

function gulpRename(obj, options) { 
  var stream = new Stream.Transform({ objectMode: true });
  stream._transform = function(originalFile, unused, callback) {
      // code 
    // transformFunction 处理你的原文件
    let file = transformFunction(originalFile);
    callback(null, file);
  }

  return stream;
}

参考:

  1. https://github.com/gulpjs/gulp/blob/master/docs/writing-a-plugin/README.md
  2. https://nodejs.org/api/stream.html#stream_class_stream_transform_1
  3. https://v3.gulpjs.com.cn/docs/writing-a-plugin/
  4. https://github.com/gulpjs/gulp/blob/master/docs/writing-a-plugin/README.md
  5. https://www.gulpjs.com.cn/docs/getting-started/explaining-globs/

相关文章

  • gulp

    gulp gulp.src gulp.dest gulp.task gulp.watch gulp.pipe() ...

  • gulp自动化项目构建

    var gulp = require('gulp');//引用gulp var $ = require('gulp...

  • gulp压缩合并文件

    gulp压缩合并文件流程 //引入gulp和gulp插件var gulp = require('gulp');va...

  • Gulp 使用方法(教程一)

    Gulp 官网 目录 Gulp 环境 Gulp 环境 初始化目录结构 安装 gulp gulp 的简单使用 使用 ...

  • gulp讲解

    一、gulp的四个主要的API gulp.src、gulp.pipe、gulp.dest、gulp.watch 二...

  • JS: gulp.js

    var gulp = require('gulp'), minify = require('gulp-minify...

  • gulp的简单使用

    gulp使用流程:安装nodejs -> 全局安装gulp -> 项目安装gulp以及gulp插件 -> 配置gu...

  • gupl 的基本压缩

    // 获取 gulp var gulp = require('gulp'); // 获取 uglify 模块(用于...

  • gulp+webpack+experss

    var gulp = require('gulp'); var gls = require('gulp-live-...

  • gulp与webpack的区别

    gulp webpack 相同功能: 功能 gulp webpack gulp.task('sass'...

网友评论

      本文标题:gulp

      本文链接:https://www.haomeiwen.com/subject/mmclzctx.html