jakejs / jake

JavaScript build tool, similar to Make or Rake. Built to work with Node.js.
http://jakejs.com
Apache License 2.0
1.97k stars 190 forks source link

"jake watch" not working with global modules? #262

Closed cedx closed 10 years ago

cedx commented 10 years ago

I'm unable to make jake watch task working at all (not even a single time! Do I need to change my brain?).

My config: Node.js 0.10.29 and Jake 0.7.17 on Windows 8.1.

I think there are several issues involved, so let's start with the most obvious problem : jake watch does not seem to work with global-only modules.

Here is my Jakefile:

'use strict';

desc('Builds the assets.');
task('default', [ 'css', 'js' ]);

desc('Builds the stylesheets.');
task('css', function() {
  jake.logger.log('Build the stylesheets...');
  jake.exec([
    'lessc --source-map-map-inline lib/ui/styles/main.less www/css/main.css',
    'cleancss --output www/css/main.min.css www/css/main.css'
  ]);
});

desc('Builds the client scripts.');
task('js', function() {
  jake.logger.log('Build the client scripts...');
  jake.exec([
    'browserify lib/client/main.js --debug --outfile www/js/main.js',
    'uglifyjs www/js/main.js --compress --mangle --output www/js/main.min.js --screw-ie8'
  ]);
});

watchTask([ 'css', 'js' ], function() {
  this.watchFiles.exclude('Jakefile.js');
});

When I launch jake watch and change a file, an error occurs:

> jake watch
WatchTask started for: css, js
Could not read path node_modules
Error: ENOENT, no such file or directory 'C:\repo\mda-sms.php\node_modules'
    at Object.fs.readdirSync (fs.js:659:18)
    at _readDir (C:\Program Files\Node.js\node_modules\jake\node_modules\utilities\lib\file.js:137:18)
    at EventEmitter.fileUtils.readdirR (C:\Program Files\Node.js\node_modules\jake\node_modules\utilities\lib\file.js:353:11)
    at globSync (C:\Program Files\Node.js\node_modules\jake\lib\file_list.js:30:18)
    at _calculateExcludeRe (C:\Program Files\Node.js\node_modules\jake\lib\file_list.js:159:25)
    at _resolveExclude (C:\Program Files\Node.js\node_modules\jake\lib\file_list.js:185:29)
    at FileList.resolve (C:\Program Files\Node.js\node_modules\jake\lib\file_list.js:267:23)
    at self.(anonymous function) [as slice] (C:\Program Files\Node.js\node_modules\jake\lib\file_list.js:103:14)
    at FileList.toArray (C:\Program Files\Node.js\node_modules\jake\lib\file_list.js:277:20)
    at C:\Program Files\Node.js\node_modules\jake\lib\watch_task.js:25:39

There is no node_modules folder: my project only uses a few global modules (e.g. modules installed with npm install -g <module>). Why Jake is looking for node_modules folder even if it doesn't exist?

If I create this folder, or if I use local modules, this task still doesn't work. But I'm still investigating... Does anyone has succeed in using watch tasks on Windows 8.1?

Off topic: I think watch task should explicitly ignore the Jakefile. It's quite common to name it Jakefile.js or Jakefile.coffee, but it's insane to trigger the watch cycle everytime we modify the Jakefile or to ignore it explictly.

mde commented 10 years ago

Looks like it's blowing up trying to calculate the exclusions -- indeed node_modules is in the default exclude list: https://github.com/jakejs/jake/blob/master/lib/watch_task.js#L45 This is a pretty bad bug.

I'm not sure why it would still not work if you actually have the exclusion directories it wants. I seem to remember there being issues with watch on Windows, but that was some time back. I would have thought it would be working reliably by now.

You're absolutely right -- we shouldn't require people to ignore the Jakefile explicitly, even if it has a .js extension (but of course shouldn't require its presence either -- this is a bug).

I've opened a ticket for this bug: https://github.com/jakejs/jake/issues/263 Thanks for catching this!

cedx commented 10 years ago

I think you can close this issue : as you said, ENOENT, no such file or directory is clearly related to the default exclusion list of watch task.

For the second part (task not working even with a node_modules directory), I think this is related to the implementation of fs.watch/watchFile on (this fucking) Windows. If I try with a custom code, instead of Jake's watch task, the result is the same : no event is triggered when a change occurs :(

I'm trying to see how Isaacs succeeded to catch file events in its node-supervisor module (which works on Windows !).

mde commented 10 years ago

Let me know what you find out.

cedx commented 10 years ago

Very disappointing... I saw nothing special in the code of node-supervisor, which uses fs.watchFile.

So, I made some tests : I tried to watch a "cli.js" file in a "bin" directory, using the following Jakefile. The results are shown in the comments:

'use strict';

var fs=require('fs');

namespace('fsWatch', function() {
  desc('File with fs.watch()');
  task('file', function() {
    fs.watch('bin/cli.js', function() {
      jake.logger.log('fs.watch(file) => callback called');
      // RESULT: Callback called 2 times on each 'change' event.
    });
  });

  desc('Directory with fs.watch()');
  task('dir', function() {
    fs.watch('bin', function() {
      jake.logger.log('fs.watch(dir) => callback called');
      // RESULT: Callback called 2 times on each 'change' event.
    });
  });
});

namespace('fsWatchFile', function() {
  desc('File with fs.watchFile()');
  task('file', function() {
    fs.watchFile('bin/cli.js', { interval: 1000 }, function() {
      jake.logger.log('fs.watchFile(file) => callback called');
      // RESULT: Callback called one time on each 'change' event.
    });
  });

  desc('Directory with fs.watchFile()');
  task('dir', function() {
    fs.watchFile('bin', { interval: 1000 }, function() {
      jake.logger.log('fs.watchFile(dir) => callback called');
      // RESULT: Callback never called.
    });
  });
});

desc('Task used as prerequisite for jake.watchTask');
task('log', function() {
  jake.logger.log('jake.watchTask => prerequesite called');
});

watchTask([ 'log' ], function() {
  this.watchFiles.include([ 'bin/cli.js' ]);
  // RESULT: Prerequesite never called.
});

Only the call to fs.watchFile('bin/cli.js') gave the expected results. Can someone can confirm that on a Windows OS? Am I doing something wrong?

cedx commented 10 years ago

I gave up: I finally implemented a custom task using nodemon as a required module.

I close this issue as 2 things were involved:

mde commented 10 years ago

Thanks so much for following up on this. Node generally does a good job of being cross-platform, but it still falls down pretty hard in some areas. #263 is fixed in 9239f6c0525be64c8dce09a28fc9b44236488266