Wie erstellt man eine Datei aus einer Zeichenfolge in Gulp?

74

In meiner Gulpfile habe ich eine Versionsnummer in einer Zeichenfolge. Ich möchte die Versionsnummer in eine Datei schreiben. Gibt es eine gute Möglichkeit, dies in Gulp zu tun, oder sollte ich mir allgemeinere NodeJS-APIs ansehen?

Daryl
quelle
1
Genaue Anforderung .. Um Versionsnummer ... Ich möchte es verwenden, um es an Assets-URL für Cache-
Bursts anzuhängen

Antworten:

74

Wenn Sie dies schluckartig tun möchten, können Sie einen Stream von "gefälschten" Vinyl-Dateien erstellen und wie pipegewohnt aufrufen . Hier ist eine Funktion zum Erstellen des Streams. "stream" ist ein Kernmodul, Sie müssen also nichts installieren:

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
}

Sie können es so verwenden:

gulp.task('version', function () {
  var pkg = require('package.json')
  return string_src("version", pkg.version)
    .pipe(gulp.dest('build/'))
})
Christoph Neumann
quelle
Am Ende habe ich das im Grunde genommen gemacht, aber mit readArray von event-stream , um den Stream zu erstellen.
Daryl
2
Für diejenigen, die mit Streams nicht auf dem neuesten Stand sind, können Sie diese Zeichenfolge für mehrere Dateien verwenden, indem Sie die beiden Zeilen _readfür jede Datei wiederholen . In diesem Fall wäre ein Array von Dateiobjekten ein besserer sting_srcParameter.
Wes Johnson
Dies deckte meinen Anwendungsfall ab, einen Stream zu erstellen, der später mit anderen Gulp-Plugins weitergeleitet wird.
Isiah Meadows
4
Wenn jemand mit dem Knoten so wenig vertraut ist wie ich, stellt der Knoten Buffereinen globalen Knoten bereit ( nodejs.org/api/buffer.html ).
Contrebis
Das hat bei mir funktioniert, this.push(null)wirft aber einen Fehler stream.push() after EOFfür mich auf, nicht sicher warum. Das Auskommentieren dieser Zeile funktioniert, aber dann hängt der Schluck auf unbestimmte Zeit.
justin.m.chase
75

Es ist so ziemlich ein Einzeiler im Knoten:

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

Oder von package.json:

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

Ich verwende es, um ein Erstellungsdatum in einer leicht zugänglichen Datei anzugeben, daher verwende ich diesen Code vor dem return gulp.src(...)in der buildAufgabe üblichen :

require('fs').writeFileSync('dist/build-date.txt', new Date());
fregante
quelle
Dies ist wahrscheinlich der beste Weg, dies zu tun (es sei denn, Sie verwenden ShellJS).
Isiah Meadows
1
writeFileDie Funktion ist jetzt asynchron und erfordert einen Rückruf. Möglicherweise möchten Sie 'writeFileSync' verwenden oder besser reaktiv sein und einen Rückruf übergeben, um etwas zu tun, wenn die Datei tatsächlich auf die Festplatte geschrieben ist.
Monzonj
2
Wie geht man vor, um auf die daraus erstellte Datei zuzugreifen? Da es sich eher um eine Knotenmethode handelt, kann ich nicht auf die Datei zugreifen, die mit derselben Erstellungsaufgabe erstellt wurde.
beauXjames
2
@beauXjames Sie können die Lösung von mjhasbach verwenden oder einfach gulp.src('dist/version.txt').pipe(…)nach der .writeFileSyncZeile hinzufügen .
Fregante
1
Liebte es. Ich habe dies verwendet, um eine zufällige Zeichenfolge zu generieren, die als Cache-Buster verwendet werden soll. gist.github.com/cmeza/e5488609d09722bd2c82e954859f36cf
cmeza
28

Dies kann auch mit Vinyl-Source-Stream erfolgen . Siehe dieses Dokument im Gulp-Repository.

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'));
});
mjhasbach
quelle
Dies ist wahrscheinlich der sauberste Knoten Weg, wenn Sie verwenden möchten.pipe()
fregante
Könnten Sie das erklären process.nextTick(fn() { stream.end(); }?
Chic
@Chic Ich habe den Stream in einem process.nextTickRückruf beendet, weil dies in der gulp-Dokumentation so gemacht wurde. Es scheint nicht notwendig zu sein, deshalb habe ich die Antwort aktualisiert. Vielen Dank für den Hinweis.
Mjhasbach
22

Laut dem Betreuer von Gulp ist die bevorzugte Methode zum Schreiben einer Zeichenfolge in eine Datei die Verwendung fs.writeFiledes Task-Rückrufs.

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

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

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

GOTO 0
quelle
Das einzige Problem dabei ist, dass die Datei vorhanden sein muss. Gibt es kein Flag, mit dem diese Datei erstellt werden kann, wenn sie nicht vorhanden ist?
Serj Sagan
@SerjSagan Nicht sicher, was dieses Verhalten verursachen könnte. writeFile mit den Standardeinstellungen erstellt die Datei, wenn sie nicht vorhanden ist.
GOTO 0
16

Sie können auch gulp-file verwenden :

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

oder ohne Verwendung gulp.src():

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

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

Das gulp-header- Paket kann verwendet werden, um Dateien mit Header-Bannern voranzustellen.

z.B. Dadurch wird ein Banner in den Header Ihrer Javascript-Dateien eingefügt.

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 ist ein Streaming-Build-System, das Pipes nutzt.

Wenn Sie einfach eine neue Datei mit einer beliebigen Zeichenfolge schreiben möchten, können Sie das integrierte Knoten-fs- Objekt verwenden.

Mike Causer
quelle
3

Hier ist eine Antwort, die 2019 funktioniert.

Plugin:

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

Und in Ihrer Schluck-Pipeline:

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

Aus der Quelle: https://github.com/gulpjs/gulp/tree/master/docs/writing-a-plugin#modifying-file-content

Der Funktionsparameter, den Sie an through.obj () übergeben, ist eine _transform-Funktion, die die Eingabedatei bearbeitet. Sie können auch eine optionale _flush-Funktion bereitstellen, wenn Sie am Ende des Streams etwas mehr Daten ausgeben müssen.

Rufen Sie innerhalb Ihrer Transformationsfunktion this.push (Datei) 0 oder mehrmals auf, um transformierte / geklonte Dateien weiterzugeben. Sie müssen this.push (Datei) nicht aufrufen, wenn Sie die gesamte Ausgabe für die Funktion callback () bereitstellen.

Rufen Sie die Rückruffunktion nur auf, wenn die aktuelle Datei (Stream / Puffer) vollständig belegt ist. Wenn ein Fehler auftritt, übergeben Sie ihn als erstes Argument an den Rückruf, andernfalls setzen Sie ihn auf null. Wenn Sie alle Ausgabedaten an this.push () übergeben haben, können Sie das zweite Argument für den Rückruf weglassen.

Im Allgemeinen würde ein gulp-Plugin file.contents aktualisieren und dann Folgendes auswählen:

Rückruf (null, Datei) aufrufen oder this.push (Datei) einmal aufrufen

William Bernting
quelle
2

Verwenden der String-to-Stream- und Vinyl-Source-Stream- Module:

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'));
Jonas Berlin
quelle
1

Dies kann auch mit einem Schluckhahn erreicht werden

Dies kann besonders hilfreich sein, wenn Sie mehrere Dateien identifiziert haben, für die dieser Header erforderlich ist. Hier ist relevanter Code (auch aus der Gulp-Tap-Dokumentation)

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