资讯动态

gulp 单任务多数据源实战:merge-stream 合并独立管线与 globs 数组拼接

发布时间:2026/9/19 15:14:46 来源:尧图企业网站定制
gulp 单任务多数据源实战merge-stream 合并独立管线与 globs 数组拼接【免费下载链接】gulpA toolkit to automate enhance your workflow项目地址: https://gitcode.com/gh_mirrors/gu/gulp在同一个 gulp 任务里从多个目录读取文件是构建工作流中的高频需求。本文以 docs/recipes/using-multiple-sources-in-one-task.md 为核心完整讲解两种官方推荐方案用merge-stream将多条独立管线合并为一条以及用gulp.src的 globs 数组特性结合gulp-concat拼接多个来源。读完你将掌握一个任务处理多组文件的两种正确姿势并能理解其底层流式原理与选择依据。场景为什么一个任务需要多个数据源在真实项目中一个任务往往不止处理一组文件。以原文档示例中的静态资源搬运为例bootstrap/js/*.js—— Bootstrap 的 JS 文件需要拷贝到public/bootstrap/jquery.cookie/jquery.cookie.js—— jQuery 插件文件需要拷贝到public/jquery/。虽然可以直接写两个任务分别处理但如果两者属于同一个构建阶段例如都服务于前端资源这一目标把它们放进同一个任务里会让构建逻辑更集中、语义更清晰。这就是单任务多源需求的来源。在 gulp 中每个gulp.src()都会创建一个独立的读取流每个.pipe(gulp.dest())又是独立写入流。同一个任务里出现多个src()时就必须考虑如何把它们组织成一条可被 gulp 正确识别的流。原文档给出了两种官方认可的方案。方案一用 merge-stream 合并多条独立管线这是原文档的第一种做法适用于每组文件的目标目录不同甚至每组文件的处理管线都不同的场景。// npm install --save-dev gulp merge-stream var gulp require(gulp); var merge require(merge-stream); gulp.task(test, function() { var bootstrap gulp.src(bootstrap/js/*.js) .pipe(gulp.dest(public/bootstrap)); var jquery gulp.src(jquery.cookie/jquery.cookie.js) .pipe(gulp.dest(public/jquery)); return merge(bootstrap, jquery); });拆解这段代码可以看到清晰的四步分别创建源流gulp.src(bootstrap/js/*.js)与gulp.src(jquery.cookie/jquery.cookie.js)各自按 glob 模式读取文件产出 Vinyl 对象流分别接上目的地每条流各自.pipe(gulp.dest(...))把文件写到自己的目录。此时bootstrap与jquery都是已经完成读取→写入完整链路的独立流对象合并merge(bootstrap, jquery)把两条流合并成一条合并流两条源流中的文件会按添加顺序依次流出返回合并流return merge(bootstrap, jquery)是最关键的一步。gulp 的任务系统依靠返回的流来判断任务何时完成详见 3-creating-tasks.md 与 4-async-completion.md。如果只返回其中一条流另一条流的写入可能尚未完成任务就会提前结束。把merge的结果作为返回值gulp 会等待两条流全部结束。注意merge-stream是第三方 npm 包npm install --save-dev gulp merge-stream不是 gulp 内置模块但它正是 gulp 生态中处理多源多目标的标准配套工具。方案二globs 数组 gulp-concat 拼接单条管线原文档强调gulp.src会按 globs 数组中声明的顺序发出文件。利用这一点可以把多个来源合并进同一条管线再统一交给下游插件处理。// npm install gulp gulp-concat var gulp require(gulp); var concat require(gulp-concat); gulp.task(default, function() { return gulp.src([foo/*, bar/*]) .pipe(concat(result.txt)) .pipe(gulp.dest(build)); });与方案一相比此方案的关键差异在于gulp.src接受数组查看 src() 的 API 文档globs参数的类型是string | array。传入[foo/*, bar/*]时gulp 会先匹配foo/*的文件再匹配bar/*的文件并按此顺序放入流中共用同一条下游管线文件依次经过concat(result.txt)合并成一个文件再写入build/目录。这正是gulp-concat插件发挥作用的时刻——它读取流中全部文件内容并按到达顺序拼接适用于多源汇聚成单文件/单目录当多个来源的文件最终要合并成一个产物如打包为一个 bundle或写入同一个目标目录时这是最简洁的写法。顺序保证背后的原理glob base方案二能保证拼接顺序与 gulp 的glob baseglob 父路径机制密切相关。在 API Concepts 中有明确说明glob base 是 glob 字符串中任意特殊字符之前的那段路径例如/src/js/**.js的 base 是/src/js/src()生成的所有 Vinyl 对象都会以该 base 作为base属性写入时dest()会移除 base 以保留目录结构。这意味着当你写gulp.src([foo/*, bar/*])时foo/*匹配的文件 base 为foo/bar/*匹配的文件 base 为bar/。虽然它们进入同一条流但各自的相对目录信息依然保留——这也解释了为什么方案二适合统一处理后仍保持各自目录结构或直接按顺序拼接的场景。两种方案如何选择维度方案一merge-stream方案二globs 数组目标目录各源流可写往不同目录通常写往同一目录/同一文件管线处理各源流可挂载不同的插件链所有源文件共享同一条插件链依赖需额外安装merge-stream仅需 gulp 本身拼接需要gulp-concat顺序合并流按传入顺序输出各源流globs 数组内按声明顺序输出文件典型场景多组资源各自拷贝/各自处理多目录源码合并打包成一个 bundle选择要点可以概括为分流用 merge-stream合流用 globs 数组。如果各组文件处理方式不同、目的地不同方案一更合适如果它们要被统一加工并汇聚成单一产物方案二更简洁。源码级原理src/dest 从何而来理解了用法之后看一下当前仓库的实现能更清楚地把握这两种方案在 gulp 整体架构中的位置。在 index.js 中可以看到 gulp 实例的核心方法定义Gulp.prototype.src vfs.src; Gulp.prototype.dest vfs.dest; Gulp.prototype.symlink vfs.symlink;src()与dest()直接来自 vinyl-fs 这个 Vinyl 适配器模块当前仓库的 package.json 中声明了vinyl-fs: ^4.0.2。也就是说无论你用方案一还是方案二底层都是 vinyl-fs 的流在干活——gulp.src负责把文件系统上的真实文件包装成 Vinyl 对象流gulp.dest负责消费这些 Vinyl 对象并写回文件系统。这解释了为什么两种方案能自由组合它们操作的是同一套流协议merge-stream合并的正是这种协议流。同时gulp 官方测试 test/index.test.js 通过hasOwnProperty断言确认了src、dest等 API 均挂在 gulp 实例自身即require(gulp).src是可用的公开接口。关于 src() 的几个相关选项若你的多源任务涉及更复杂的匹配需求可以查阅 docs/api/src.md 中src()的完整选项表其中与多源场景直接相关的包括base显式设置生成 Vinyl 对象的 base控制输出目录结构allowEmpty默认false当某个 glob 只能匹配单个文件如jquery.cookie/jquery.cookie.js且匹配不到时会抛出 File not found with singular glob 错误设为true可抑制ignore从匹配结果中排除指定 globuniqueBy默认path去除流中的重复文件。进阶实践多源管线的错误处理与复用为多源管线统一捕获错误方案一中每条管线都是独立流错误可能发生在任一流上。官方配方 combining-streams-to-handle-errors.md 指出默认情况下流上发出error事件若没有监听器会被直接抛出。更稳妥的做法是用stream-combiner2把一长串流合并成单个流从而只在一处监听errorvar combiner require(stream-combiner2); var uglify require(gulp-uglify); var gulp require(gulp); gulp.task(test, function() { return combiner.obj([ gulp.src(bootstrap/js/*.js), uglify(), gulp.dest(public/bootstrap) ]) .on(error, console.error.bind(console)); });这个思路同样适用于方案一可以把merge(bootstrap, jquery)的结果接入统一错误监听让多源任务失败时错误集中可见。用流工厂复用多源管线如果多个任务都包含多源→统一变换→输出的相同链路官方配方 sharing-streams-with-stream-factories.md 提供了lazypipe方案把共享的插件链封装成工厂函数不同任务中只需pipe(factory())即可复用这也天然兼容多源流各自接同一段工厂管线的组合方式。此外incremental-builds-with-concatenate.md 展示了gulp-cachedgulp-remembergulp-concat配合gulp.watch做增量构建的完整实战其中同样使用了多源聚合 concat的模式可作为方案二在 watch 场景下的延伸参考。小结多源多目标用merge-stream合并各条独立的src→dest管线并务必 return 合并结果保证 gulp 任务在全部写入完成后才结束多源单目标/单文件利用gulp.src支持 globs 数组且按声明顺序发流的特性配合gulp-concat将多目录文件汇聚成一个产物本质src/dest均来自 vinyl-fs两种方案都建立在统一的 Vinyl 流协议之上可自由与错误处理、流工厂、增量构建等其他官方配方组合。更多多源相关实战可继续浏览 docs/recipes/README.md 中的其他配方如 browserify-with-globs.md、minified-and-non-minified.md 等。【免费下载链接】gulpA toolkit to automate enhance your workflow项目地址: https://gitcode.com/gh_mirrors/gu/gulp创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

读完文章,也想定制专属网站?

尧图设计师 24 小时内与您沟通定制方案

免费获取报价