关于node.js:如何从Gulp中的字符串创建文件?

How do you create a file from a string in Gulp?

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


这几乎是节点中的一线:

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

或从package.json中获取:

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

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

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


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

1
2
3
4
5
6
7
8
9
10
11
12
13
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
}

您可以像这样使用它:

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


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

1
2
3
4
5
6
7
8
9
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'));
});


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

1
2
3
4
5
6
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


您也可以使用gulp-file:

1
2
3
4
5
6
7
8
9
10
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()

1
2
3
4
5
6
gulp.task('version', function () {
    var pkg = require('package.json')

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


gulp-header包可用于为文件添加标头横幅前缀。

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

1
2
3
4
5
6
7
8
9
10
11
12
13
14
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('\
');

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

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

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


这是在2019年有效的答案。

插入:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
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);
}

在您的吞咽管道中:

1
2
3
4
5
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

The function parameter that you pass to through.obj() is a _transform
function which will operate on the input file. You may also provide an
optional _flush function if you need to emit a bit more data at the
end of the stream.

From within your transform function call this.push(file) 0 or more
times to pass along transformed/cloned files. You don't need to call
this.push(file) if you provide all output to the callback() function.

Call the callback function only when the current file (stream/buffer)
is completely consumed. If an error is encountered, pass it as the
first argument to the callback, otherwise set it to null. If you have
passed all output data to this.push() you can omit the second argument
to the callback.

Generally, a gulp plugin would update file.contents and then choose to
either:

call callback(null, file) or make one call to this.push(file)


使用字符串流和乙烯基源流模块:

1
2
3
4
5
var str = require('string-to-stream');
var source = require('vinyl-source-stream');
var gulp = require('gulp');

str('1.4.27').pipe(source('version.txt')).pipe(gulp.dest('dist'));

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

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

1
2
3
4
5
6
7
8
9
10
11
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');