2

I have a web-app whose directory structure looks like this:

src/
 - styles/
   - a.css
   - b.css
   - c.scss
   - d.scss
 - media/
   - d.jpg
   - e.png
   - f.mpf
dest/
 - css/
 - media/
package.json
Gruntfile.js

I want to use the Gruntfile to watch files for changes. And when they change, process or copy them. I don't want files to be copied or processed unneccesarily. I'm trying to figure out how to do this with the Gruntfile and finding it pretty tricky.

I come from the world of C++ and makefiles. They were great because for each derived file, you would specify the command to derive it, and the files on which that derivation was directly dependent. If any of the dependency files were newer than the target, your command would be run. If any of the dependency files were absent, then it would be generated based on this same recursive logic.

How can I achieve the same thing here in Grunt? Specifying watches allows you to watch multiple files for changes. But then the command you run is usually not specific to the changed file.

My Gruntfile is here. Please show me how I can modify it to implement the following 3 rules:

  • When any file src/styles/.scss changes, compile it with Sass and place the result in dest/css/.css. Then minify it to dest/css/*.min.css
  • When any file src/styles/.css changes, copy it to dest/css/.css. Then minify it to dest/css/*.min.css
  • When any file src/media/* changes, copy it to dest/media/*

I want these rules to be generic. IE: I don't want to have to write separate rules for b.scss and d.scss. It seems dumb to have to specify similar rules explicitly for every single file.

Saqib Ali
  • 11,931
  • 41
  • 133
  • 272
  • all of the values under the `watch: { /* ... */ }` object are config objects that will all be run on `grunt watch`, and they specify a set of tasks to run when a given set of files changes. – William B Nov 26 '16 at 04:58
  • Yes William. But how can I tell it: *when file c.scss changes, run sass on c.scss only, then put the resultant .css file into dest/css/c.css. Then minfiy dest/css/c.css only into dest/css/c.min.css*? – Saqib Ali Nov 26 '16 at 05:10
  • specify c.scss in the `files` property – William B Nov 26 '16 at 05:50
  • 1
    Welcome to 2016, where re-inventing the wheel is the norm, and the new wheels are worse than the original ones from forty years ago. Why not use `make` itself? Many people do, and are very happy with how it works, compared to over-engineered millennial replacements such as grunt and gulp. You can quite easily find guides for using make with JS projects. Then you can move on to your next project, which is getting rid of SASS in your project. –  Nov 26 '16 at 07:01
  • LOL Torazaburo. There is a certain amount of bitter truth in what you are saying. If make wasn't broke, why fix it? – Saqib Ali Nov 26 '16 at 07:15
  • 1
    I have a sneaking suspicion that the originators of grunt and its ilk did not even know about make, much less understand it. And in any case, we couldn't use it in JS projects, because you know **everything** must be JS. –  Nov 26 '16 at 07:26

1 Answers1

0

You need to add a module grunt-concurrent to run mutiple instance of watch:

concurrent: {
 dev: {
   tasks: [
    'watch:sass:12340',
    'watch:copy_css:12350',
   ],
   options: {
    logConcurrentOutput: true
   }
  }
}
grunt.loadNpmTasks('grunt-concurrent');

and i think that i will edit the watch section in this way:

watch: {
  sass: {
      files: ['src/css/*.scss'],
      tasks: ['sass:all','cssmin'],
      options: {
          spawn: false
      }
  },
  copy_css: {
      files: 'src/css/*.css',
      tasks: ['copy:all','cssmin'],
      options: {
          spawn: false
      }
  },
  copy_media: {
    files: 'src/media/**',
    tasks: ['copy']
  }
}

than run grunt concurrent:dev

Emanuele Parisio
  • 1,192
  • 8
  • 27