Watching sass and browserify js files at the same time
Opened this issue · 6 comments
How can I watch sass files with grunt-browserify and grunt-contrib-watch at the same time?
I tried setting browserify's keepAlive
to false but that disables browserify's watch
option too.
Running the browserify
task with grunt-contrib-watch is not really an option because my bundle is too big for that. I tried a workaround by splitting it into 2 bundles but that isn't a real solution.
Compiling sass in an IDE is not really an option because we have way too many collaborators to make sure that everyone uses the same config for compiling.
If I remove the comment from //'watch'
then browserify:frontend_bundle_watch
never runs. Moving watch
down does not help either.
Using grunt-concurrent
makes both of them run once but none of them actually responds to changed files.
Versions:
$ npm list -i --depth=0
├── angular@1.4.8
├── angular-ui-bootstrap@1.0.3
├── bootstrap-sass@3.3.6
├── browserify-ng-html2js@1.1.5
├── console-polyfill@0.2.2
├── font-awesome@4.5.0
├── grunt@0.4.5
├── grunt-browserify@4.0.1
├── grunt-concurrent@2.1.0
├── grunt-contrib-copy@0.8.2
├── grunt-contrib-uglify@0.11.0
├── grunt-contrib-watch@0.6.1
├── grunt-ng-annotate@1.0.1
├── grunt-sass@1.1.0
├── load-grunt-tasks@3.4.0
└── node.normalize.scss@3.0.3
Gruntfile (removed potentially irrelevant lines)
module.exports = function(grunt) {
require('load-grunt-tasks')(grunt);
/* ... folder variables ... */
grunt.initConfig({
pkg: grunt.file.readJSON('package.json'),
browserify: {
options: {
"watch": true,
"keepAlive": true,
},
frontend_bundle_watch: {
src: frontendAppFolder + "/frontend.js",
dest: compiledFolder + "/app.js",
},
},
/* ... */
sass: {
options: {
sourceMap: false,
includePaths: [vendorFolder],
},
site_frontend: {
options: {
outputStyle: 'nested',
},
src: frontendAppFolder+'/frontend.scss',
dest: compiledFolder+"/app.css"
}
},
watch: {
options: {
spawn: false,
debounceDelay: 100
},
sass_frontend: {
files: frontendAppFolder+"/**/scss/**/*.scss",
tasks: ['sass:site_frontend'],
}
}
});
/* ... */
var buildTasks = [
'browserify:frontend_bundle_watch',
'sass:site_frontend',
/* ... */
];
grunt.registerTask('default', buildTasks.concat([
//'watch',
'browserify:frontend_bundle_watch',
]));
Hello
Parts of my config:
# order is important
grunt.registerTask 'default', ['browserify:dev', 'less:dev', 'connect', 'watch']
grunt.initConfig {
# ...
# dev static server with livereload
connect:
dev:
options:
# no keepalive!
debug : false
port : 9000
hostname : '*'
livereload: true
base : ['.', 'dist']
watch:
options:
atBegin : false
livereload: true
less:
options:
livereload: false # no reload page after update
interrupt : true
files: ['src/**/*.less']
tasks: ['less:dev']
css: # for hotreload styles
files: ['dist/styles.css']
tasks: []
spawn: false
js: # for autoreload page
files: ['dist/*.js']
tasks: []
# ...
browserify:
dev:
options:
# ...
# no keepalive!
watch: true
files:
'dist/lib.js': ['src/lib.coffee']
'dist/app.js': ['src/app.coffee']
less:
dev:
files:
'dist/styles.css': ['src/**/*.less', '!src/less/import/**/*.less']
}
@ovcharik does your console output when a file is built include the text Watchifying...
? If your output is just Bundle foo/bar.js created.
then it's not running with watchify (which should be considerably faster).
Running the browserify task with grunt-contrib-watch is not really an option because my bundle is too big for that.
I believe @dsge is trying to get it to run with watchify. I'm also looking for a solution as my build is a little slower than I'd like it to be but I need to run grunt-contrib-watch for other assets.
@wesvetter this solution for combining watchify
and grunt-contrib-watch
.
From documentation:
watch
Type: Boolean If true, invoke watchify instead of browserify.
For watchify to work properly, you have to keep the process running. The option keepAlive can help you do that, or you can use another grunt-watch task.
I'm turn on watch
option for browserify
task and turn off keepAlive
, because watch
task will keep process.
Option watch
determines that will be used watchify vs browserify.
https://github.com/jmreidy/grunt-browserify/blob/master/lib/runner.js#L33
//determine watchify or browserify
var b = options.watch ? this.watchify(this.browserify(bOpts), wOpts) : this.browserify(bOpts);
Although option keepAlive
affects display Watchifying...
in console, but it does not affect the choice between browserify and watchify. With keepAlive
callback of the task not happening, without option it called once. This is the only important difference.
https://github.com/jmreidy/grunt-browserify/blob/master/lib/runner.js#L161
self.logger.log.ok('Bundle ' + destination.cyan + ' created. ' + (options.keepAlive ? 'Watchifying...' : ''));
self.writer.write(destination, buf);
e. g. grunt
output with similar config:
# from grunt-browserify with options.watch == true
>> /home/mov/dev/project/lib/mixins/property.coffee changed, updating bundle.
>> Bundle dist/lib.js created.
# from grunt-contrib-watch
>> File "dist/lib.js" changed.
Completed in 0.000s at Wed Apr 06 2016 21:00:36 GMT+0500 (YEKT) - Waiting...
String >> <file> changed, updating bundle
is inserted here. It's reaction on update
event from watchify.
By the way it works well with persistent cache in my project.
And in my project with similarly configuration, the first build via grunt-browserify
lasts about 15 seconds, further bundle updating takes few milliseconds. With persistent cache for browserify, duration of the first build is reduced to 3-4 seconds. Not sure that the presence or absence of the text Watchifying ...
in console output is important, when there is a performance.
To successfully build is necessary to set grunt-browserify
before grunt-contrib-watch
. Turn off keepAlive
, turn on watch
in the grunt-browserify
. Isolate source files, so that they are not used at the same time in different tasks. And don't include grunt-browserify
in grunt-contrib-watch
.
In this case, after completion of the first build, grunt-browserify
will remain in the background for monitoring changes in files and updating bundles (using watchify
) parallel with the grunt-contrib-watch
, which will keep alive the process.
ps: sorry for my English.
@ovcharik Sorry for the delay (was on holiday), turns out you are correct. The watch
option does work without the keepAlive
function. There is a dependency issue with watchify (browserify/watchify#260), so I had to manually install a watchify version prior to 3.3. After doing that, the watch
option started working properly and I was able to remove browserify from my grunt-contrib-watch
task (which I'm guessing negated the benefits of the watch
option). Subsequent builds are now in the miliseconds range, as you stated.
Thanks for your help, I owe you a beer!
ps: your English is fine 😄