如何从Gulp中的字符串创建文件?


75

在我的gulpfile中,我在字符串中有一个版本号。我想将版本号写入文件。在Gulp中是否有一种很好的方法可以做到这一点,还是我应该看看更通用的NodeJS API?


1
确切的要求..围绕版本号...我想用它来将其附加到资产URL上以进行缓存爆发
Akarsh Satija

Answers:


75

如果您想以类似口水的方式执行此操作,则可以创建“假”黑胶文件流并按pipe常规方式调用。这是用于创建流的函数。“ stream”是一个核心模块,因此您不需要安装任何东西:

function string_src(filename, string) {
  var src = require('stream').Readable({ objectMode: true })
  src._read = function () {
    this.push(new gutil.File({
      cwd: "",
      base: "",
      path: filename,
      contents: new Buffer(string)
    }))
    this.push(null)
  }
  return src
}

您可以像这样使用它:

gulp.task('version', function () {
  var pkg = require('package.json')
  return string_src("version", pkg.version)
    .pipe(gulp.dest('build/'))
})

我最终基本上做到了这一点,但是使用事件流的readArray来创建流。
达里尔

2
对于那些不了解流的人,可以通过在_read每个文件中重复两行来对多个文件字符串进行处理。在这种情况下,文件对象数组将是一个更好的sting_src参数。
Wes Johnson

这涵盖了我创建一个流以与其他Gulp插件一起传递的用例。
伊赛亚·梅多斯

4
如果没有其他人像我一样不熟悉node,则nodeBuffer作为全局节点提供(nodejs.org/api/buffer.html)。
contrebis 2015年

这对我this.push(null)有用,但对我却引发错误stream.push() after EOF,不知道为什么。注释掉该行是可行的,但随后gulp无限期挂起。
justin.m.chase 2016年

75

它几乎是节点中的一线:

require('fs').writeFileSync('dist/version.txt', '1.2.3');

或从package.json中获取:

var pkg = require('./package.json');
var fs = require('fs');
fs.writeFileSync('dist/version.txt', 'Version: ' + pkg.version);

我使用它在易于访问的文件中指定生成日期,因此我return gulp.src(...)在执行build任务之前使用此代码:

require('fs').writeFileSync('dist/build-date.txt', new Date());

这可能是执行此操作的最佳方法(除非您使用的是ShellJS)。
Isiah Meadows 2014年

1
writeFile函数现在是异步的,需要回调。您可能想使用'writeFileSync'或更好地进行反应,并在文件实际写入磁盘时传递回调以执行某些操作。
monzonj 2015年

2
如何进行链接(管道)以访问由此创建的文件?由于它更多是节点方法,因此我无法访问在同一构建任务中创建的文件。
beauXjames

2
@beauXjames可以使用mjhasbach的解决方案,也可以仅在行gulp.src('dist/version.txt').pipe(…)后添加.writeFileSync
fregante

2
爱它。我用它来生成一个随机字符串,用作缓存破坏者。 gist.github.com/cmeza/e5488609d09722bd2c82e954859f36cf
cmeza

28

这也可以使用乙烯基源流来完成。请在gulp存储库中查看此文档

var gulp = require('gulp'),
    source = require('vinyl-source-stream');

gulp.task('some-task', function() {
    var stream = source('file.txt');

    stream.end('some data');
    stream.pipe(gulp.dest('output'));
});

如果您想使用,这可能是最干净的节点方式.pipe()
fregante 2015年

你能解释一下process.nextTick(fn() { stream.end(); }吗?
2015年

@Chic我在process.nextTick回调中结束了流,因为这是在gulp文档中完成的。似乎没有必要,所以我更新了答案。感谢您指出了这一点。
mjhasbach

22

根据Gulp的维护者,将字符串写入文件的首选方法是fs.writeFile与任务回调一起使用。

var fs = require('fs');
var gulp = require('gulp');

gulp.task('taskname', function(cb){
  fs.writeFile('filename.txt', 'contents', cb);
});

来源:https : //github.com/gulpjs/gulp/issues/332#issuecomment-36970935


唯一的问题是它需要文件存在...如果没有文件,是否存在允许创建该文件的标志?
塞杰·萨根

@SerjSagan不知道是什么原因引起的。如果文件不存在,则使用默认设置的writeFile会创建该文件。
GOTO

16

您也可以使用gulp-file

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

gulp.task('version', function () {
    var pkg = require('package.json')

    return gulp.src('src/**')
        .pipe(file('version', pkg.version))
        .pipe(gulp.dest('build/'))
});

或不使用gulp.src()

gulp.task('version', function () {
    var pkg = require('package.json')

    return file('version', pkg.version, {src: true})
        .pipe(gulp.dest('build/'))
});

5

一饮而尽头包可以使用头横幅前缀的文件。

例如。这会将标语注入到您的javascript文件的标题中。

var header = require('gulp-header');
var pkg = require('./package.json');
var banner = ['/**',
  ' * <%= pkg.name %> - <%= pkg.description %>',
  ' * @version v<%= pkg.version %>',
  ' * @link <%= pkg.homepage %>',
  ' * @license <%= pkg.license %>',
  ' */',
  ''].join('\n');

gulp.src('./foo/*.js')
  .pipe(header(banner, { pkg: pkg } ))
  .pipe(gulp.dest('./dist/')

Gulp是利用管道的流式构建系统。

如果您只想编写带有任意字符串的新文件,则可以使用内置节点fs对象。


3

这是2019年有效的答案。

插入:

var Vinyl = require('vinyl');
var through = require('through2');
var path = require('path');

// https://github.com/gulpjs/gulp/tree/master/docs/writing-a-plugin#modifying-file-content
function stringSrc(filename, string) {
    /**
     * @this {Transform}
     */
    var transform = function(file, encoding, callback) {
        if (path.basename(file.relative) === 'package.json') {
            file.contents = Buffer.from(
                JSON.stringify({
                    name: 'modified-package',
                    version: '1.0.0',
                }),
            );
        }

        // if you want to create multiple files, use this.push and provide empty callback() call instead
        // this.push(file);
        // callback();

        callback(null, file);
    };

    return through.obj(transform);
}

在您的吞咽管道中:

gulp.src([
    ...
])
.pipe(stringSrc('version.json', '123'))
.pipe(gulp.dest(destinationPath))

来源:https : //github.com/gulpjs/gulp/tree/master/docs/writing-a-plugin#modifying-file-content

您通过through.obj()传递的函数参数是一个_transform函数,它将对输入文件进行操作。如果需要在流的末尾发出更多数据,则还可以提供可选的_flush函数。

从您的转换函数中调用this.push(file)0次或更多次以传递经过转换/克隆的文件。如果将所有输出提供给callback()函数,则无需调用this.push(file)。

仅在完全消耗了当前文件(流/缓冲区)后才调用回调函数。如果遇到错误,请将其作为第一个参数传递给回调,否则将其设置为null。如果已将所有输出数据传递给this.push(),则可以省略回调的第二个参数。

通常,gulp插件会更新file.contents,然后选择:

调用callback(null,file)或对此this进行一次调用



1

这也可以使用gulp-tap来实现

如果您确定了需要此标头的多个文件,这将特别有用。这是相关的代码(也来自gulp-tap文档)

var gulp = require('gulp'),
    tap = require('gulp-tap');

gulp.src("src/**")
    .pipe(tap(function(file){
           file.contents = Buffer.concat([
             new Buffer('Some Version Header', 'utf8'),
             file.contents
           ]);
         }))
    .pipe(gulp.dest('dist');
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.