web-dev-qa-db-fra.com

Grunt: regarder plusieurs fichiers, compiler uniquement modifié

Je suis nouveau chez Grunt, et jusqu'à présent je l'apprécie beaucoup. Je veux que Grunt compile uniquement les fichiers modifiés lors de l'exécution de grunt watch

Dans mon Grunfile.coffee, j'ai actuellement (parties pertinentes).
Remarque: les actifs/javascript/app.coffee et les actifs/javascript/app.js sont des répertoires

    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

Il y a probablement un moyen plus court, mais je compile d'abord app.coffee en app.js, afin qu'après avoir distribué mon travail, les personnes qui ne sont pas à l'aise avec Coffeescript puissent parcourir le code de manière assez raisonnable.

Le problème avec tout cela, c'est que maintenant que j'enregistre un fichier Coffeescript, je reçois trop d'étapes (je pense):

>> 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...

Actuellement, je suis en train de configurer mon projet, mais j'aurai beaucoup plus de fichiers Coffeescript, et je ne veux pas que Coffeescript recompile tous les fichiers, à chaque changement de fichier.

En outre, libs.js n'a aucune part à tout cela, mais je suppose qu'il est toujours compilé, car il correspond également au modèle "assets/* /. Js".

Existe-t-il un moyen de faire en sorte que Grunt compile uniquement les fichiers qui ont été modifiés?

42
justnorris

J'ai enfin trouvé une vraie solution! Et c'est super simple aussi!

npm install grunt-newer --save-dev

Puis dans votre Gruntfile (après avoir chargé la tâche dans grunt):

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

Et c'est tout! The Awesome grunt-newer is awesome!

75
justnorris

Si vous concatérez toutes les sources .coffee en un seul fichier .js, vous devrez le recompiler à chaque fois si l'une de vos sources change. Fractionnez-le en plusieurs fichiers .js et effectuez une tâche de publication où vous ne concatérez que ces fichiers .js. De cette façon, il vous suffit d'inclure un seul fichier .js.

Voir En utilisant gruntjs, comment surveiller les changements dans les fichiers .coffee?

2
Jamesgt

Le grunt.event.on L'événement détecte les modifications dans les fichiers et reçoit les paramètres action et filepath.

Voici un exemple non testé basé sur l'un de mes gruntfiles. Dans ce cas, tous mes fichiers source coffeescript sont conservés dans un répertoire appelé sources, et pour la prévisualisation, ils sont compilés et enregistrés dans une structure de répertoire identique sous un répertoire appelé 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"
)

J'espère que cela pourra aider.

EDIT: Probablement pas exactement ce que vous voulez - parce que vous voulez sans aucun doute accéder aux variables intermédiaires, aux actions et ainsi de suite - mais vous pouvez utiliser grunt pour simplement exécuter une commande Shell coffee. Le grunt-Shell La tâche npm fait cela, par exemple

EDIT2: J'ai toujours eu des problèmes avec grunt.watch.on ne fonctionne pas de manière cohérente dans grunt 0.4.1 sur OSX 10.8 et MacVim 7.3; pour une raison quelconque, il arrête de regarder. Je suis revenu à l'utilisation de l'objet grunt initConfig de base, mais avec beaucoup plus de granularité, il ne surveille et ne compile que des groupes de fichiers relativement petits plutôt que le tout. Cela ralentit considérablement le temps de construction, mais il est beaucoup plus robuste. Votre kilométrage peut très.

1
Jof Arnold

J'ai également trébuché là-dessus et je n'ai trouvé aucune version qui fonctionnait avec la version actuelle (0.4.1). Mais la réponse de Jof Arnolds a montré une bonne approche.

Voici ce que j'ai trouvé:

# 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

J'ai une section café qui ressemble un peu à ceci:

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"
    ]
0
Sebastian Hoitz