grunt-contrib-watch + grunt-rsync

3

我正在尝试使用grunt-contrib-watchgrunt-rsync将任何文件更改上传到我的开发服务器。以下是我的设置:

var path = require('path');

module.exports = function(grunt) {
    grunt.initConfig({
        pkg: grunt.file.readJSON('package.json'),

        ...

        watch: {
            upload: {
                files: ['*'],
            },
            ...
        },

        rsync: {
            options: {
                args: ['--verbose'],
                exclude: ['.*','node_modules','sql','artifacts','session','logs','cache'],
                recursive: true,
                syncDestIgnoreExcl: true
            },
            dev: {
                options: {
                    src: './',
                    dest: '/usr/local/project',
                    host: 'dev3',
                }
            }
        },
    });

    grunt.event.on('watch', function(action, filepath, target) {
        if(target!=='upload') return;
        grunt.config('rsync.dev.options.src', filepath);
        grunt.task.run('rsync:dev');
    });

    grunt.loadNpmTasks('grunt-contrib-watch');
    grunt.loadNpmTasks('grunt-rsync');
    ...
};

rsync 任务本身表现良好;它可以相对快速地上传整个项目,但并不足够快以在每次编辑文件时运行。

我正在尝试使用 grunt.event.on 在再次运行任务之前修改 src,使其只上传一个文件。然而,grunt.task.run('rsync:dev') 看起来根本没有任何作用。它没有引发错误,也没有任何输出。下面是我运行它并创建新文件时的输出:

$ grunt watch:upload --debug --stack
Running "watch:upload" (watch) task
Waiting...OK
>> File "ppp" added.

如果我提供了一个无效的任务名称,它会出现错误,因此显然它正在寻找任务,我不确定它正在执行什么操作。该文件从未到达我的服务器。
如何让它仅同步我保存的文件?
注意:newer 似乎也不起作用,因此我正在尝试通过 grunt.event.on('watch' 手动完成此操作。
2个回答

2

即使使用Kyle的解决方案grunt-contrib-watch在Linux上仍然太慢了。我发现另一个库,grunt-este-watch运行得更快,而且可以在每次更改之前更新rsync配置而无需进行任何hackery。我的设置现在看起来像这样:

esteWatch: {
    options: {
        dirs: [
            '**/',
            '!node_modules/**/',
            '!sql/**/',
            '!artifacts/**/',
            '!session/**/',
            '!logs/**/',
            '!cache/**/',
            '!plugins/ezc/**/',
        ],
        livereload: {
            enabled: true,
            port: 35729,
            extensions: ['css'],
        }
    },
    '*': function(filepath) {
        if(grunt.file.isMatch(['**/*___jb*'],filepath)) return []; // ignore temporary JetBrains files
        var tasks = ['rsync'];
        if(grunt.file.isMatch(grunt.config('uglify.dist.src'),filepath)) tasks.push('uglify');
        if(grunt.file.isMatch(grunt.config('less.dist.src'),filepath)) tasks.push('less');
        grunt.config('rsync.dev.options.src', filepath);
        grunt.config('rsync.dev.options.dest', path.join('/path/to/project',filepath));
        return tasks;
    }
},

1
谢谢。在 Windows 上,grunt-contrib-watch 经常会出现不稳定的情况,让我很烦恼。而 grunt-este-watch 更快、更干净、更可靠。 - Kafoso

2
不建议在“watch”事件内运行任务。请看这里的警告:https://github.com/gruntjs/grunt-contrib-watch#using-the-watch-event
目前执行上述操作最佳方式是使用watch事件配置您的rsync任务,但使用watch的“tasks”来运行任务,像这样:
grunt.initConfig({
  watch: {
    upload: {
      // Dont spawn to retain the process context here
      options: { spawn: false },
      files: ['*'],
      tasks: ['rsync:dev']
    },
  },
});
grunt.event.on('watch', function(action, filepath, target) {
  if (target === 'upload') grunt.config('rsync.dev.options.src', filepath);
});

值得一提的是,我们正在寻求更好的方法来处理上述用例。以下是主要的想法:https://github.com/gruntjs/grunt-contrib-watch/issues/156


我觉得是生成进程的问题让我遇到了麻烦。新版本的watch存在最大调用栈问题。我降级回到0.4.x,但这又停止工作了。不得不更改选项为nospawn:true - mpen
即便如此,Grunt在每次更改后仍会重新启动对所有文件的监视。我有19K个文件,所以这需要几分钟,显然太慢了。我需要将整个过程缩短到大约半秒钟左右。 - mpen
那个问题与你的问题不同。为什么要监视19K个文件?grunt-contrib-watch(也没有其他当前在node.js中的观察者)将处理19K个文件,更不用说在500毫秒内了。 - Kyle Robinson Young
不在Ubuntu上。我将其放入详细模式,可以看到它每次都会为每个文件创建一个监视器。我发现另一个库grunt-este-watch,它只在目录上创建监视器,并且不会在每个文件更改后重新创建它们。启动需要1.5秒(约1775个目录),之后速度非常快。有时它会触发我的IDE创建的'jb_bak'文件事件,但这些很容易过滤掉。此外,它为每个更改提供回调,因此我们不需要grunt-newer - mpen
很高兴它对你有用。我也希望我也能放弃我的测试用例 :) - Kyle Robinson Young

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接