42

我是 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

4 回答 4

75

我终于找到了真正的解决方案!它也超级简单!

npm install grunt-newer --save-dev

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

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

就是这样!Awesome grunt-newer太棒了!

于 2013-11-01T08:01:24.973 回答
2

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

请参阅使用 gruntjs,如何监视 .coffee 文件中的更改?

于 2013-05-28T18:39:05.927 回答
1

grunt.event.on事件检测文件中的更改,接收一个actionfilepath参数。

这是基于我的一个 gruntfiles 的未经测试的示例。在这种情况下,我所有的咖啡源文件都保存在一个名为 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-shellnpm 任务就是这样做的

EDIT2:我一直面临着grunt.watch.on在 OSX 10.8 和 MacVim 7.3 上的 grunt 0.4.1 中无法始终如一地工作的问题;无论出于何种原因,它都会停止观看。我已经恢复到只使用基本的 grunt initConfig 对象,但粒度更大,因此它只监视和编译相对较小的文件组,而不是全部文件。这大大减慢了构建时间,但更加健壮。你的里程可能很。

于 2013-06-21T08:21:19.433 回答
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"
    ]
于 2013-09-12T11:33:02.573 回答