Benjamin Buch
Benjamin Buch

Reputation: 610

Metalsmith plugin: Why ist the tiny-lr server started twice?

I'm trying to write a metalsmith plugin that rebuilds files on file change and reloads the page via tiny-lr.

Watching and rebuilding works fine, but when a file is changed, the tiny-lr server is started again – which results in an error because the server is allready running.

Here's the plugin code:

module.exports = plugin;

var gaze    = require('gaze'),
    chalk   = require('chalk'),
    tinylr  = require('tiny-lr');


function plugin(){
  return function(files, metalsmith, done){

    var port    = 35729,
        server  = tinylr();

    server.listen(port, function(){
      console.log(chalk.cyan('Listening on port', port));
    });

    gaze(['templates/*', 'src/**/*'], function(err, watcher) {

      console.log(chalk.green('Watching files'));

      this.on('changed', function(filepath) {

        console.log(chalk.red(filepath) + chalk.blue(' was changed.'));
        console.log(chalk.yellow('Rebuilding files...'));

        metalsmith.build(function(err, files){
          console.log(chalk.blue('Build successful'))
        });
      });
    });
    done();
  }
}

Console output when a file is changed:

Listening on port 35729
Watching files
/Users/benjamin/metal/src/content/index.md was changed.
Rebuilding files...

... Uhoh. Got error listen EADDRINUSE ...
Error: listen EADDRINUSE
    at errnoException (net.js:901:11)
    at Server._listen2 (net.js:1039:14)
    at listen (net.js:1061:10)
    at Server.listen (net.js:1127:5)
    at Server.listen (/Users/benjamin/Desktop/metal/node_modules/metalsmith-watchall/node_modules/tiny-lr/lib/server.js:145:15)
    at /Users/benjamin/Desktop/metal/node_modules/metalsmith-watchall/index.js:26:12
    at next (/Users/benjamin/Desktop/metal/node_modules/metalsmith/node_modules/ware/lib/index.js:68:8)
    at /Users/benjamin/Desktop/metal/node_modules/metalsmith-templates/node_modules/async/lib/async.js:119:25
    at /Users/benjamin/Desktop/metal/node_modules/metalsmith-templates/node_modules/async/lib/async.js:24:16
    at convert (/Users/benjamin/Desktop/metal/node_modules/metalsmith-templates/lib/index.js:67:32)
Watching files
Build successful

Why is the server started a second time?

How can I prevent it from being started?

Bonus question:

Why are the console messages not in the order that I would expect from looking at the code? Especially, why does "Build sucessful" appear after "Watching files"? I would think it should appear directly after "Rebuilding files...".

Upvotes: 1

Views: 347

Answers (1)

Benjamin Buch
Benjamin Buch

Reputation: 610

Still clueless why the example above doesn't work, but here's something I came up with that does (thanks chuck for reminding me to post a solution...)

module.exports = plugin;

var gaze    = require('gaze'),
    chalk   = require('chalk'),
    tinylr  = require('tiny-lr');


var watchall = {
  running: false
};

function startLiveReloadServer(){
  var port    = 35729,
      server  = tinylr();
  server.listen(port, function(){
    console.log(chalk.cyan('Listening on port', port));
  });
  watchall.server = server;
};

function startWatcher(metalsmith, files, done){
  gaze(['templates/*', 'src/**/*'], function(err, watcher) {
    console.log(chalk.green('Watching files'));
    this.on('changed', function(filepath) {
      console.log(chalk.red(filepath) + chalk.blue(' was changed.'));
      console.log(chalk.yellow('Rebuilding files...'));
      metalsmith.build(function(err, files){
        console.log(chalk.blue('Build successful'))
        watchall.server.changed({body:{files:Object.keys(files)}});
      });
    });
  });
  done();
};

function plugin(){
  return function(files, metalsmith, done){
    if ( watchall.running === false ) {
      startLiveReloadServer();
      startWatcher(metalsmith, files, done);
      watchall.running = true;
    } else {
      done();
    };
  }
}

Upvotes: 1

Related Questions