【问题标题】:How do you create a file from a string in Gulp?如何在 Gulp 中从字符串创建文件?
【发布时间】:2014-04-22 21:29:31
【问题描述】:

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

【问题讨论】:

  • 确切要求..围绕版本号...我想用它来将其附加到资产 url 以进行缓存爆破

标签: node.js gulp


【解决方案1】:

如果您想以类似 gulp 的方式执行此操作,您可以创建一个“假”乙烯基文件流,并照常致电 pipe。这是一个用于创建流的函数。 “stream”是一个核心模块,所以你不需要安装任何东西:

const Vinyl = require('vinyl')

function string_src(filename, string) {
  var src = require('stream').Readable({ objectMode: true })
  src._read = function () {
    this.push(new Vinyl({
      cwd: "",
      base: "",
      path: filename,
      contents: Buffer.from(string, 'utf-8')
    }))
    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 来创建流。
  • 对于那些不了解流的人,您可以通过为每个文件重复 _read 中的两行来处理多个文件字符串。在这种情况下,文件对象数组将是更好的sting_src 参数。
  • 这涵盖了我创建流以与其他 Gulp 插件进行管道传输的用例。
  • 如果其他人跟我一样不熟悉node,node提供Buffer作为全局(nodejs.org/api/buffer.html)。
  • 这对我有用,但 this.push(null) 对我抛出错误 stream.push() after EOF,不知道为什么。注释掉该行有效,但随后 gulp 无限期挂起。
【解决方案2】:

它几乎是一个单行节点:

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);

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

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

【讨论】:

  • 这可能是最好的方法(除非您使用的是 ShellJS)。
  • writeFile 函数现在是异步的,需要回调。您可能希望使用“writeFileSync”或更好的响应式,并在文件实际写入磁盘时传递回调以执行某些操作。
  • 如何链接(管道?)以访问由此创建的文件?由于它更像是一种节点方法,因此我无法访问在同一构建任务中创建的文件。
  • @beauXjames 您可以使用mjhasbach's solution 或在.writeFileSync 行之后添加gulp.src('dist/version.txt').pipe(…)
  • 喜欢它。我用它来生成一个随机字符串以用作缓存破坏器。 gist.github.com/cmeza/e5488609d09722bd2c82e954859f36cf
【解决方案3】:

这也可以通过vinyl-source-stream 完成。请参阅 gulp 存储库中的 this document

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(),这可能是最干净的节点方式
  • 你能解释一下process.nextTick(fn() { stream.end(); }吗?
  • @Chic 我在process.nextTick 回调中结束了流,因为这是在 gulp 文档中完成的。似乎没有必要,所以我更新了答案。感谢您指出这一点。
【解决方案4】:

根据 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 使用默认设置创建文件,如果它不存在。
【解决方案5】:

你也可以使用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/'))
});

【讨论】:

    【解决方案6】:

    gulp-header 包可用于为带有标题横幅的文件添加前缀。

    例如。这将在您的 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 是一个利用管道的流式构建系统。

    如果你只是想用任意字符串写一个新文件,你可以使用内置的node fs对象。

    【讨论】:

      【解决方案7】:

      使用string-to-streamvinyl-source-stream 模块:

      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'));
      

      【讨论】:

        【解决方案8】:

        这是一个适用于 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 管道中:

        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

        你通过.obj() 传递的函数参数是一个_transform 将对输入文件进行操作的函数。您还可以提供一个 如果您需要在 流的结尾。

        在您的转换函数中调用 this.push(file) 0 或更多 传递转换/克隆文件的时间。你不需要打电话 this.push(file) 如果你向 callback() 函数提供所有输出。

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

        一般来说,gulp 插件会更新 file.contents 然后选择 要么:

        调用 callback(null, file) 或调用 this.push(file)

        【讨论】:

          【解决方案9】:

          这也可以使用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');
          

          【讨论】:

            猜你喜欢
            • 1970-01-01
            • 1970-01-01
            • 2020-07-22
            • 1970-01-01
            • 2018-03-30
            • 1970-01-01
            • 1970-01-01
            • 2010-09-24
            相关资源
            最近更新 更多