Search code examples
javascriptnode.jswatchassemblenodemon

NodeJs: external javascript with dependencies


We are trying to use only nodeJS with minimal dependencies to other packages, the challenge we now encounter is HandelbarsJS. We found a package, Assemble who can generate html for us. Only, it is very very slow, about 3 seconds each time, of these 3 seconds, there are 2,5 / 2,7 seconds of the next line:

var assemble = require('assemble');

Our package.json script section:

"scripts": {
  "build:handlebars": "node scripts/handlebars.js",
  "watch:handlebars": "nodemon --watch assets --exec \"npm run build:handlebars\"" }

the script/handlebars.js file

#! /usr/bin/env node

var assemble = require('assemble');
var extname = require('gulp-extname');

console.log(Date.now() - start);

assemble.data('assets/templates/data/*.json');
assemble.layouts('assets/templates/layouts/*.hbs');
assemble.partials('assets/templates/partials/*.hbs');

assemble.src('assets/templates/*.hbs', { layout: 'default' })
    .pipe(extname())
    .pipe(assemble.dest('build/'));

Each time, when we save a .hbs file, Nodemon restart and the external javascript file will be called.

How can we ensure that 'require' get called only once, or whether they remain in memory?

Thank you!


Solution

  • Since you want to accomplish using this with assemble, but without gulp, I recommend chokidar.

    npm install chokidar --save
    

    Now you can require chokidar like this:

    var chokidar = require('chokidar');
    

    Then define a little helper that runs handler whenever something in a pattern changes:

    function watch(patterns, handler) {
      chokidar.watch(patterns, {
        ignoreInitial: false
      }).on('add', handler).on('change', handler).on('unlink', handler);
    }
    

    Now we can alter the script like this:

    #! /usr/bin/env node
    
    var assemble = require('assemble');
    var extname = require('gulp-extname');
    var chokidar = require('chokidar');
    
    console.log(Date.now() - start);
    
    assemble.data('assets/templates/data/*.json');
    assemble.layouts('assets/templates/layouts/*.hbs');
    assemble.partials('assets/templates/partials/*.hbs');
    
    // Enable --watch command line for Chokidar, otherwise, just run!
    if (process.argv.pop() === '--watch') {
      watch('assets', runOnce);
    } else {
      runOnce();
    }
    
    function watch(patterns, handler) {
      chokidar.watch(patterns, {
        ignoreInitial: false
      }).on('add', handler).on('change', handler).on('unlink', handler);
    }
    
    function runOnce() {
      assemble.src('assets/templates/*.hbs', { layout: 'default' })
          .pipe(extname())
          .pipe(assemble.dest('build/'));
    }
    

    And instead of nodemon, this will keep your script alive and running. So, in npm, you want this:

    "scripts": {
      "build:handlebars": "node scripts/handlebars.js",
      "watch:handlebars": "node scripts/handlebars.js --watch"
    }
    

    Whenever a file changes, the script will now run, without re-invoking from scratch.