【问题标题】:How can I use grunt-contrib-watch and grunt-contrib-coffee to compile CoffeeScript only as needed?如何使用 grunt-contrib-watch 和 grunt-contrib-coffee 仅在需要时编译 CoffeeScript?
【发布时间】:2014-02-25 11:04:20
【问题描述】:

我想仅在我保存的单个文件上运行 coffee lint 和 coffee compile。我的项目中有数百个 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 任务仅在更改的文件上成功运行。

coffee 编译不会产生任何 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']

【问题讨论】:

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


    【解决方案1】:

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

    安装它:

    npm install grunt-newer --save-dev
    

    然后稍微改变一下你的咖啡脚本任务。如果您转到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
    

    然后像这样在你的监视任务中使用 newer:

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

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

    【讨论】:

    • 这只会编译已更改的咖啡文件,但它会在所有咖啡文件上运行咖啡棉:-(
    • 是的。我也有同样的问题。
    【解决方案2】:

    尝试将这样的内容添加到您的 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

    【讨论】:

      【解决方案3】:

      这里有两个问题。

      第一:

      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 -&gt; src 下。反映同样的情况也可能有用。

      编辑:小附录

      【讨论】:

      • 第一个:>> 文件“src/coffeescript/app.coffee”已更改。运行 "coffeelint:files" (coffeelint) 任务 >> 1 文件 lint free。运行“coffee:files”(咖啡)任务警告:无法读取“未定义”文件(错误代码:ENOENT)。
      • 第二:不创建 JavaScript 文件。
      【解决方案4】:

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

      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 开箱即用......

      【讨论】:

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