Grunt:观看多个文件,仅编译已更改

时间:2013-05-28 09:39:52

标签: node.js coffeescript gruntjs

我是Grunt的新手,到目前为止,我非常喜欢它。 我希望Grunt在运行grunt watch

时仅编译已更改的文件

在我的Grunfile.coffee中,我目前有(相关部分) 注意:assets / javascript / app.coffee和assets / javascript / app.js是目录

    coffee:
        default:
            expand: true
            cwd: "assets/javascript/app.coffee"
            src: ["*.coffee"]
            dest: "assets/javascript/app.js"
            ext: ".js"

    uglify:
        dev:
            options:
                beautify: true
                compress: false
                mangle: false
                preserveComments: 'all'

            files: 
                "js/app.js": "assets/javascript/app.js/*.js"
                "js/libs.js": "assets/javascript/libs/*.js"

    watch:
        coffeescript:
            files: 'assets/javascript/**/*.coffee'
            tasks: ["coffee"]

        javascript:
            files: "assets/**/*.js"
            tasks: ["uglify:dev"]
        livereload:
            files: ["Gruntfile.coffee", "js/*.js", "*.php", "css/*.css", "images/**/*.{png,jpg,jpeg,gif,webp,svg}", "js/*.js", ]
            options:
                livereload: true

可能有一个较短的方法,但我首先将app.coffee编译为app.js,这样在我分发我的作品后,不熟悉Coffeescript的人可以以合理的方式浏览代码。

所有这一切的问题在于,现在我保存了一个Coffeescript文件,我得到了太多步骤(我认为):

>> File "assets/javascript/app.coffee/browse.coffee" changed.

Running "coffee:default" (coffee) task
File assets/javascript/app.js/browse.js created.
File assets/javascript/app.js/filters.js created.

Done, without errors.
Completed in 0.837s at Tue May 28 2013 12:30:18 GMT+0300 (EEST) - Waiting...
OK
>> File "assets/javascript/app.js/browse.js" changed.
>> File "assets/javascript/app.js/filters.js" changed.

Running "uglify:dev" (uglify) task
File "js/app.js" created.
File "js/libs.js" created.

Done, without errors.
Completed in 0.831s at Tue May 28 2013 12:30:19 GMT+0300 (EEST) - Waiting...
OK
>> File "js/app.js" changed.
>> File "js/libs.js" changed.

Completed in 0.000s at Tue May 28 2013 12:30:19 GMT+0300 (EEST) - Waiting...

目前我只是设置我的项目,但我会有更多的Coffeescript文件,我不希望Coffeescript在每次更改文件时重新编译所有文件。

此外,libs.js完全不参与所有这些,但我想它仍然是编译的,因为它也匹配“assets / * / .js”模式。

有没有办法让Grunt只编译已更改的文件?

4 个答案:

答案 0 :(得分:73)

我终于找到了一个真正的解决方案!而且它也非常简单!

npm install grunt-newer --save-dev

然后在你的Gruntfile中(在grunt中加载任务后):

watch:
    coffeescript:
        files: 'assets/javascript/**/*.coffee'
        tasks: ["newer:coffee"]

就是这样! The Awesome grunt-newer is awesome!

答案 1 :(得分:2)

如果将所有.coffee源连接到一个.js文件中,那么每次任何源更改时都必须重新编译它。将其拆分为几个.js文件并进行发布任务,您只能连接这些.js文件。这样你仍然只需要包含一个.js文件。

请参阅Using gruntjs, how do watch for changes in .coffee files?

答案 2 :(得分:1)

grunt.event.on事件检测到文件中的更改,并收到actionfilepath参数。

这是一个基于我的gruntfiles之一的未经测试的示例。在这种情况下,我的所有源coffeescript文件都保存在名为sources的目录中,为了预览,它们​​被编译并保存到名为dev

的目录下的相同目录结构中。
SOURCES_DIR = 'sources'
DEV_DIR = 'dev'

grunt.initConfig
  watch :
    all :
      files : ["**/*.coffee"]
  coffee :
    dev :
      files :
        dest : "app.js"
grunt.loadNpmTasks 'grunt-contrib-watch'
grunt.loadNpmTasks 'grunt-contrib-coffee'

grunt.registerTask 'build', ['coffee:dev']

grunt.event.on('watch', (action,filepath) ->
  # Determine the full directory of the changed file
  wdi = filepath.lastIndexOf '/'
  wd =  filepath.substring 0,wdi

  # remove `sources` prefix from that directory
  fpath = wd.replace(SOURCES_DIR,'') + '/'

  # determine the filename
  fnamei = filepath.lastIndexOf '.'
  fname = filepath.substring wdi+1,fnamei # NOTE: this breaks the case where in same dir

  # concatenate fpath and fname with the dir to be compiled into
  deststr = "#{DEV_DIR}#{fpath}#{fname}.coffee"


  # set coffee.dev.files value in the coffee task to have am entry of form {"destination":"source"}
  obj = {}
  obj[deststr] = filepath
  grunt.config "coffee.dev.files", obj

  # fire the coffee task
  grunt.task.run "coffee"
)

希望有所帮助。

编辑:可能不完全是您想要的 - 因为毫无疑问您需要访问中间变量,操作等等 - 但您可以使用grunt来运行shell coffee命令。 grunt-shell npm任务执行此操作,例如

EDIT2:我遇到了grunt.watch.on在OSX 10.8和MacVim 7.3上不能始终如一地处理grunt 0.4.1的问题。无论出于何种原因,它都不再看了。我已经恢复到只使用基本的grunt initConfig对象,但具有更多的粒度,因此它只监视和编译相对较小的文件组而不是整个批次。这大大减慢了构建时间,但它更加强大。你的里程可能非常。

答案 3 :(得分:0)

我也偶然发现了这一点,并没有发现任何适用于当前版本的工作版本(0.4.1)但是Jof Arnolds的回答显示了一个很好的方法。

这就是我提出的:

# only recompile changed files
grunt.event.on "watch", (action, filepath) ->
  # note that we have to manually change the target file name to 
  # our desired format
  targetName = filepath.replace(/\/(client|shared)/, "")
    .replace(".coffee", ".js")
    .replace("app/", "")

  options =
    src: filepath
    dest: "public/javascripts/#{targetName}"

  grunt.config ["coffee", "client"], options

我的咖啡部分看起来有点像这样:

coffee:
  client:
    options:
      sourceMap: false
    files: [
      expand: true
      cwd: "app"
      src: ["*/client/**/*.coffee", "helpers/{client,shared}/*.coffee"]
      dest: "public/javascripts"
      rename: (folder, name) ->
        name = name.replace(/\/(client|shared)/, "")

        [folder, name].join path.sep
      ext: ".js"
    ]