【问题标题】:Grunt: `contrib-watch` Fire livereload event after `grunt-nodemon` has restarted when server-side `.coffee` files are compiledGrunt: `contrib-watch` 在编译服务器端`.coffee` 文件时`grunt-nodemon` 重新启动后触发livereload 事件
【发布时间】:2013-10-18 18:49:25
【问题描述】:

我在使用 Grunt.js 和一些插件时遇到了问题,特别是:grunt-contrib-watchgrunt-nodemongrunt-contrib-coffee。这两天我一直在尝试解决这个问题,但我认为我对 Grunt 的了解不足以解决这个问题。

我遇到的问题只是我希望我的服务器端 .coffee 文件能够编译,然后让 nodemon 重新启动服务器,然后只有 livereload 工作。现在,Livereload 可以按预期工作,但服务器端 coffee 文件除外。 contrib-watch 检测到更改,运行 coffee 并触发 livereload 事件,但随后 nodemon 重新启动。

有没有办法让nodemon 在页面重新加载之前重新启动,以便我在屏幕上看到的内容与我的服务器端代码中的内容保持同步?

我已经看到了在单独的终端选项卡中运行 nodemon 的选项,但我在 Windows 上并且更愿意为此目的保持一个终端运行,这就是我使用的全部原因grunt-concurrent.

这是我的 Gruntfile,它还处于早期阶段(因为我试图弄清楚这一切)。如果您希望我将其编译为 JavaScript,那么只需发表评论并提出请求,我将很乐意。

module.exports = (grunt) ->

  # configuration
  grunt.initConfig
    pkg: grunt.file.readJSON 'package.json'

    # watch task
    watch:
      css:
        files: ['src/assets/styles/**/*.styl']
        tasks: ['stylus']
        options:
          livereload: true
      coffee:
        files: ['src/**/*.coffee']
        tasks: ['coffee']
      js:
        files: ['**/*.js']
        options:
          livereload: true
      jade:
        files: ['views/**/*.jade']
        options:
          livereload: true

    # compile coffeescript to javascript
    coffee:
      compile:
        options:
          sourceMap: true
        files: [
          expand: true
          cwd: 'src/'
          src: ['**/*.coffee']
          dest: ''
          ext: '.js'
        ]

    # compile stylus to css
    stylus:
      compile:
        files: [
          expand: true
          cwd: 'src/assets/styles/'
          src: ['**/*.styl']
          dest: 'assets/styles/'
          ext: '.css'
        ]

    # run server
    nodemon:
      dev:
        options:
          file: 'server.js'
          watchedExtensions: ['js', 'json']
          ignoredFiles: [
            'assets/**',
            'node_modules/**',
            '**/.js.map'
          ]

    # run tasks concurrently for fast builds
    concurrent:
      first:
        tasks: ['coffee', 'stylus']
        options:
          logConcurrentOutput: true
      second:
        tasks: ['nodemon', 'watch']
        options:
          logConcurrentOutput: true

  # load dependencies
  require('load-grunt-tasks') grunt

  # register tasks
  grunt.registerTask 'default', [
    'concurrent:first',
    'concurrent:second'
  ]

【问题讨论】:

    标签: gruntjs grunt-contrib-watch grunt-concurrent


    【解决方案1】:

    我自己没有使用过这个,但我不久前发现了它:grunt-rerun。与监视任务结合使用,您可以暂停长时间运行的任务,例如 express(但也可能与 nodemon 一起使用),运行一些任务,然后再次启动任务。示例配置如下所示:

    grunt.initConfig({
      watch: {
          dev: {
            files: ['server/*.js'],
    
            //Note the :go flag used for sending the reload message to the rerun server
            tasks: ['clean','rerun:dev:express:go']
          },
        },
        express: {
            dev: {
                options: {
                    port: 3000,
                    bases: ['/public'],
                    keepalive: true,
                    server: path.resolve('./server/app.js')
                }
            }
        },
        // Configuration to be run (and then tested).
        rerun: {
          dev: {
            options: {
              tasks: ['express']
            },
          },
        }
    })
    

    https://npmjs.org/package/grunt-rerun

    我不完全确定实时重新加载的事情。我的猜测是因为它会关闭进程,通过生成一个新进程会重新加载页面,但我没有亲自使用过,所以我不确定。

    第二种选择是,使用支持多个选项卡的命令提示符,例如Console。我是 Mac 用户,所以我使用 iTerm 2,它有多个窗格;大多数时候我每个项目有四个打开,watchtestem、一个 php 服务器和一个用于其他所有内容的 shell。您可能会发现这要快得多,也少了很多麻烦。

    只是一个关于 Coffeescript 的简短说明,很多 JavaScript 开发人员不使用它,因此为了让更广泛的受众了解您的源代码,将咖啡编译成 js 可能是一个好习惯之前 你发布你的问题。

    【讨论】:

    • 我不确定应该如何使用这个插件,我看到了示例代码,但在我的场景中没有任何意义。由于livereloadgrunt-contrib-watch 运行,我将如何使用rerun 来处理它?此外,该项目的 README 声明它是实验性的,并且在过去 7 个月内没有维护它,这让我有点犹豫......我想我可能必须使用两个终端选项卡(我使用 ConEMu 运行Git Bash on windows),但我想避免这种情况......而且我知道 CoffeeScript 的污名,但由于这是一个配置文件,我认为这不是问题
    • 使用两个终端选项卡(或三个,还是四个?)有什么问题?我不会浪费您的时间来尝试提出一些精心设计的解决方案来节省您必须打开另一个选项卡的时间,这似乎比老实说值得花更多的时间。您还有第三个选项,即完全放弃 livereload 选项并在浏览器中按 F5。就我个人而言,我只会使用两个标签。
    • 只是看看我能不能让事情变得更简单。但是我尝试了两个终端选项卡,它实际上并没有什么不同。它仍然没有及时重新启动服务器,我尝试使用debounceDelay 选项延迟livereload,它根本没有延迟任何东西。 LiveReload 会在我更改文件后立即发生(这很好,但是延迟它以让服务器端的东西有时间重新启动服务器会很棒)
    • 对,我明白了。这不是一个微不足道的问题。您可能需要考虑创建自己的插件来实现此功能,或者派生grunt-contrib-watch 来触发一个事件,您可以在之前按照您的描述运行监视任务。我刚刚快速浏览了 npm,你也有grunt-wait:在 nodemon 重新启动时在 watch 任务中插入一个延迟。可能需要一些试验和错误才能使其正常工作,但这可能是最好的折衷方案。 :) npmjs.org/package/grunt-wait
    • @IanWarburton - 我更喜欢有一个长时间运行的过程。您可以通过在命令末尾附加& 直接在命令行上实现它,这样您就可以“释放”您的shell 来执行其他任务,而无需打开窗口。我今天这样做的方式可能涉及通过 node 或其他任何方式生成 nodemon 或其他一些服务器,在后台运行它,然后开发,而不必担心管理服务器重启。认为这也是一个更快的工作流程。在此处查看更多信息:kb.iu.edu/d/afnz
    【解决方案2】:

    我使用 watch 来查看服务器文件和一个简单的“2SecDelay”任务,让 nodemon 有时间重新启动服务器。

    所以,我得到了一个补丁,但它很丑:

    grunt.registerTask '2SecDelay', 'just taking some time', ->
      done = @async()
      setTimeout((() -> done()), 2000)
    
    ...
    
    nodemon:
      server:
        ... run server and watch server related files ...
    watch:
      server: 
        files: ... same files as the nodemon watches ...
        tasks: ['2SecDelay']
    concurrent:
      server:
        ['nodemon', 'watch']
    

    ```

    【讨论】:

      【解决方案3】:

      为什么要重新加载咖啡/手写笔/玉文件?

      只需 livereload 编译的更改!我猜你有一个公用文件夹,其中包含 .coffee/.styl/.jade 文件的编译输出

      这是我的 Gruntfile 示例:

      module.exports = (grunt) ->
        grunt.config.init
          ...
      
          watch:
            css:
              files: ['src/assets/styles/**/*.styl']
              tasks: ['stylus']
            coffee:
              files: ['src/**/*.coffee']
              tasks: ['coffee']
            jade:
              files: ['views/**/*.jade']
            livereload:
              files: ['public/**/*.*']
              options:
                livereload: true
          ...
      

      这样,您还将触发非 js/css 文件更改的 livereloading,例如图像、字体等。而且你总是确定 livereload 会被触发

      【讨论】:

        【解决方案4】:

        我在服务器启动时向 tiny-lr 添加了以下 http 请求。

        var server = app.listen(process.env.PORT || 3000, function() {
          debug('Koa server listening on port ' + server.address().port);
        
          require('http').get({host: 'localhost', port: 35729, path: '/changed?files=app.js'},      
             function (response){
                console.log('Restart');
          });
        });
        

        我有运行 nodemon 的 Webstorm,所以这似乎是一种在 nodemon 和我正在使用的 livereload 服务器实现之间进行通信的简单方法。

        我尝试从 Gulp 任务运行 nodemon 并在那里进行 http 调用以保持我的代码干净,但 nodemon 似乎没有在服务器启动后触发 的事件 - 它'restart' 事件在重启之前触发。

        应用程序自己的监听事件似乎是触发刷新的最佳位置,因为您知道此时服务器已准备好开始处理请求。

        这些不是问题中指定的技术,但原理应该是一样的。

        【讨论】:

          猜你喜欢
          • 2014-02-25
          • 2014-04-25
          • 1970-01-01
          • 2017-03-18
          • 2017-06-12
          • 2013-07-22
          • 2013-02-11
          • 2015-06-25
          • 1970-01-01
          相关资源
          最近更新 更多