如何根据需要使用grunt-contrib-watch和grunt-contrib-coffee来编译CoffeeScript?

时间:2014-02-01 19:11:52

标签: coffeescript gruntjs grunt-contrib-watch grunt-contrib-coffee

我想在我保存的单个文件上运行咖啡lint和咖啡编译。我的项目中有数百个CoffeeScript文件,编译所有这些文件需要花费太多时间。

这是我的Gruntfile:

module.exports = (grunt) ->

  grunt.initConfig

    pkg: grunt.file.readJSON 'package.json'

    coffee:
      all:
        expand: true
        bare: true
        cwd: 'src/coffeescript/'
        src: '**/*.coffee'
        dest: 'public/js/compiled'
        ext: '.js'

    coffeelint:
      all: ['src/coffeescript/**/*.coffee']

    watch:
      coffeescript:
        files: ['src/**/*.coffee']
        tasks: ['coffeelint', 'coffee']
        options:
          spawn: false

  grunt.event.on 'watch', (action, filepath) ->
    grunt.config(['coffeelint', 'all'], filepath)
    grunt.config(['coffee', 'all'], filepath)

  grunt.loadNpmTasks 'grunt-coffeelint'
  grunt.loadNpmTasks 'grunt-contrib-coffee'
  grunt.loadNpmTasks 'grunt-contrib-watch'

  grunt.registerTask 'default', ['coffeelint', 'coffee', 'watch']

coffeelint任务仅在更改的文件上成功运行。

咖啡编译不会产生任何JS文件,即使grunt说它运行。

这是保存单个咖啡文件后的输出:

OK
>> File "src/coffeescript/app.coffee" changed.


Running "coffeelint:all" (coffeelint) task
>> 1 file lint free.

Running "coffee:all" (coffee) task

Running "watch" task
Completed in 0.009s at Sat Feb 01 2014 13:10:07 GMT-0600 (CST) - Waiting...

这里有什么问题?任何帮助将不胜感激!

更新

这是一个有效的例子:

module.exports = (grunt) ->

  fs = require 'fs'
  isModified = (filepath) ->
    now = new Date()
    modified =  fs.statSync(filepath).mtime
    return (now - modified) < 10000

  grunt.initConfig

    coffee:
      options:
        sourceMap: true
        bare: true
        force: true # needs to be added to the plugin
      all:
        expand: true
        cwd: 'src/coffeescript/'
        src: '**/*.coffee'
        dest: 'public/js/compiled'
        ext: '.js'
      modified:
        expand: true
        cwd: 'src/coffeescript/'
        src: '**/*.coffee'
        dest: 'public/js/compiled'
        ext: '.js'
        filter: isModified

    coffeelint:
      options:
        force: true
      all:
        expand: true
        cwd: 'src/coffeescript/'
        src: '**/*.coffee'
      modified:
        expand: true
        cwd: 'src/coffeescript/'
        src: '**/*.coffee'
        filter: isModified

    watch:
      coffeescript:
        files: ['src/**/*.coffee']
        tasks: ['coffeelint:modified', 'coffee:modified']

  grunt.loadNpmTasks 'grunt-coffeelint'
  grunt.loadNpmTasks 'grunt-contrib-coffee'
  grunt.loadNpmTasks 'grunt-contrib-watch'

  grunt.registerTask 'default', ['coffeelint:all', 'coffee:all', 'watch']

4 个答案:

答案 0 :(得分:10)

当源比编译输出更新时,您可以使用grunt-newer仅编译文件。

使用以下命令安装:

npm install grunt-newer --save-dev

然后稍微更改你的coffeescript任务。如果您转到Grunt.js docs中的“动态构建文件对象”部分,您将看到需要在files数组中保存与文件位置和编译输出位置相关的信息。任务正确执行。

然后可以使用选项对象指定其他选项,例如bare: true

因此,对于您的coffee任务,请执行以下操作:

   coffee:
      all:
        files: [{
          expand: true
          cwd: 'src/coffeescript/'
          src: '**/*.coffee'
          dest: 'public/js/compiled'
          ext: '.js'
        }]
        options:
          bare: true
          spawn: false

然后在你的观察任务中使用更新的东西:

    watch:
      coffeescript:
        files: ['src/**/*.coffee']
        tasks: ['newer:coffeelint:all', 'newer:coffee:all']
        options:
          spawn: false

然后,Newer将只编译比其编译版本更新的文件。

答案 1 :(得分:4)

尝试将这样的内容添加到您的c任务中

 coffee:
  all:
    filter: (filepath) ->
        fs = require('fs')
        now = new Date()
        modified =  fs.statSync(filepath).mtime
        return (now - modified) < 10000 # or another difference in millyseconds

documentation

中了解详情

答案 2 :(得分:0)

这里有两个问题。

首先:

Grunt将更改的文件路径生成为src/coffeescript/some_file.coffee,但在coffee任务中,您已将cwd定义为src/coffeescript

因此,咖啡任务实际上只期待some_file.coffee但它正在获得src/coffeescript/some_file.coffee,然后将其扩展为src/coffeescript/src/coffeescript/some_file.coffee O_o

您的coffeelint任务没有任何cwd,因此它使用完整的文件路径成功运行。

相应地调整文件路径,或从咖啡配置中删除cwd

grunt.config(['coffee', 'all'], filepath.replace("src/coffeescript", ""))

第二

这个是次要的,可能不是必需的,但也要注意这一点。

grunt.event.on 'watch', (action, filepath) ->
  grunt.config(['coffeelint', 'all'], filepath)
  grunt.config(['coffee', 'all'], filepath)
  ^^^^^^^ You might have to change above line to:
  grunt.config(['coffee', 'all', 'src'], filepath)

在您的coffeelint任务中,直接在all下设置来源。但在coffee任务中,来源设置在all -> src下。反映这一点也可能有用。

编辑:次要附录

答案 3 :(得分:0)

您可以将每个修改时间存储在地图中,而不是使用任意持续时间阈值:

fs = require 'fs'
mtimes = {}
isModified = (filepath) ->
    mtime = fs.statSync(filepath).mtime
    if mtimes[filepath]?
        return mtimes[filepath] < mtime
    else
        mtimes[filepath] = mtime
        return yes

虽然grunt没有提供目标文件路径作为过滤器函数的第二个参数,但这太糟糕了。这样可以进行简单的检查,看看生成的文件是否存在且是否早于源... Make开箱即用...