【问题标题】:Grunt watch: only upload files that have changedGrunt watch:仅上传已更改的文件
【发布时间】:2013-12-05 18:45:34
【问题描述】:

related

我能够使用 grunt-ssh 设置 Grunt 任务,将 SFTP 文件发送到我的开发服务器:

sftp: {
    dev: {
        files: {
            './': ['**','!{node_modules,artifacts,sql,logs}/**'],
        },
        options: {
            path: '/path/to/project',
            privateKey: grunt.file.read(process.env.HOME+'/.ssh/id_rsa'),
            host: '111.111.111.111',
            port: 22,
            username: 'marksthebest',
        }
    }
},

但是当我运行它时,它会上传所有内容。有数千个文件。每次修改文件都没有时间等他们一一上传。

如何设置手表只上传我更改的文件,一旦我更改了它们?

(出于好奇,服务器是本地网络上的虚拟机。它在不同的操作系统上运行,并且设置比我的本地机器更类似于生产。如果我能正常工作,上传应该很快)

【问题讨论】:

    标签: ssh gruntjs grunt-contrib-watch


    【解决方案1】:

    您需要的是grunt-newer,该任务专门用于根据刚刚更改的文件更新任何任务的配置,然后运行它。示例配置可能如下所示:

    watch: {
      all: {
        files: ['**','!{node_modules,artifacts,sql,logs}/**'],
        tasks: ['newer:sftp:dev']
      }
    }
    

    【讨论】:

    • 这在实践中似乎效果不佳......它现在正在上传所有内容,而且速度很慢。我不确定它是否只会在第二次上传新内容,但我认为我没有耐心等待几个小时。我认为我的 IDE 捆绑并上传了东西,所以它要快得多。手表也需要很长时间才能启动,但我认为这是 SFTP 的错。
    • 是的,我可以看到问题所在。你试过rsync吗?它仅上传更改的文件部分,因此与传统 FTP 相比,它超级快。还有一个 grunt 包装器:github.com/jedrichards/grunt-rsync
    • 哇。 rsync 上传整个项目目录的速度快了十亿倍,而且设置起来非常容易,但与 newer 不匹配。我和他们开了ticket;不确定这是新版本的故障还是我搞砸了。
    【解决方案2】:

    您可以这样做 using the watch eventgrunt-contrib-watch。 你基本上需要处理 watch 事件,修改 sftp files config 只包含更改的文件,然后让 grunt 运行 sftp 任务。

    类似这样的:

    module.exports = function(grunt) {
        grunt.initConfig({
            pkg: grunt.file.readJSON('package.json'),
            secret: grunt.file.readJSON('secret.json'),
            watch: {
                test: {
                    files: 'files/**/*',
                    tasks: 'sftp',
                    options: {
                        spawn: false
                    }
                }
            },
            sftp: {
              test: {
                files: {
                  "./": "files/**/*"
                },
                options: {
                  path: '/path/on/the/server/',
                  srcBasePath: 'files/',
                  host: 'hostname.com',
                  username: '<%= secret.username %>',
                  password: '<%= secret.password %>',
                  showProgress: true
                }
              }
            }
        }); // end grunt.initConfig
    
        // on watch events configure sftp.test.files to only run on changed file
        grunt.event.on('watch', function(action, filepath) {
            grunt.config('sftp.test.files', {"./": filepath});
        });
    
        grunt.loadNpmTasks('grunt-contrib-watch');
        grunt.loadNpmTasks('grunt-ssh');
    };
    

    注意“spawn: false”选项,以及您需要在事件处理程序中设置配置的方式。

    注意2:此代码将一次上传一个文件,在同一link中有一个更健壮的方法。

    【讨论】:

      【解决方案3】:

      您可以使用 Grunt 实现这一目标:

      • grunt-contrib-watch

      • grunt-rsync

      第一件事:我使用的是 Docker 容器。我还在我的 Docker 容器中添加了一个公共 SSH 密钥。因此,我仅将本地环境中使用此 Grunt 任务更改的文件上传到我的“远程”容器中:

      'use strict';
      
      module.exports = function(grunt) {
      
          grunt.initConfig({
      
              rsync: {
                  options: {
                      args: ['-avz', '--verbose', '--delete'],
                      exclude: ['.git*', 'cache', 'log'],
                      recursive: true
                  },
                  development: {
                      options: {
                          src: './',
                          dest: '/var/www/development',
                          host: 'root@www.localhost.com',
                          port: 2222
                      }
                  }
              },
      
              sshexec: {
                  development: {
                      command: 'chown -R www-data:www-data /var/www/development',
                      options: {
                          host: 'www.localhost.com',
                          username: 'root',
                          port: 2222,
                          privateKey: grunt.file.read("/Users/YOUR_USER/.ssh/id_containers_rsa")
                      }
                  }
              },
      
              watch: {
                  development: {
                      files: [
                      'node_modules',
                      'package.json',
                      'Gruntfile.js',
                      '.gitignore',
                      '.htaccess',
                      'README.md',
                      'config/*',
                      'modules/*',
                      'themes/*',
                      '!cache/*',
                      '!log/*'
                      ],
                      tasks: ['rsync:development', 'sshexec:development']
                  }
              },
      
          });
      
          grunt.loadNpmTasks('grunt-contrib-watch');
          grunt.loadNpmTasks('grunt-rsync');
          grunt.loadNpmTasks('grunt-ssh');
      
          grunt.registerTask('default', ['watch:development']);
      };
      

      祝你好运,黑客愉快!

      【讨论】:

        【解决方案4】:

        我最近遇到了类似的问题,我只想上传已更改的文件。我只使用grunt-exec。如果您有ssh 访问您的服务器,您可以更高效地完成此任务。我还创建了一个rsync.jsongit 忽略,因此协作者可以拥有自己的rsync 数据。

        好处是,如果有人做出更改,它会自动上传到他们的舞台。

            // Watch - runs tasks when any changes are detected.
            watch: {
                scripts: {
                    files: '**/*',
                    tasks: ['deploy'],
                    options: {
                        spawn: false
                    }
                }
            }
        

        我的部署任务是一个注册任务,它编译脚本然后运行exec:deploy

           // Showing exec:deploy task 
           // Using rsync with ssh keys instead of login/pass
            exec: {
                deploy: {
                    cmd: 'rsync public_html/* <%= rsync.options %> <%= rsync.user %>@<%= rsync.host %>:<%=rsync.path %>'
            }
        

        你看到很多&lt;%= rsync %&gt; 的东西吗?我用它从rysnc.json 获取信息,该信息由git 输入。我只有这个,因为这是一个团队工作流程。

        // rsync.json
        {
          "options": "-rvp --progress -a --delete -e 'ssh -q'",
          "user": "mmcfarland",
          "host": "example.com",
          "path": "~/stage/public_html"
        }
        

        确保您在 grunt 中定义了 rsync.json

        module.exports = function(grunt) {
        
          var rsync = grunt.file.readJSON('path/to/rsync.json');
          var pkg = grunt.file.readJSON('path/to/package.json');
        
          grunt.initConfig({
            pkg: pkg,
            rsync: rsync,
        

        【讨论】:

        • 这看起来很甜蜜!谢谢分享!
        【解决方案5】:

        我认为一次将所有更改的内容上传到登台服务器并不是一个好主意。在登台服务器上工作也不是一个好主意。你必须配置你的本地机器服务器,与登台/生产相同

        最好在部署时上传 1 次。

        您可以使用 grunt-contrib-compress 归档所有文件。并使用 grunt-ssh 将它们作为 1 个文件推送,然后将其提取到服务器上,这样会快得多。

        这是压缩任务的例子:

        compress: {
                    main: {
                        options:{
                            archive:'build/build.tar.gz',
                            mode: 'tgz'
                        },
                        files: [
                            {cwd: 'build/', src: ['sites/all/modules/**'], dest:'./'},
                            {cwd: 'build/', src: ['sites/all/themes/**'], dest:'./'},
                            {cwd: 'build/', src: ['sites/default/files/**'], dest:'./'}
                        ]
                    }
                }
        

        PS:从未考虑过 rsync grunt 模块。 我知道这可能不是您想要的。但我决定将我的答案创建为独立答案。

        【讨论】:

        • 这不是临时的,它只是我们办公室的另一台机器。我猜以这种方式管理所有虚拟机更容易我们的服务器管理员,但除此之外我同意——我通常在本地开发或使用 Vagrant。不过,这个压缩的想法应该会在以后派上用场,谢谢!
        猜你喜欢
        • 1970-01-01
        • 2016-01-07
        • 1970-01-01
        • 2014-05-12
        • 1970-01-01
        • 2013-05-23
        • 1970-01-01
        • 1970-01-01
        • 2013-07-29
        相关资源
        最近更新 更多