javascript - 在一个管道中定义的 gulp var 在另一个管道中未定义

标签 javascript node.js gulp gulp-rename

我正在使用 gulp 处理网站的页面,其中一些页面是 php 文件。问题是,所有页面都通过模板引擎运行后,它们具有 .html 文件扩展名。我向文件添加一个属性,指定它是否应该是 html 之外的文件,然后重命名该文件以匹配。然而,由于某种原因 gulp-rename 一直说我用来存储扩展的变量是未定义

gulpfile.js 中对应的任务:

var gulp         = require('gulp'),
    gutil        = require('gulp-util'),
    lodash       = require('lodash'),
    data         = require('gulp-data'),
    filesize     = require('gulp-filesize'),
    frontMatter  = require('gulp-front-matter'),
    rename       = require('gulp-rename'),
    util         = require('util');    


gulp.task('metalsmith', function(){
var ext;                     //Variable to store file extension
return gulp.src(CONTENT_DIR)
    .pipe(frontMatter()).on("data", function(file){
        lodash.assign(file, file.frontMatter);
        delete file.frontMatter;
    })
    .pipe(data(function(file){                  //ext is defined here
        if(typeof file.filetype === 'undefined'){
            ext = {extname: '.html'};
        }else{
            ext = {extname: file.filetype};
        }
    }))
    .pipe(tap(function(file){
        console.log(ext);       //when I print to the console, ext is defined and correct
    }))
    .pipe(rename(ext)) //ext is undefined
    .pipe(gulp.dest(BUILD_DIR))
});

当我运行上面的代码时,它会出现错误,提供的重命名参数类型不受支持

我还尝试过将选项 obj 与 rename() 放在同一行,ext 仅存储文件扩展名,例如: .pipe(rename({extname: ext})) 这会导致文件添加 undefined 作为扩展名(而不是 phpfile.php,下面的 md 文件将被命名为 phpfileundefined)

phpfile.md 中的 yaml

---
layout: php.hbt
filetype: ".php"
title: "php"
---

package.json

"devDependencies": {
    "gulp": "^3.9.1",
    "gulp-data": "^1.2.1",
    "gulp-filter": "^4.0.0",
    "gulp-front-matter": "^1.3.0",
    "gulp-rename": "^1.2.2",
    "gulp-util": "^3.0.7",
    "lodash": "^4.11.1"
  }

最佳答案

您的问题是,当您执行 rename(ext) 时,ext 的值仍然是 undefined,因为您的 data(...) 代码尚未运行。

Gulp 插件的工作原理如下:

  1. 您调用插件函数并向其传递任何必要的参数。在您的情况下rename(ext)
  2. 插件函数返回 duplex stream
  3. 您将该双工流传递给 .pipe()
  4. 只有在执行完所有 .pipe() 调用后,流式传输才会开始运行。

因此,rename(ext) 是一个函数调用,用于构造流本身。只有在流构建完成后,流才能开始运行

但是,只有在流运行时才设置 ext 的值。在构造流时,您需要之前 ext 的值。

针对您的情况,最简单的解决方案是在 data(...) 函数中手动进行重命名,而不是依赖 gulp-rename。您可以使用内置的node.js path模块(这就是 gulp-rename 在底层使用的):

var path = require('path');

gulp.task('metalsmith', function(){
  return gulp.src(CONTENT_DIR)
    .pipe(frontMatter()).on("data", function(file){
        lodash.assign(file, file.frontMatter);
        delete file.frontMatter;
    })
    .pipe(data(function(file){
        var ext;
        if(typeof file.filetype === 'undefined'){
            ext = '.html';
        }else{
            ext = file.filetype;
        }
        var parsedPath = path.parse(file.path);
        file.path = path.join(parsedPath.dir, parsedPath.name + ext);
    }))
    .pipe(gulp.dest(BUILD_DIR))
});

或者,您也可以使用 gulp-foreach正如我在this answer中建议的那样类似的问题。不过,在您的情况下,这并不是真正必要的,因为您已经直接在 data(...) 中访问 file 对象。

编辑:为了完整起见,这是使用gulp-foreach的版本:

var foreach = require('gulp-foreach');

gulp.task('metalsmith', function(){
   return gulp.src(CONTENT_DIR)
    .pipe(frontMatter()).on("data", function(file){
        lodash.assign(file, file.frontMatter);
        delete file.frontMatter;
    })
    .pipe(foreach(function(stream, file){
        var ext;
        if(typeof file.filetype === 'undefined'){
            ext = {extname: '.html'};
        }else{
            ext = {extname: file.filetype};
        }
        return stream.pipe(rename(ext));
    }))
    .pipe(gulp.dest(BUILD_DIR))
});

关于javascript - 在一个管道中定义的 gulp var 在另一个管道中未定义,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/39380427/

相关文章:

javascript - 由于缺少 bson 模块,node.js 教程失败

jasmine - 使用 Jasmine 2、Protractor 和 Gulp 显示规范文本

javascript - 如何将变量传递给 gulp-processhtml?

string - 在 Gulp 中是否可以使用字符串而不是源文件开头?

javascript - JQuery 验证插件显示 "Please enter a value greater than or equal to 0."

node.js - Nodejs Sequelize sqlite3 没有这样的表

javascript - 通过 Node 中的 module.exports 获取变量

javascript - 错误 : Object doesn't support property or method 'css'

javascript - 如何将集合中的一份文档发布到客户端?

javascript - 更新 Aurelia 自定义属性中的绑定(bind)