These are chat archives for jescalan/roots

12th
Dec 2016
Les intendants IT
@IntendantsIt_twitter
Dec 12 2016 01:27

Okay so I have tried something. First I want to say that i'm a beginner with node.js tech (npm, browserify & co). So I can be totally wrong.
I have been seduceed by mojotech architecture (roots + page.js) so i'm bulding a website, trying to follow the same global concepts. Today I've found the first limit by using browserify in this kind of architecture : JS is compiled in a single (potentially big) file that will be used for every pages, even if they have different requirements (i.e one page needs three.js, another one doens't ...)
My understanding is that factor-bundle gives us ability to make js output files more "tailored", so to speak.
So I just come back with this test:

in app.coffee :

    browserify
      files: [
        'assets/js/common.coffee'
        'assets/js/page1.coffee'
      ]
      out: 'js/bundle.js'
      factor: true
      minify: false
      transforms: ['coffeeify']

In roots-browserify/lib/index.js, First modification (add factor to opts) :

    opts = _.defaults(opts, {
      files: 'js/main.js',
      opts: {
        extensions: ['.js', '.json', '.coffee']
      },
      minify: false,
      factor: false,
      sourceMap: false,
      transforms: [coffeeify]
    });

Second modification (if (opts.factor) block) :

     Browserify.prototype.category_hooks = function() {
        return {
          after: (function(_this) {
            return function(ctx) {
              var changed, deferred, map_path, out_path, stream, writer;
              deferred = W.defer();
              out_path = path.join(_this.roots.config.output_path(), opts.out);
              changed = ctx.roots.file_changed;
              if (changed) {
                invalidate.call(_this, changed);
              }

              if (opts.factor) {
                factor_outputs = _this.files.map(function(file) {
                  return path.join(path.parse(out_path).dir, path.parse(file).name + '.js');
                });
                _this.b.plugin('factor-bundle', { outputs: factor_outputs });
              }

              stream = _this.b.bundle();
              if (opts.sourceMap) {
                map_path = out_path.replace(path.extname(out_path), '') + '.js.map';

                /*
                 * Convert output paths to be relative
                 * to roots project instead of absolute paths
                 * https://github.com/substack/node-browserify/issues/663
                 */
                stream = stream.pipe(mold.transformSourcesRelativeTo(_this.roots.root || '')).pipe(exorcist(map_path));
              }
              writer = fs.createWriteStream(out_path);
              stream.pipe(writer);
              stream.on('error', deferred.reject);
              writer.on('error', deferred.reject);
              writer.on('finish', deferred.resolve);
              return deferred.promise;
            };
          })(this)
        };
      };

Looks like it works like expected.
It could give me the ability to call specific js for any page on the fly with page.js.
Do you guys think it's a good idea ? or overcomplicated ?

Last point :
I noticed that "extensions" aren't real options in roots-browserify because they are hardcoded in browserify constructor :

        this.b = browserify({
          entries: this.files,
          extensions: ['.js', '.json', '.coffee'],
          debug: opts.sourceMap,
          cache: this.cache,
          packageCache: this.pkg_cache
        });

See you ! Mat

Jeff Escalante
@jescalan
Dec 12 2016 03:19
hey @IntendantsIt_twitter -- wow this is great!
thanks for the deep dive and kind words
so what you're talking about here I think is generally referred to as code splitting
I haven't done it specifically with browserify, although webpack (and therefore spike) would probably be quite good at it
and also can run the same type of mojotech architecture
this is an example of how to compile a file to a client template as well as a static template
for the code you dropped here on the browserify extension, could you make a pull request with this code? it would be a lot easier for me to review this way :)
it looks good from my cursory scan though!