Як створити файл із рядка в Gulp?


75

У моєму gulpfile у мене є номер версії у рядку. Я хотів би записати номер версії у файл. Чи є хороший спосіб зробити це в Gulp, чи я повинен розглядати більш загальні API NodeJS?


1
Точна вимога .. Навколо номера версії ... Я хочу використовувати його, щоб додати його до URL-адреси активів для розриву кешу
Akarsh Satija

Відповіді:


76

Якщо ви хочете зробити це залпом, ви можете створити потік "фальшивих" вінілових файлів і дзвонити 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 для створення потоку за допомогою event- stream.
Дарил,

2
Для тих, хто не в курсі потоків, ви можете виконати цю роботу над кількома рядками файлів, повторивши два рядки _readдля кожного файлу. У цьому випадку масив файлових об'єктів буде кращим sting_srcпараметром.
Wes Johnson

Це охопило мій випадок створення потоку для конвеєру з іншими плагінами Gulp по дорозі.
Isiah Meadows

4
Якщо хтось ще не знайомий з node, як я, node надає Bufferяк глобальний ( nodejs.org/api/buffer.html ).
contrebis

Це спрацювало для мене, але this.push(null)видає помилку stream.push() after EOFдля мене, не знаю, чому. Коментуючи, що рядок працює, але потім ковток зависає на невизначений час.
justin.m.покупка

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

1
writeFileфункція тепер асинхронна і вимагає зворотного виклику. Можливо, ви захочете використовувати 'writeFileSync' або краще реагувати і передати зворотний виклик, щоб зробити щось, коли файл фактично записаний на диск.
monzonj

2
Як можна застосувати ланцюжок (pipe?) Для доступу до файлу, створеного з цього? Оскільки це більше метод вузла, я не можу отримати доступ до файлу, створеного в тому ж завданні збірки.
beauXjames

2
@beauXjames ви можете використовувати рішення mjhasbach або просто додати gulp.src('dist/version.txt').pipe(…)після .writeFileSyncрядка.
fregante

2
Дуже сподобалося. Я використав це для створення випадкового рядка для використання як кеш кешу. gist.github.com/cmeza/e5488609d09722bd2c82e954859f36cf
cmeza

28

Це також можна зробити за допомогою вінілового джерела-потоку . Дивіться цей документ у сховищі ковтків.

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

Не могли б ви пояснити process.nextTick(fn() { stream.end(); }?
Шикарний

@Chic Я закінчив потік process.nextTickзворотним викликом, оскільки саме так це було зроблено в документації про ковтання. Здається, це не потрібно, тому я оновив відповідь. Дякуємо, що вказали на це.
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 0

16

Ви також можете використовувати gulp-файл :

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

Пакет 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 - це потокова система побудови, що використовує труби.

Якщо ви просто хочете написати новий файл із довільним рядком, ви можете використовувати вбудований об'єкт fs node .


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

Параметр функції, який ви передаєте через .obj () - це функція _transform, яка буде працювати з вхідним файлом. Ви також можете надати додаткову функцію _flush, якщо вам потрібно випустити трохи більше даних в кінці потоку.

За допомогою функції перетворення викличте this.push (файл) 0 або більше разів, щоб передати перетворені / клоновані файли. Вам не потрібно викликати this.push (файл), якщо ви надаєте всі вихідні дані функції callback ().

Викликайте функцію зворотного виклику лише тоді, коли поточний файл (потік / буфер) повністю споживається. Якщо виявляється помилка, передайте її як перший аргумент зворотного виклику, інакше встановіть для неї значення null. Якщо ви передали всі вихідні дані в this.push (), ви можете пропустити другий аргумент для зворотного виклику.

Як правило, плагін gulp оновлює file.contents, а потім обирає:

виклик зворотного виклику (null, файл) або зробити один дзвінок на this.push (файл)



1

Цього також можна досягти за допомогою залпового крана

Це може бути особливо корисно, якщо ви визначили кілька файлів, для яких потрібен цей заголовок. Ось відповідний код (також із документації про 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');
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.