explainer
explainer

Reputation: 1335

gulp-concat throws exception 'file.isNull(), index.js:39 TypeError: file.isNull is not a function

I am attempting to compile react (.jsx), coffeescript (.coffee), and vanilla javascript (.js) files using gulp to package all of the resulting .js files into one file, app.js, which gets loaded into my index.html page. I am generating a stream for each compilation type and using merge-stream to collect the contents of the 3 feeder streams into a single stream, which I am passing to gulp-concat to create app.js.

I am getting an exception from gulp-concat, index.js, line 39, letting me know that 'file' is not a function. Here is my entire gulpfile.js, the reference to gulp-concat is near the bottom of this section.

var browserify = require('browserify');
var coffee = require('gulp-coffee');
var concat = require('gulp-concat');
var gulp = require('gulp');
var gutil = require('gulp-util');
var mergeStream = require('merge-stream');
var reactify = require('reactify');
var sass = require('gulp-sass');
var source = require('vinyl-source-stream');

gulp.task('javascript', function(){
  // convert .jsx files to .js, collecting them in a stream
  var b = browserify();
  b.transform(reactify); // use the reactify transform
  b.add('./jsx-transforms.js');
  jsxStream = b.bundle();
  if (gutil.isStream(jsxStream)) {
    gutil.log("jsxStream is a stream");
  } else {gulp-concatgulp
    gutil.log("jsxStream is not a stream");
  }

  merged = mergeStream(jsxStream);
  if (gutil.isStream(merged)) {
    gutil.log("merged is a stream");
  } else {
    gutil.log("merged is not a stream");
  }

  // collect all .js files in a stream
  jsStream = gulp.src(['./client/**/*.js','./common/**/*.js']);
  if (gutil.isStream(jsStream)) {
    gutil.log("jsStream is a stream");
  } else {
    gutil.log("jsStream is not a stream");
  }
  merged.add(jsStream);

  // compile all .coffee file to .js, collect in a stream
  coffeeStream = gulp.src(['./client/**/*.coffee','./common/**/*.coffee'])
    .pipe(coffee({bare: true}).on('error', gutil.log));
  if (gutil.isStream(coffeeStream)) {
    gutil.log("coffeeStream is a stream");
  } else {
    gutil.log("coffeeStream is not a stream");
  }
  merged.add(coffeeStream);

  // concatenate all of the .js files into ./build/app.js
  merged
    .pipe(concat('app.js'))
    .pipe(gulp.dest('./build'));
});

gulp.task('styles', function() {
  gulp.src('./client/assets/stylesheets/**/*.scss')
    .pipe(sass().on('error', sass.logError))
    .pipe(concat('app.css'))
    .pipe(gulp.dest('./build'));
});

gulp.task('default', ['javascript', 'styles']);

I have used gulp-concat before, but never hit this problem before.

Upvotes: 1

Views: 1127

Answers (1)

McMath
McMath

Reputation: 7188

Gulp streams are a very particular sort of stream: they are Node streams in object mode containing vinyl file objects. If your stream comes from somewhere other than gulp.src(), such as from the browserify API, then you will have to first convert the stream into the sort that gulp can deal with.

There are two steps you need to take. First, convert your browserify bundle stream into a stream containing a vinyl file object with vinyl-source-stream (which you have required but not used).

var source = require('vinyl-source-stream');

...

var jsxStream = b.bundle()
  .pipe(source('bundle.js'));

Now there is another catch. Vinyl streams may be in one of two modes: streaming mode or buffer mode. Vinyl-source-stream gives you a stream in streaming mode. Many Gulp plugins, including gulp-concat, only support buffer mode. The fix for this is easy: use vinyl-buffer.

var source = require('vinyl-source-stream');
var buffer = require('vinyl-buffer');

...

var jsxStream = b.bundle()
  .pipe(source('bundle.js'))
  .pipe(buffer());

Now you have something you can merge with your other streams and pipe to gulp-concat. For more detail, see this recipe.

Upvotes: 6

Related Questions