I'm trying to work my way through the updates to Visual Studio 2015 including using Grunt and so on.
I can get Grunt to recompile .scss
files when they change, but I have a problem. I use SASS for theming, and a lot of my CSS is in a central _main.scss
. What I want is when I edit that file, it should recompile all the theme-*.scss
files that include _main.scss
.
Is there any way to tell watch
or stuff like that to recompile things when dependencies change? Even if I have to specify the dependencies manually?
I don't know if there's a way to follow dependencies from one file to another, but you can watch for changes in .scss
files and then run a sass task to update your theme files.
So you'll have your sass task like this:
sass : {
build: {
files : {
'path/to/compiled-foo.css': 'path/to/theme-foo.scss',
'path/to/compiled-bar.css': 'path/to/theme-bar.scss',
// Or more generally
'path/to': 'path/to/theme-*.scss',
}
}
},
And then your watch task like this:
watch : {
themes: {
files : [ 'path/to/_main.scss' ],
tasks : [ 'sass' ],
options : {
// You may change these to better suit your needs
spawn : false,
interrupt: true,
livereload: true
},
},
},
The downside of this is that all your themes will compile each time you change your _main.scss
. If you have different files to watch for different themes then you can have more tasks inside watch
(instead of themes
you can make theme_foo
and theme_bar
call different tasks (e.g.: sass:theme_foo
or sass:theme_bar
) and then recompile just that theme.
You can also run grunt watch
on a specific task: grunt watch theme_foo
, which won't update theme_bar
but just theme_foo
.
Edit: You can modularize your _main.scss
so it becomes _foo.scss
, _bar.scss
and _common.scss
, and then change _common.scss
when it's a change that affects all themes, and _foo.scss
when it just affects theme_foo
. This way you can monitor _foo.scss
and update only theme_foo
when it changes; or update all your themes just when _common.scss
changes.
Edit 2 (based on comments):
Lets say we have two themes, blue and red. We'll have two sass tasks (one for each theme):
sass : {
red: {
files : {
'path/to/compiled-red.css': 'path/to/theme-red.scss',
}
},
blue: {
files : {
'path/to/compiled-blue.css': 'path/to/theme-blue.scss',
}
},
},
Right now, if you run grunt sass
it will update both themes. But if you run grunt sass red
it will update just the red theme.
To make your watch
update just the required theme, you'll have two tasks:
watch : {
red: {
files : [ 'path/to/theme-red.scss' ],
tasks : [ 'sass:red' ],
options : { /* ... */ },
},
blue: {
files : [ 'path/to/theme-blue.scss' ],
tasks : [ 'sass:blue' ],
options : { /* ... */ },
},
},
Notice red
calls sass:red
(the task for that theme and only that theme). Same happens with blue
calling sass:blue
.
To make it update every theme when _main.scss
changes, you add one more task inside watch
:
watch : {
red: {
files : [ 'path/to/theme-red.scss' ],
tasks : [ 'sass:red' ],
options : { /* ... */ },
},
blue: {
files : [ 'path/to/theme-blue.scss' ],
tasks : [ 'sass:blue' ],
options : { /* ... */ },
},
all: {
files : [ 'path/to/_main.scss' ],
tasks : [ 'sass' ],
options : { /* ... */ },
},
},
Now all
is watching your _main.scss
, and when it changes every task in sass
will be run (i.e. sass:red
and sass:blue
).