2

I've been having an issue with Grunt.js and a few plugins, notably: grunt-contrib-watch, grunt-nodemon and grunt-contrib-coffee. I've been trying to figure this out for two days now but I don't think my knowledge of Grunt is sufficient to solve it at this point.

The problem I'm experiencing is simply that I want my server-side .coffee files to compile and then have nodemon restart the server and THEN only have livereload work. Right now, Livereload works as intended for everything but server-side coffee files. contrib-watch detects the change, runs coffee and fires off a livereload event, but then nodemon restarts.

Is there a way to get nodemon to restart before the page reloads so that what I see on the screen is up-to-date with what's going on in my server-side code?

I've been presented with the option of just running nodemon in a separate terminal tab, but I'm on Windows and would much prefer to keep one terminal running for this purpose and is the whole reason I'm using grunt-concurrent.

Here's my Gruntfile, it's quite early in it's stages (as I try to figure all this out). If you would prefer I compile it to JavaScript, then just leave a comment and request so, I will be happy to.

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'
  ]
4

4 回答 4

3

我自己没有使用过这个,但我不久前遇到了它: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 ;大多数时候,我每个项目有四个打开,用于watch, testem,一个 php 服务器和一个用于其他所有内容的 shell。您可能会发现这要快得多,麻烦也少得多。

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

于 2013-10-18T20:10:29.810 回答
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']

```

于 2013-12-15T14:00:16.173 回答
1

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

只需 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 会被触发

于 2013-12-29T23:32:26.350 回答
0

当我的服务器启动时,我向 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 似乎没有在服务器启动触发的事件- 它的“重启”事件在重启之前触发。

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

这些不是问题中指定的技术,但原则应该同样适用。

于 2014-12-08T18:13:06.853 回答