Using Browserify with a revision manifest in Gulp, getting "Error: write after end"

Using Browserify with a revision manifest in Gulp, getting "Error: write after end"

我正在尝试编译 React 应用程序,将哈希附加到输出文件名并生成修订清单,以便我可以告诉浏览器永远缓存它。问题是所涉及的十几个工具并不能完美地协同工作,至少就我通过尝试吸收他们所有的自述文件和兼顾 .pipe 调用所能弄清楚的而言是这样。

Gulp文件:gist

Gulp 任务:

gulp.task( 'compile:js', function() {
    var browserifyTransform = transform( function( filename ) {
        return browserify( filename )
            .transform( reactify )
            .bundle();
    });

    return gulp.src( 'src/index.js' )
        .pipe( browserifyTransform )
        .pipe( sourcemaps.init({ loadMaps: true }))
        .pipe( uglify() )
        .pipe( rev() )
        .pipe( gulp.dest( 'static/dist' ));
});

更新 精简版,同样错误:

gulp.task( 'compile:js', function() {
    var browserifyTransform = transform( function( filename ) {
        return browserify( filename )
            .transform( reactify )
            .bundle();
    });

    return gulp.src( 'src/index.js' )
        .pipe( browserifyTransform )
        .pipe( gulp.dest( 'static/dist' ));
});

错误堆栈:

[15:55:04] Using gulpfile ~/Projects/pixsplodr/gulpfile.js
[15:55:04] Starting 'compile:js'...

Error: write after end
    at writeAfterEnd (/home/dan/Projects/pixsplodr/node_modules/browserify/node_modules/readable-stream/lib/_stream_writable.js:161:12)
    at Labeled.Writable.write (/home/dan/Projects/pixsplodr/node_modules/browserify/node_modules/readable-stream/lib/_stream_writable.js:208:5)
    at write (_stream_readable.js:601:24)
    at flow (_stream_readable.js:610:7)
    at _stream_readable.js:578:7
    at process._tickCallback (node.js:419:13)

有一些未解决的错误会导致此错误(例如:github.com/hughsk/vinyl-transform/issues/1)。它们的问题在于,当原始 src 流结束时,它会结束仍在使用的可写流。因此错误。 试试这个。

gulp.task( 'compile:js', function() {
    var browserifyTransform = transform( function( filename ) {
        return browserify( filename )
            .transform( reactify )
            .bundle();
    });

    gulp.src( 'src/index.js' )
        .pipe( browserifyTransform )
        .pipe( sourcemaps.init({ loadMaps: true }))
        .pipe( uglify() )
        .pipe( rev() )
        .pipe( gulp.dest( 'static/dist' ));

    return gulp.src( '');
});

通过 return 单独的 gulp.src,gulp 被迫等待初始命令完成,以便 return 新的 src。

嗯,我有满足我要求的解决方案,但它并不完美。

  1. 让 Browserify 从文件名开始流,而不是使用 gulp.src
  2. 在将数据传递给其他 gulp 插件之前,使用 vinyl-source-stream 将 Browserify 的节点流转换为 Gulp 流

我还使用 gulp-rev 将散列附加到生成的文件名,并创建一个将它们映射到原始文件名的清单。

我之前也遇到过源映射问题,但我发现使用 Browserify 转换和设置似乎比在 Browserify 的输出上使用 Gulp 插件更有效。这可能完全是由于用户错误造成的,但我已经看到太多相互冲突的 Browserify / Gulp 示例和我无法以直观方式扩展的最小示例,我很高兴有一个可用的构建我想要的所有功能。

var gulp = require( 'gulp' );
var gutil = require( 'gulp-util' );
var watchify = require( 'watchify' );
var browserify = require( 'browserify' );
var source = require( 'vinyl-source-stream' );
var buffer = require( 'vinyl-buffer' );
var sass = require( 'gulp-sass' );
var _ = require( 'lodash' );
var rev = require( 'gulp-rev' );

// Dev build
gulp.task( 'watch', [ 'sass' ], function() {
    gulp.watch( 'node_modules/quiz/style/**/*.scss', [ 'sass' ]);
    builder( './src/app/index.js', true ).bundle( './dist/static', 'quiz-app.min.js' );
});

// Production build
gulp.task( 'build', [ 'sass' ], function() {
    builder( './src/app/index.js', false ).bundle( './dist/static', 'quiz-app.min.js' );
});

// snip //

function builder( entry, isDev ) {
    var bundler;

    if( isDev ) {
        bundler = watchify( browserify(
            './src/app/index.js',
            _.extend( watchify.args, { debug: true })
        ));
    } else {
        bundler = browserify(
            './src/app/index.js'
        );
    }

    bundler.transform( 'reactify' );
    bundler.transform( 'es6ify' );
    bundler.transform({ global: true }, 'uglifyify' );

    bundler.on( 'log', gutil.log ); // Help bundler log to the terminal

    function bundle( dest, filename ) {
        return bundler.bundle()
        .on( 'error', gutil.log.bind( gutil, 'Browserify error' )) // Log errors during build
        .pipe( source( filename ))
        .pipe( buffer() )
        .pipe( rev() )
        .pipe( gulp.dest( dest ))
        .pipe( rev.manifest() )
        .pipe( gulp.dest( dest ));
    }

    return { bundle: bundle };
}

我也试过只使用 NPM 脚本中的工具,但我无法找到在观察一组文件时进行增量构建的好方法。

我使用 gulp-streamify 包解决了这个问题。

我不得不重写我的任务如下:

gulp        = require('gulp');
rev         = require('gulp-rev');          // add hash to filename
rimraf      = require('gulp-rimraf');       // delete folder
gulpsync    = require('gulp-sync')(gulp);   // sync gulp task 
babel       = require('gulp-babel');        // es6 transpiler
browserify  = require('browserify');        
source      = require('vinyl-source-stream');
streamify   = require('gulp-streamify');


gulp.task('compile-es6', function(){
  var stream =  browserify('app/assets/javascript/application.js')
    .transform("babelify", {presets: ["es2015"]})
    .bundle();

  return stream.pipe(source('bundle.js'))
    .pipe(streamify(rev()))
    .pipe(gulp.dest('public/javascripts'))
    .pipe(rev.manifest('./rev-manifest.json',{merge:true}))
    .pipe(gulp.dest(''));
});