How to inform browserify about extra dependencies within a transform module?

48 views Asked by At

I created a browserify transform to transform .pug files to preparsed Ractive JSON objects. That operation requires to transform Pug files to HTML and then pass to the Ractive.parse() function.

What doesn't work after initial build is that when I change a relative Pug file, browserify doesn't recompile the parent file, so the change is not reflected to the bundle file. I'm using watchify to watch the file changes.

Consider the following hello.js file:

var x = require('./index.pug')
...

and index.pug file:

b hello 
include ./a.pug

I can obtain ["/path/to/index.pug", "/path/to/a.pug"] inside my transform function. How can I pass it to the browserify to invalidate its relevant cache whenever index.pug or a.pug has been changed within the transform function?

My transform function is as follows:

var through2 = require('through2')

preparsePug = function(file, contents){
  // returns {
  //     dependencies (Array), 
  //     parsed (String)
  //  }
  ...
}

function isTemplate(file){
  return /.*\.(pug)$/.test(file);
}
exports.ractivePreparserify = function(file){
  var contents, write, flush;
  if (!isTemplate(file)) {
    return through();
  }
  contents = '';
  write = function(chunk, enc, next){
    contents += chunk.toString('utf-8');
    next();
  };
  flush = function(cb){
    try {
      var x = preparsePug(file, contents);
      this.push("module.exports = " + JSON.stringify(x.parsed));
      return cb();
    } catch (err) {
      console.error("Preparserify error: ", err);
      return this.emit('error', err);
    }
  };
  return through2.obj(write, flush);
};
1

There are 1 answers

0
ceremcem On

It's the watchify module that does the actual caching between builds. watchify uses browserify's internal cache under the hood, but still we send our signal to watchify to make browserify rebuild on dependency changes.

As can be seen in the source code, a transform informs its browserify instance through watchify about its dependencies by this.emit('file', dependency) signal.

Above ractivePreparserify function should be:

through = require('through');

ractivePreparserify = function(file){
  var contents, write, end;
  if (!isTemplate(file)) {
    return through();
  }
  contents = '';
  write = function(chunk){
    contents += chunk.toString('utf-8');
  };
  end = function(){
    var x, i$, x$, ref$, len$, e;
    try {
      var x = preparsePug(file, contents);
      for (var i = 0; i < x.dependencies.length; i++) {
        this.emit('file', x.dependencies[i]); // <----- Informs browserify about dependencies.
      }
      this.queue("module.exports = " + JSON.stringify(x.parsed));
    } catch (e$) {
      e = e$;
      console.error("Preparserify error: ", e);
      this.emit('error', e);
    }
    return this.queue(null);
  };
  return through(write, end);
};

In order this to work, browserify should be configured exactly as explained here.